Smart contracts for Superchain interoperability and RYLA standard credit primitives.
Operational procedures (deployment, incident, rollback) are documented in RUNBOOK.md. Pre-mainnet promotion criteria are documented in STAGING_GO_NO_GO_CHECKLIST.md.
- THREAT_MODEL.md — trust assumptions, role compromise impact, external dependencies
- KNOWN_ISSUES.md — accepted design decisions and known limitations
- Superchain-compatible ERC-7802 token (mint/burn on bridge is enforced by
SuperchainTokenBridge) - Market symbol:
RYLA MINTER_ROLE/BURNER_ROLEfor protocol issuance modules- Uses
AccessControlDefaultAdminRulesfor delayed default-admin transfer hardening
- Operator-gated bridge-out adapter that routes through
SuperchainTokenBridge - Destination allowlist and optional
maxPerTx/dailyCaprisk limits - Keeps token core bridge authority on the canonical predeploy
- Uses
AccessControlDefaultAdminRules(OPERATOR_ROLE)
- Phase-2 integration boundary for UTXO / zk accounting
- Operator-gated settlement with replay protection (
intentId) - Optional external proof verifier hook (
IUTXOSettlementVerifier) - Holds token minter/burner roles for controlled mint and burn settlement
- Uses
AccessControlDefaultAdminRules(OPERATOR_ROLE)
- Signature-based settlement verifier (
ATTESTER_ROLEallowlist) - Intended as a concrete verifier baseline before integrating zk circuits
- Uses OZ
ECDSA+MessageHashUtils - Binds signed proofs to settlement module address (prevents cross-module replay)
- Proof format:
abi.encode(uint256 deadline, bytes32 contextHash, uint8 v, bytes32 r, bytes32 s)
- Groth16-based settlement verifier adapter for 13-signal proofs.
- Binds verifier usage to one
MARKSettlementModuleviasetSettlementModule(address). - Supports staged
isMintdirection enforcement:- default (migration mode):
signals[7]must be0 - strict mode:
signals[7]must beisMint ? 1 : 0
- default (migration mode):
- Strict mode is toggled by
setDirectionEnforcementEnabled(bool).
Note: legacy CrossChainCounter example contracts and tests were retired in favor of MARK protocol deployment/ops flows. Current CI and release gates focus on MARK stack contracts and governance evidence artifacts.
forge installforge buildforge testRun the fast local CI checks (recommended during iteration):
make ci-fastRun the full local CI checks (includes explicit production-lock checks):
make ci-fullRun canonical release gate checks and emit a timestamped evidence artifact:
make release-gateFor remote/mainnet-style verification, run with:
RPC_URLandPRIVATE_KEY- anchored release artifact via
MARK_RELEASE_VERIFY_ARTIFACT_PATHorMARK_RELEASE_ARTIFACT_PATH - signed evidence verification inputs (default-on):
VERIFY_PUBLIC_KEY_FILEorVERIFY_PUBLIC_KEY_PEM- optional manifest path overrides:
MARK_RELEASE_VERIFY_MANIFEST_PATHMARK_RELEASE_VERIFY_SIGNATURE_PATHMARK_RELEASE_VERIFY_SIGNATURE_META_PATH
Set MARK_RELEASE_VERIFY_REQUIRE_SIGNED_MANIFEST=false only for controlled break-glass scenarios.
MARK_RELEASE_GATE_MODE=remote make release-gateRun integration (fork/RPC-dependent) tests only:
CHAIN_A_RPC_URL=http://127.0.0.1:9545 \
CHAIN_B_RPC_URL=http://127.0.0.1:9546 \
FOUNDRY_PROFILE=integration forge test --match-path 'test/integration/**/*.t.sol'Deploy to multiple chains using either:
- Super CLI (recommended):
cd ../ && pnpm sup- Direct Forge script (MARK stack):
set -a && source .env && set +a
forge script script/deploy/bridge/DeployMARKStack.s.sol --rpc-url $RPC_URL --broadcastDeploy RYLA stack:
set -a && source .env && set +a
forge script script/deploy/bridge/DeployMARKStack.s.sol --rpc-url $RPC_URL --broadcastDeploy settlement module:
set -a && source .env && set +a
forge script script/deploy/settlement/DeployMARKSettlementModule.s.sol --rpc-url $RPC_URL --broadcastDeploy settlement module with in-script attested verifier:
set -a && source .env && set +a
forge script script/deploy/settlement/DeployMARKSettlementModule.s.sol --rpc-url $RPC_URL --broadcastApply deterministic role/config setup on already deployed contracts:
set -a && source .env && set +a
forge script script/ops/settlement/PostDeployMARKSetup.s.sol --rpc-url $RPC_URL --broadcastRun read-only checks to validate env wiring and admin permissions before deployment/setup:
set -a && source .env && set +a
forge script script/ops/settlement/PreflightMARKDeployment.s.sol --rpc-url $RPC_URLMARK_PREFLIGHT_MODE values:
1=> checks forDeployMARKStack.s.sol2=> checks forDeployMARKSettlementModule.s.sol3=> checks forPostDeployMARKSetup.s.sol
Run full release pipeline (preflight -> deploy -> optional setup -> verify -> artifact):
set -a && source .env && set +a
forge script script/ops/settlement/ReleaseMARK.s.sol --rpc-url $RPC_URLLocal production-mode smoke (starts Anvil, deploys verifier, runs strict release verify):
make smoke-production-modeControl behavior with:
MARK_RELEASE_EXECUTE=falsefor dry-run (no broadcast)MARK_RELEASE_EXECUTE=truefor executionMARK_RELEASE_RUN_POSTDEPLOY=trueto runPostDeployMARKSetupafter deploymentMARK_RELEASE_WRITE_ARTIFACT=trueto write JSON artifact (requires Foundry FS write permission)MARK_RELEASE_ARTIFACT_PATHfor JSON output pathMARK_GIT_COMMITto tag artifact with commit idMARK_RELEASE_STRICT_VERIFY=trueto require explicitVERIFY_MARK_SETTLEMENT_*expectations during execute-mode verifyMARK_SETTLEMENT_PRODUCTION_MODE=trueto lock settlement verifier/proof validation configuration in productionMARK_SETTLEMENT_GROTH16_DIRECTION_ENFORCEMENT=true|falseto control Groth16 strict direction binding during deploy/setup
Use this sequence when MARK_SETTLEMENT_VERIFIER points to Groth16SettlementVerifier:
- Deploy/setup with migration-compatible mode:
MARK_SETTLEMENT_GROTH16_DIRECTION_ENFORCEMENT=false- This keeps legacy proof mapping (
signals[7] == 0) valid.
- Upgrade proof generation so
signals[7]encodes direction:- mint:
1 - burn:
0
- mint:
- Re-run staging tests and post-deploy verify.
- Enable strict mode:
MARK_SETTLEMENT_GROTH16_DIRECTION_ENFORCEMENT=true
- Only then activate settlement production mode.
Run the full pre-mainnet gate in one command:
RPC_URL=<target_rpc> \
PRIVATE_KEY=<deployer_pk> \
./script/ops/mainnet-readiness.shGate mode is controlled by MARK_MAINNET_GATE_MODE:
predeploy(default): tests + slither + preflight + dry-run artifactpostdeploy: verify-only checks against deployed contractsfull: predeploy checks + postdeploy verify + dry-run artifact
This gate enforces (by mode):
- contract tests pass
- slither scan pass
- preflight pass (all modes)
- deployment verify pass
- release artifact generation + schema validation
Manual CI entrypoint:
.github/workflows/contracts-mainnet-readiness.yml(workflow_dispatch)
Run read-only checks against deployed contracts and role wiring:
set -a && source .env && set +a
forge script script/ops/settlement/VerifyMARKDeployment.s.sol --rpc-url $RPC_URLOptional strict checks supported by verify script:
VERIFY_MARK_BRIDGE_MAX_PER_TX/VERIFY_MARK_BRIDGE_DAILY_CAP- Verifier admin check via
VERIFY_MARK_RYLA_OWNERwhenVERIFY_MARK_SETTLEMENT_VERIFIERis set - Verifier attester check via
VERIFY_MARK_SETTLEMENT_ATTESTER - Settlement production lock expectation via
VERIFY_MARK_SETTLEMENT_PRODUCTION_MODE
Run production lock post-deploy assurance (read-only checks):
set -a && source .env && set +a
make verify-production-lockManual CI entrypoint for post-deploy production checks:
.github/workflows/contracts-production-lock-verify.yml(workflow_dispatch)
Dispatch helper (auto-fills workflow inputs from env/artifact):
set -a && source .env && set +a
make dispatch-production-lock-verifyBy default this is dry-run only. To actually dispatch:
set -a && source .env && set +a
DISPATCH_EXECUTE=true make dispatch-production-lock-verifyDispatch full evidence sequence (staging rehearsal -> mainnet readiness -> promotion checklist):
STAGING_RPC_URL=<staging_rpc> \
STAGING_SETTLEMENT_OPERATOR=<0x_operator> \
MAINNET_RPC_URL=<mainnet_rpc> \
DISPATCH_EXECUTE=true \
WAIT_FOR_COMPLETION=true \
make dispatch-release-evidence-sequenceNotes:
- dispatcher resolves run IDs using
workflow_dispatch+ actor + branch + dispatch timestamp filters (safer under concurrent runs) - production dispatch/verify paths enforce
MARK_ENV_STRICT_PLACEHOLDERS=trueto block known placeholder addresses
Required GitHub secrets for this sequence:
MARK_STAGING_DEPLOYER_PRIVATE_KEYMARK_DEPLOYER_PRIVATE_KEY
Bootstrap those secrets from local env values (dry-run by default):
MARK_STAGING_DEPLOYER_PRIVATE_KEY=<0x_staging_pk> \
MARK_DEPLOYER_PRIVATE_KEY=<0x_mainnet_pk> \
DISPATCH_EXECUTE=true \
make bootstrap-release-secretsStaging rehearsal (release + production-lock verify):
set -a && source .env && set +a
make rehearse-production-lockManual CI entrypoint for staging rehearsal:
.github/workflows/contracts-staging-rehearsal.yml(workflow_dispatch)
Promotion checklist generator (links latest successful staging rehearsal + mainnet readiness):
make generate-promotion-checklistPolicy defaults:
- freshness window:
72hours (FRESHNESS_HOURS) - lineage: mainnet commit must be
identicaloraheadvs staging commit - strict mode: fails command/workflow when any check fails (
STRICT_PROMOTION_CHECKS=true)
Manual CI entrypoint:
.github/workflows/contracts-promotion-checklist.yml(workflow_dispatch)
Environment safety precheck utility:
VALIDATE_MODE=rehearsal make validate-prod-envSupported modes:
rehearsaldispatchverify-lock
Canonical env profiles:
config/profiles/staging.envconfig/profiles/mainnet.env
CI env schema guard entrypoint:
.github/workflows/contracts-env-guard.yml
Evidence manifest tooling:
make generate-evidence-manifest
make verify-evidence-manifest
make sign-evidence-manifest
make verify-evidence-signatureCI/manual entrypoint:
.github/workflows/contracts-evidence-manifest.yml
- Copy
.env.exampleto.envand fill all required deploy/verify values. - Use MARK-prefixed keys (
MARK_*,VERIFY_MARK_*) for all deploy and verify scripts. - Network-specific templates are in:
config/networks/optimism-mainnet.env.exampleconfig/networks/optimism-sepolia.env.example
All RYLA contracts use AccessControlDefaultAdminRules with a 1-day admin delay.
# Examples via cast:
# cast send <RYLA> "setMinter(address,bool)" <module> true --private-key $PK
# cast send <RYLA> "setBurner(address,bool)" <module> true --private-key $PK
# cast send <BRIDGE_ADAPTER> "setOperator(address,bool)" <operator> true --private-key $PK
# cast send <SETTLEMENT_MODULE> "setOperator(address,bool)" <operator> true --private-key $PK
# cast send <ATTESTED_VERIFIER> "setAttester(address,bool)" <attester> true --private-key $PKStep 1: current admin starts transfer
# cast send <CONTRACT> "beginDefaultAdminTransfer(address)" <newAdmin> --private-key $OLD_ADMIN_PKStep 2: wait at least defaultAdminDelay() (1 day)
Step 3: new admin accepts transfer
# cast send <CONTRACT> "acceptDefaultAdminTransfer()" --private-key $NEW_ADMIN_PKOptional: cancel pending transfer before acceptance
# cast send <CONTRACT> "cancelDefaultAdminTransfer()" --private-key $OLD_ADMIN_PK- Operators submit settlement intents through
MARKSettlementModule. - Optional verifier (
AttestedSettlementVerifieror customIUTXOSettlementVerifier) validates intent proof material. - Settlement module mints/burns
RYLAunder role-constrained rules. - Bridge adapter enforces destination/risk controls for cross-chain transfers.
Tests are in test/ directory:
- Unit tests for token/protocol/verifier and deploy scripts
- Invariant tests for settlement supply and authorization safety
- Integration tests (in
test/integration/) are isolated from default runs
forge testRun Slither locally on MARK core contracts:
cd contracts
make slither-install
export PATH="$HOME/Library/Python/3.9/bin:$PATH"
make slither-coreCI workflow:
.github/workflows/contracts-slither.yml
MIT