CONFIG.md — sail.toml Schema & Project Layout¶
Living reference for the project configuration file and the tree produced by
sun init. Tier-1 authority remains docs/ARCHITECTURE.md; this file documents
the concrete schema implemented in internal/config and the templates in
assets/templates/.
sail.toml¶
sail.toml is decoded with strict validation (github.com/pelletier/go-toml/v2,
DisallowUnknownFields). Any key not in the schema is an error, reported with
its line number — e.g. sail.toml:8: unknown key "networks.nile.typo". Type
mismatches are reported the same way (sail.toml:3: cannot decode …). Typos never
pass silently.
TOML structure note: top-level keys (
remappings) must appear before any[table]header. Once a table header opens, subsequent bare keys belong to that table.
Sections¶
| Key | Type | Required | Description |
|---|---|---|---|
remappings |
[]string |
no | Foundry-style import remappings, forwarded to solc's settings.remappings. |
[solc] version |
string |
yes | The pinned solc-tron release, e.g. "0.8.23". |
[solc.checksums] |
table<str,str> |
no¹ | SHA-256 hex digest of the solc-tron binary per platform, keyed by "<goos>/<goarch>". |
[aderyn] version |
string |
no³ | The pinned Cyfrin aderyn release run by sun audit, e.g. "0.6.8". |
[aderyn.checksums] |
table<str,str> |
no³ | SHA-256 hex digest of the extracted aderyn binary per platform, keyed by "<goos>/<goarch>". |
[networks.<name>] fullnode |
string |
yes² | host:port of the FullNode (protocol.Wallet) gRPC service — broadcast + unsolidified reads. |
[networks.<name>] solidity |
string |
yes² | host:port of the Solidity (protocol.WalletSolidity) gRPC service — solidified confirmation. |
[profiles.<name>] solc_version |
string |
no | Overrides solc.version when the profile is active (applied in a later sprint). |
[profiles.<name>] remappings |
[]string |
no | Overrides the top-level remappings when the profile is active (applied in a later sprint). |
¹ Checksums — sun compile downloads the pinned solc-tron release asset and
requires and verifies the host platform's digest before ever executing the
binary (ARCHITECTURE §1.5); a platform without a pinned digest cannot compile.
The scaffolded template pins the official tv_0.8.23 digests (the darwin asset
is a universal x86_64+arm64 binary, so both darwin keys share one digest; no
linux/arm64 asset is published upstream). See docs/COMPILER.md for the full
binary-management contract.
³ Aderyn — optional; only sun audit consumes it, under the same rule as
solc: no digest for the host platform, no execution (§1.5). The release ships
tar.xz archives, so the pinned digest is that of the extracted binary.
Upstream publishes no Windows asset — sun audit reports that explicitly on
Windows. See docs/AUDIT.md.
² Networks — if a [networks.<name>] table is declared, it must carry both
fullnode and solidity. SunSail opens one ClientConn per (network, service)
and never multiplexes the two services onto a single connection (ARCHITECTURE §5.7):
broadcast always goes to the FullNode Wallet service; solidified confirmation to
the WalletSolidity service. The <name> is free-form (mainnet, nile, or a
custom network); the scaffolded default declares mainnet and nile. The optional
jsonrpc key is the node's JSON-RPC HTTP endpoint, consumed ONLY by the fork
storage reader (sun test --fork-url) — java-tron exposes no contract-storage
read over gRPC (ARCHITECTURE Erratum E2, docs/FORKING.md); everything else
stays gRPC-only.
Default endpoints (scaffolded)¶
| Network | FullNode (fullnode) |
Solidity (solidity) |
JSON-RPC (jsonrpc) |
|---|---|---|---|
mainnet |
grpc.trongrid.io:50051 |
grpc.trongrid.io:50052 |
https://api.trongrid.io/jsonrpc |
nile |
grpc.nile.trongrid.io:50051 |
grpc.nile.trongrid.io:50061 |
https://nile.trongrid.io/jsonrpc |
Example¶
remappings = ["@openzeppelin/=lib/openzeppelin-contracts/"]
[solc]
version = "0.8.23"
[solc.checksums]
"linux/amd64" = "<sha256-hex>"
[networks.mainnet]
fullnode = "grpc.trongrid.io:50051"
solidity = "grpc.trongrid.io:50052"
[networks.nile]
fullnode = "grpc.nile.trongrid.io:50051"
solidity = "grpc.nile.trongrid.io:50061"
Project layout (sun init)¶
sun init [name] materializes a Foundry-like project from the binary's embedded
templates (no satellite files). With no name it initializes the current directory;
with a name it creates that subdirectory. A non-empty destination is refused
unless --force is given; under --force the operation is idempotent (template
files are overwritten, yielding the same tree).
<project>/
├── .gitignore # ignores /out/ (build output)
├── sail.toml # project config (two networks, pinned solc)
├── lib/ # third-party sources (git submodules / vendored)
│ └── .gitkeep # keeps the empty dir under version control
├── out/ # build output — created here, gitignored, filled by `sun compile`
├── src/
│ └── Counter.sol # example contract
├── test/
│ └── Counter.t.sol # example test (plain require; cheatcodes arrive in a later sprint)
└── script/
└── Deploy.s.sol # example deployment script
out/is the build-output directory. It is created at init so the layout is complete, and the scaffolded.gitignoreignores it — build artifacts are never committed.sun compile(Sprint 2) populates it.lib/carries a.gitkeepso the (otherwise empty) directory survivesgit addin the user's project.embed.FScannot carry empty directories, so the scaffolder createsout/explicitly whilelib/.gitkeeprides along in the embed.- The example
.solfiles are static assets (no name interpolation), which keeps the scaffolded tree deterministic and byte-identical to the embedded templates — the property the e2e golden test asserts. They compile with plain solc in Sprint 2.