The .github/workflows/contracts-ci.yml workflow compiles, lints, and tests
every contract in contracts/* independently. It is triggered on any push or
pull request that modifies a file under contracts/ or the root Cargo.toml /
Cargo.lock.
Runs cargo check --workspace --locked on both Ubuntu and macOS. This job is
the fast sanity gate for workspace-wide resolution and catches cross-crate
breakage before the per-contract matrix fans out.
Runs on ubuntu-latest for each contract listed in the matrix:
| Step | Command | Purpose |
|---|---|---|
| Check | cargo check -p <contract> |
Fast type-check; catches import and type errors |
| Lint | cargo clippy -p <contract> -- -D warnings |
Enforce Clippy lints as errors |
| Test | cargo test -p <contract> |
Run unit and integration tests |
fail-fast: false is set so every contract is evaluated even when one fails —
this surfaces all regressions in a single CI run.
Builds a subset of contracts to wasm32-unknown-unknown --release. Only
contracts whose [dependencies] section does not include
soroban-sdk = { features = ["testutils"] } are listed here; the testutils
feature pulls in std-only code that cannot be compiled for WASM.
The step also prints the size of the resulting .wasm file.
The contracts that explicitly require the wasm32-unknown-unknown target in
CI are:
flashloan-tokengovernance-contractkani-poc-contractuups-proxyreentrancy-guardtimelocktoken-with-bugsvulnerable-contract
- Add the crate to
[workspace.members]in the rootCargo.toml. - Add the crate package name (as declared in the contract's
Cargo.toml) to thecontract-checkmatrix in.github/workflows/contracts-ci.yml. - If the contract's production dependencies do not include
testutils, also add it to thecontract-wasmmatrix. - Add a WASM size budget entry to
contracts/benchmark/src/budgets.rsandscripts/build-contracts.sh.
scripts/build-contracts.sh produces reproducible WASM binaries by:
- Pinning
SOURCE_DATE_EPOCHto the latest git commit timestamp. - Fixing
RUSTFLAGSto-C opt-level=z -C lto=fat -C codegen-units=1. - Enforcing the minimum Rust version declared in
[workspace.package].
Run with --check in CI to additionally validate WASM binary sizes against the
budgets in contracts/benchmark/src/budgets.rs.
Size budgets are defined in two places (kept in sync manually):
contracts/benchmark/src/budgets.rs— Rust constants, referenced in benchmark tests and CI commentary.scripts/build-contracts.sh— shelldeclare -Atable used by the size-check logic.
CPU instruction ceilings are documented in contracts/benchmark/src/budgets.rs
and enforced implicitly: if an operation exceeds the Soroban host's default
budget the test panics.
The CI matrix hardens the contracts/* area in the following ways:
| Threat | Mitigation |
|---|---|
| Broken contract silently merged | contract-check job fails the PR |
| Clippy regression | -D warnings promotes warnings to errors |
| WASM size bloat (hidden feature creep) | contract-wasm reports sizes; --check blocks merges |
| Non-deterministic WASM output | build-contracts.sh fixes SOURCE_DATE_EPOCH + RUSTFLAGS |
| CPU/memory regression (exceeds Soroban budget) | Benchmark tests in contracts/benchmark catch this |
| Untested code path merged | Matrix runs cargo test for every contract independently |