Background / Context
Per the README, all three deployed testnet contracts share a single admin/treasury address (GBUXADZJ7O4NM7S7CDZYVXGP37M772D2TYMFBT2QFH2JSRCFEJPAVW5N), and mergefi-backend is expected to hold this admin keypair and sign release/refund/allocate/release_issue/withdraw/cancel_milestone calls across potentially multiple deployed instances (the README notes escrow/milestones/maintenance-pool "can share one admin key or use separate ones per environment"). None of the three contracts implement any custom __check_auth logic — they rely entirely on Soroban's built-in Address::require_auth()/authorization framework.
Problem Statement
This is a research task to rigorously verify (not assume) that Soroban's standard authorization framework provides adequate replay protection in this specific multi-contract, potentially multi-network, shared-admin-key deployment shape. Specific questions to resolve: does Soroban's built-in auth-entry nonce/signature-expiration scheme bind an authorized invocation to a specific contract address and network passphrase such that a valid signed authorization for, say, mergefi-escrow's release call could never be replayed against mergefi-milestones' release_issue (different function, but confirm the binding is to more than just "this admin's signature" generically) or against the same contract redeployed at a new address (e.g., after an upgrade, if the upgrade-mechanism work lands) or on a different network (testnet signature replayed on a future mainnet deployment using the same admin keypair, if the team reuses keys across environments contrary to the "separate ones per environment" README caveat)? What is the actual nonce/expiration-ledger window behavior for a standard require_auth() call with no custom auth contract, and what operational practices (e.g., never reusing the same keypair as admin across testnet and mainnet, regardless of what the contract enforces) does this imply mergefi-backend's deployment procedure should follow?
Requirements
- Study Soroban's authorization framework internals (the
SorobanAuthorizationEntry structure, its binding to network id, contract address, function name/args, and nonce/signature-expiration-ledger fields) directly from the Soroban protocol/host source or official specification, not secondhand summaries.
- Produce concrete test scenarios (to the extent they're constructible in
testutils::Env, which may have limits on simulating true multi-network/multi-deployment auth-entry replay — document what can and can't be empirically tested in the current test harness vs. what must be reasoned about from the specification alone) demonstrating the actual replay-safety boundaries.
- Deliver a clear, actionable write-up: what Soroban's framework guarantees for free (contract-address and network binding, if confirmed), what it does not guarantee (anything cross-function within the same admin's authority, if that's found to be a gap), and what operational safeguards (key-per-environment policy, key rotation cadence)
mergefi-backend's deployment runbook should therefore enforce, given no contract code change may be able to fix a pure operational-key-reuse risk.
- If any genuine contract-level gap is found (not just an operational recommendation), file it as a precise, separate follow-up issue with a reproducing scenario, and implement a fix here if straightforward.
Acceptance Criteria
Technical Notes / Hints
- Relevant primitive: every privileged call in this codebase uses the plain pattern
require_admin(&env)?.require_auth() with no custom __check_auth/CustomAccountInterface — the analysis is entirely about the guarantees of Soroban's default account-based authorization for a classic (non-contract) admin address, which is very likely what's actually deployed per the README's G...-prefixed admin address.
soroban_sdk::testutils::Address as _/Ledger and the env.mock_all_auths() shortcut used throughout the existing test suite deliberately bypasses real auth-entry construction — this research task requires looking past that shortcut to the real signed-authorization-entry mechanics.
Difficulty Justification
This demands genuinely specialized knowledge of Soroban's authorization/signature-binding internals that goes well beyond what's exercised by this repo's existing mock_all_auths()-based tests, careful primary-source research rather than assumption or analogy from other chains, and the judgment to correctly separate "the protocol guarantees this" from "this needs an operational policy because the protocol can't prevent it" — exactly the kind of ambiguous, investigation-first task a spike is for.
Background / Context
Per the README, all three deployed testnet contracts share a single admin/treasury address (
GBUXADZJ7O4NM7S7CDZYVXGP37M772D2TYMFBT2QFH2JSRCFEJPAVW5N), andmergefi-backendis expected to hold this admin keypair and signrelease/refund/allocate/release_issue/withdraw/cancel_milestonecalls across potentially multiple deployed instances (the README notes escrow/milestones/maintenance-pool "can share one admin key or use separate ones per environment"). None of the three contracts implement any custom__check_authlogic — they rely entirely on Soroban's built-inAddress::require_auth()/authorization framework.Problem Statement
This is a research task to rigorously verify (not assume) that Soroban's standard authorization framework provides adequate replay protection in this specific multi-contract, potentially multi-network, shared-admin-key deployment shape. Specific questions to resolve: does Soroban's built-in auth-entry nonce/signature-expiration scheme bind an authorized invocation to a specific contract address and network passphrase such that a valid signed authorization for, say,
mergefi-escrow'sreleasecall could never be replayed againstmergefi-milestones'release_issue(different function, but confirm the binding is to more than just "this admin's signature" generically) or against the same contract redeployed at a new address (e.g., after an upgrade, if the upgrade-mechanism work lands) or on a different network (testnet signature replayed on a future mainnet deployment using the same admin keypair, if the team reuses keys across environments contrary to the "separate ones per environment" README caveat)? What is the actual nonce/expiration-ledger window behavior for a standardrequire_auth()call with no custom auth contract, and what operational practices (e.g., never reusing the same keypair as admin across testnet and mainnet, regardless of what the contract enforces) does this implymergefi-backend's deployment procedure should follow?Requirements
SorobanAuthorizationEntrystructure, its binding to network id, contract address, function name/args, and nonce/signature-expiration-ledger fields) directly from the Soroban protocol/host source or official specification, not secondhand summaries.testutils::Env, which may have limits on simulating true multi-network/multi-deployment auth-entry replay — document what can and can't be empirically tested in the current test harness vs. what must be reasoned about from the specification alone) demonstrating the actual replay-safety boundaries.mergefi-backend's deployment runbook should therefore enforce, given no contract code change may be able to fix a pure operational-key-reuse risk.Acceptance Criteria
SorobanAuthorizationEntrybinding guarantees, sourced from primary Soroban documentation/specificationtestutils::Env, with clear notes on what isn'tmergefi-backend's key-management practicesTechnical Notes / Hints
require_admin(&env)?.require_auth()with no custom__check_auth/CustomAccountInterface— the analysis is entirely about the guarantees of Soroban's default account-based authorization for a classic (non-contract) admin address, which is very likely what's actually deployed per the README'sG...-prefixed admin address.soroban_sdk::testutils::Address as _/Ledgerand theenv.mock_all_auths()shortcut used throughout the existing test suite deliberately bypasses real auth-entry construction — this research task requires looking past that shortcut to the real signed-authorization-entry mechanics.Difficulty Justification
This demands genuinely specialized knowledge of Soroban's authorization/signature-binding internals that goes well beyond what's exercised by this repo's existing
mock_all_auths()-based tests, careful primary-source research rather than assumption or analogy from other chains, and the judgment to correctly separate "the protocol guarantees this" from "this needs an operational policy because the protocol can't prevent it" — exactly the kind of ambiguous, investigation-first task a spike is for.