diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f509e8b..e39e75eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,22 +75,10 @@ jobs: with: fetch-depth: 0 - - name: Require a contract version bump when lib.rs changes + - name: Contract changes use a fragment, not a version bump if: github.event_name == 'pull_request' working-directory: . - run: | - if git diff --quiet "origin/${{ github.base_ref }}...HEAD" -- contracts/escrow/src/lib.rs; then - exit 0 - fi - - base_version=$(git show "origin/${{ github.base_ref }}:contracts/escrow/src/lib.rs" \ - | sed -nE 's/^pub const CONTRACT_VERSION: &str = "([^"]+)";/\1/p') - head_version=$(sed -nE 's/^pub const CONTRACT_VERSION: &str = "([^"]+)";/\1/p' \ - contracts/escrow/src/lib.rs) - if [ -z "$head_version" ] || { [ -n "$base_version" ] && [ "$base_version" = "$head_version" ]; }; then - echo "contracts/escrow/src/lib.rs changed without a CONTRACT_VERSION bump" >&2 - exit 1 - fi + run: node scripts/check-contract-change.mjs "origin/${{ github.base_ref }}" - name: Install Rust toolchain uses: dtolnay/rust-toolchain@1.96.0 diff --git a/AGENTS.md b/AGENTS.md index 759854ae..86892e45 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,6 +12,11 @@ the change belongs in `docforum-core` instead, not here. - No PHI. No healthcare domain concepts (patient, doctor, referral, etc.) anywhere in this repo — see `ARCHITECTURE_ESSENTIALS.md` hard rule 1. - Contract changes need contract tests in the same PR, always. +- Never edit `CONTRACT_VERSION` or renumber an `Error` code. A PR that + changes `contracts/escrow/src/lib.rs` adds a fragment under + `contract-changes.d/`, and new `Error` variants use a provisional code + (issue number × 100 + n). A maintainer bumps the version and assigns final + codes. See `contract-changes.d/README.md`; CI enforces it. - Testnet only, per `ARCHITECTURE_ESSENTIALS.md` hard rule 4, until an explicit security-review milestone (ROADMAP.md Phase E4) is marked done. - Update `ROADMAP.md` on every contribution — org-wide rule, applies here diff --git a/ARCHITECTURE_ESSENTIALS.md b/ARCHITECTURE_ESSENTIALS.md index d226da84..4bc3d1e8 100644 --- a/ARCHITECTURE_ESSENTIALS.md +++ b/ARCHITECTURE_ESSENTIALS.md @@ -26,6 +26,7 @@ refund(escrow_id, caller) -> result // IMPLEMENTED (Phase E2 + E4) — a rele refund_with_approvals(escrow_id, approvers) -> result // IMPLEMENTED (Phase E5, issue #119) — same approval rules as release_with_approvals settle_many(caller, ops: Vec<(escrow_id, Release|Refund)>) -> Vec> // IMPLEMENTED (Phase E5, issue #29, ADR 0012) — caller authorizes once; each op gets exactly the checks of release/refund against that escrow's own releasers; best-effort, one result per op in input order (Err = untouched; same escrow twice → second NotFunded); a post-transfer failure (payee callback) reverts the whole batch; at most MAX_SETTLE_OPS = 20 (BatchTooLarge); not deployed on testnet yet top_up(escrow_id, payer, amount) -> result // IMPLEMENTED (issue #26) — original payer only, funded state only; emits `top_up` +transfer_payee(escrow_id, current_payee, new_payee) -> result // IMPLEMENTED (Phase E5, issue #45) — current payee only, funded state only; new_payee may not be the contract address or the payer; rotation tool, not key-loss recovery create_pooled_escrow(creator, payee, token, funding_target, condition_ref, releaser, funding_deadline) -> escrow_id // IMPLEMENTED (Phase E5, issue #113, ADR 0011) — pooled escrow; amount starts at 0, `funding_target` > 0 and a strictly-future `funding_deadline` are fixed at creation; not deployed on testnet yet contribute(escrow_id, payer, amount) -> () // IMPLEMENTED (issue #113) — permissionless before the deadline, up to the target only; balance-delta verified (`transfer_in_exact`) and recorded per payer, accumulating across repeats claim_refund(escrow_id, contributor) -> () // IMPLEMENTED (issue #113) — pull-based refund, contributor's own auth, only from a failed round (deadline passed, target unmet), pays exactly the recorded amount once (`AlreadyRefunded` after) @@ -339,3 +340,4 @@ quickstart deployment. ## Roadmap / status See `ROADMAP.md` in this repo. Live testnet deployment record: `docs/testnet-deployments.md`. +A failed outbound token transfer during release returns `Undeliverable` and preserves the funded record, allowing the releaser to retry or use the refund path. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 84fa1dd4..a57fa7e6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,6 +72,12 @@ verification/release-engineering tracks. entry as a new file in `changelog.d/`, in the same PR. Don't append to the end of `ROADMAP.md`; that is what made every PR conflict. See `changelog.d/README.md`. +- If you change the contract (`contracts/escrow/src/lib.rs`), add a fragment + under `contract-changes.d/` with the bump level and a one-line summary. + **Don't edit `CONTRACT_VERSION`**: a maintainer bumps it once per batch. + New `Error` variants use a provisional code (your issue number × 100 + n); + never renumber or remove an existing one. CI checks all three. See + `contract-changes.d/README.md`. - Changes to escrow lifecycle semantics must also update the TLA+ specification under `spec/` and rerun TLC. That includes changes to settlement auth, status transitions, timeouts, payee acceptance, diff --git a/ROADMAP.md b/ROADMAP.md index 6b7b1fc6..70f15e9a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -165,6 +165,7 @@ An opt-in creation method can require the payee to authorize `accept` before rel - [x] Per-token liability accounting and an on-chain solvency view (issue #39): `solvency(token) -> (balance, liabilities)`; the counter moves in the same invocation as every value-moving state change and its TTL is extended on each write. Property test: `contracts/escrow/tests/liabilities.rs`. Monitoring guidance in `docs/threat-model.md`. **Not yet on testnet.** - [x] Optional escrow-wide earliest release time (issue #43, ADR 0009); refund path remains independent. - [x] Two-party releaser rotation (issue #23): current releaser and payer authorize; only funded single-releaser escrows can rotate. Contract and payee addresses are rejected. +- [x] Undeliverable payee handling (issue #55): a rejected outbound release transfer (deauthorised SAC trustline, rejecting contract payee) returns append-only `Error::Undeliverable = 35` and leaves the escrow `Funded`, so the releaser can retry or refund. Tests: `tests/undeliverable.rs`. - [x] **OpenZeppelin Stellar library evaluation** (issue #118) — `docs/adr/0006`: all six candidate modules checked against ADR 0001/0002 @@ -274,6 +275,25 @@ An opt-in creation method can require the payee to authorize `accept` before rel (scenarios A–M) + 3 malicious-token contribution tests; existing suites and snapshots unchanged. SDK `0.7.0 → 0.8.0` (additive). **Not yet on testnet** — the live deployment predates it. + +- [x] Payee rights transfer (issue #45): `transfer_payee(escrow_id, + current_payee, new_payee)` lets the current payee reassign the release + destination to a new address while the escrow is `Funded`. Only the + current payee may authorise this call — the payer and releaser have no + power to redirect funds via this path. `new_payee` may not be the + contract's own address (would permanently lock funds) or the payer + (would let a colluding payee redirect a release to the payer, bypassing + refund auth). Emits a `pay_xfer` event. This is a rotation tool: a + payee who has already lost their key cannot use it (they cannot sign). + Key loss remains an operational risk the payee must mitigate off-chain. + 12 tests in `contracts/escrow/tests/transfer_payee.rs` covering the + happy path, release/refund after transfer, chained transfers, + auth rejection for stranger/payer/releaser, and both rejected + `new_payee` targets. Rejected with `Error::InvalidNewPayee`. + Threat model + I1 updated; T11 added covering the new payee-key attack surface. + `ARCHITECTURE_ESSENTIALS.md` contract surface updated. + Closes issue #45. ## Phase E6 — SDK & integrator tooling - [x] Escrow lifecycle snapshots and a configurable SubQuery indexer with a typed, paginated SDK query client (issue #87). Operators provide the deployed contract and starting ledger; no hosted indexer is assumed. - [x] Automated npm release workflow (`.github/workflows/release-sdk.yml`), @@ -928,3 +948,69 @@ An opt-in creation method can require the payee to authorize `accept` before rel `scripts/test_settle_outcomes.py` run by a new CI job. The 50+ escrow testnet drill is still to be run and recorded in the runbook. No contract or SDK change. +- 2026-10-27 — Issue #29 (Phase E5): batch release and refund. `settle_many` now takes + `ops: Vec<(escrow_id, SettleAction)>` (`Release` | `Refund`) instead of + release-only `escrow_ids`, and `caller` authorizes the batch once (the + old version called `release` per id, so any batch of two or more failed + `Error(Auth, ExistingValue)`). Each op runs exactly the checks of + `release`/`refund` against that escrow's own releaser set, shared through + `release_checks`/`refund_checks` so the paths can't diverge. Best-effort, + decided in `docs/adr/0012`: one result per op in input order, `Err` means + untouched, the same escrow twice gives `NotFunded` on the second op, and + a failure after an op's transfer (a failing payee callback) reverts the + whole batch. Bound `MAX_SETTLE_OPS` = 20, measured: 656 bytes of events + per release against the 16,384-byte events budget (13,120 at 20). + Existing error codes unchanged (`BatchTooLarge` = 25 reused). T1 + response guidance in `docs/threat-model.md`. 13 tests in + `tests/settle_many.rs`. Bindings regenerated (SDK patch). Not yet + deployed to testnet. +- 2026-10-27 — Issue #30 (Phase E5): optional protocol fee taken at release. `create_escrow` + (and `create_escrow_release_time`) accept an optional `fee_recipient`/`fee_bps` + pair, fixed at creation, capped at 10 % and floor-rounded; `release` pays that + share to `fee_recipient` and the exact remainder to the payee, while refunds + still return the full amount. `get_escrow` exposes the pair, the `ESCROW` + event snapshot appends it as one nested pair, and `top_up` re-checks the fee + math as the amount grows. Decided in `docs/adr/0010`; new invariant I7 in the + threat model; new append-only error `InvalidFee = 35`. The SDK gains + `feeRecipient`/`feeBps` on `createEscrow` (minor changeset) and regenerated + bindings. Not yet redeployed to testnet. +- 2026-10-27 — Issue #39 (Phase E5): per-token liability accounting and an on-chain + solvency view. New read-only `solvency(token) -> (balance, liabilities)`; + `liabilities` is the sum of `amount` over every `Funded` escrow in that + token, kept in a new persistent `DataKey::Liability(token)` entry + (appended last, so existing storage encodings are unchanged) whose TTL is + re-extended on every write. The counter is increased in + `transfer_in_exact` (the single inbound path for every creation entry + point, `top_up` and `contribute`) and decreased in `settle()` and + `claim_refund`, always in the same invocation as the state change. + `tests/liabilities.rs`: 14 tests, including a proptest that runs random + sequences over every state-changing entry point and checks, after each + step, that liabilities equal the per-token sum of `Funded` amounts and the + contract balance. Monitoring guidance in `docs/threat-model.md`. Existing + test snapshots change only by the new `Liability` storage entry. SDK: + `client.getSolvency(token)` and regenerated bindings (minor). Not yet + deployed to testnet. +- 2026-10-27 — The SDK now publishes ESM and CommonJS builds with matching declarations and a browser-compatible ESM entry. CI smoke checks exercise Node imports and a browser bundle. +- 2026-10-27 — Phase E6 (issue #247): added multisig releaser setup helpers to the SDK. + `buildMultisigSetup` returns one atomic `setOptions` transaction (thresholds, + one operation per signer, master key weight zeroed last) and refuses any + configuration that would lock the account out; `dryRunMultisigSetup` and + `verifyMultisig` cover review and on-chain verification. Client-side only — no + contract change, so the generated bindings are unchanged. +- 2026-10-28 — Issue #55 (Phase E5): `release` now uses `try_transfer` for the payout. If the + token rejects the transfer (for example a SAC payee whose trustline was + deauthorised, or a contract payee that rejects the funds), the call returns the + new append-only `Error::Undeliverable = 35` and the escrow stays `Funded` with + its balance intact, so the releaser can retry once the payee is reachable or + use the refund path. Refund transfers are unchanged. Tests in + `contracts/escrow/tests/undeliverable.rs`; generated SDK bindings regenerated + for the new error code. +- 2026-10-28 — Contract changes now use fragments in `contract-changes.d/` instead of each + PR bumping `CONTRACT_VERSION`, which put every open contract PR into conflict + on each contract merge. New `Error` variants use provisional codes + (issue number × 100 + n) until the maintainer fold + (`scripts/fold-contract-changes.mjs`) bumps the version once per batch and + assigns final codes. CI's "Contract changes use a fragment, not a version + bump" step (`scripts/check-contract-change.mjs`) replaces the old + "Require a contract version bump" step. The version test now compares with + `CONTRACT_VERSION` instead of a literal. diff --git a/changelog.d/29-batch-settlement.md b/changelog.d/29-batch-settlement.md deleted file mode 100644 index 2a0b7763..00000000 --- a/changelog.d/29-batch-settlement.md +++ /dev/null @@ -1,16 +0,0 @@ -Issue #29 (Phase E5): batch release and refund. `settle_many` now takes -`ops: Vec<(escrow_id, SettleAction)>` (`Release` | `Refund`) instead of -release-only `escrow_ids`, and `caller` authorizes the batch once (the -old version called `release` per id, so any batch of two or more failed -`Error(Auth, ExistingValue)`). Each op runs exactly the checks of -`release`/`refund` against that escrow's own releaser set, shared through -`release_checks`/`refund_checks` so the paths can't diverge. Best-effort, -decided in `docs/adr/0012`: one result per op in input order, `Err` means -untouched, the same escrow twice gives `NotFunded` on the second op, and -a failure after an op's transfer (a failing payee callback) reverts the -whole batch. Bound `MAX_SETTLE_OPS` = 20, measured: 656 bytes of events -per release against the 16,384-byte events budget (13,120 at 20). -Existing error codes unchanged (`BatchTooLarge` = 25 reused). T1 -response guidance in `docs/threat-model.md`. 13 tests in -`tests/settle_many.rs`. Bindings regenerated (SDK patch). Not yet -deployed to testnet. diff --git a/changelog.d/30-protocol-fee-at-release.md b/changelog.d/30-protocol-fee-at-release.md deleted file mode 100644 index b4bdf1c7..00000000 --- a/changelog.d/30-protocol-fee-at-release.md +++ /dev/null @@ -1,10 +0,0 @@ -Issue #30 (Phase E5): optional protocol fee taken at release. `create_escrow` -(and `create_escrow_release_time`) accept an optional `fee_recipient`/`fee_bps` -pair, fixed at creation, capped at 10 % and floor-rounded; `release` pays that -share to `fee_recipient` and the exact remainder to the payee, while refunds -still return the full amount. `get_escrow` exposes the pair, the `ESCROW` -event snapshot appends it as one nested pair, and `top_up` re-checks the fee -math as the amount grows. Decided in `docs/adr/0010`; new invariant I7 in the -threat model; new append-only error `InvalidFee = 35`. The SDK gains -`feeRecipient`/`feeBps` on `createEscrow` (minor changeset) and regenerated -bindings. Not yet redeployed to testnet. diff --git a/changelog.d/39-per-token-liabilities.md b/changelog.d/39-per-token-liabilities.md deleted file mode 100644 index c3ef4de6..00000000 --- a/changelog.d/39-per-token-liabilities.md +++ /dev/null @@ -1,16 +0,0 @@ -Issue #39 (Phase E5): per-token liability accounting and an on-chain -solvency view. New read-only `solvency(token) -> (balance, liabilities)`; -`liabilities` is the sum of `amount` over every `Funded` escrow in that -token, kept in a new persistent `DataKey::Liability(token)` entry -(appended last, so existing storage encodings are unchanged) whose TTL is -re-extended on every write. The counter is increased in -`transfer_in_exact` (the single inbound path for every creation entry -point, `top_up` and `contribute`) and decreased in `settle()` and -`claim_refund`, always in the same invocation as the state change. -`tests/liabilities.rs`: 14 tests, including a proptest that runs random -sequences over every state-changing entry point and checks, after each -step, that liabilities equal the per-token sum of `Funded` amounts and the -contract balance. Monitoring guidance in `docs/threat-model.md`. Existing -test snapshots change only by the new `Liability` storage entry. SDK: -`client.getSolvency(token)` and regenerated bindings (minor). Not yet -deployed to testnet. diff --git a/changelog.d/45-payee-rights-transfer.md b/changelog.d/45-payee-rights-transfer.md new file mode 100644 index 00000000..daf0aab3 --- /dev/null +++ b/changelog.d/45-payee-rights-transfer.md @@ -0,0 +1 @@ +Issue #45 (Phase E5): added `transfer_payee(escrow_id, current_payee, new_payee)` — restricted to the current payee (require_auth), only while Funded; `new_payee` may not be the contract address or the payer. Rotation tool, not key-loss recovery. 12 tests in `contracts/escrow/tests/transfer_payee.rs`. New error `Error::InvalidNewPayee` (provisional code 4500, renumbered by the maintainer fold). Contract surface updated in `ARCHITECTURE_ESSENTIALS.md`; threat model I1 updated and T11 added. `CONTRACT_VERSION` is left for the maintainer fold, per `contract-changes.d/README.md`. diff --git a/changelog.d/65-dual-sdk-builds.md b/changelog.d/65-dual-sdk-builds.md deleted file mode 100644 index 18a1b021..00000000 --- a/changelog.d/65-dual-sdk-builds.md +++ /dev/null @@ -1 +0,0 @@ -The SDK now publishes ESM and CommonJS builds with matching declarations and a browser-compatible ESM entry. CI smoke checks exercise Node imports and a browser bundle. diff --git a/changelog.d/77-multisig-releaser-helpers.md b/changelog.d/77-multisig-releaser-helpers.md deleted file mode 100644 index c4f65347..00000000 --- a/changelog.d/77-multisig-releaser-helpers.md +++ /dev/null @@ -1,6 +0,0 @@ -Phase E6 (issue #247): added multisig releaser setup helpers to the SDK. -`buildMultisigSetup` returns one atomic `setOptions` transaction (thresholds, -one operation per signer, master key weight zeroed last) and refuses any -configuration that would lock the account out; `dryRunMultisigSetup` and -`verifyMultisig` cover review and on-chain verification. Client-side only — no -contract change, so the generated bindings are unchanged. diff --git a/contract-changes.d/45-payee-rights-transfer.md b/contract-changes.d/45-payee-rights-transfer.md new file mode 100644 index 00000000..08ccb26c --- /dev/null +++ b/contract-changes.d/45-payee-rights-transfer.md @@ -0,0 +1,8 @@ +bump: minor +--- +Issue #45 (Phase E5): new `transfer_payee(escrow_id, current_payee, new_payee)` +entry point — only the current payee may authorize it, only while the escrow +is `Funded`, and `new_payee` may be neither the contract address nor the +payer. Emits a `pay_xfer` event and adds `Error::InvalidNewPayee` (provisional +code 4500, renumbered by the maintainer fold). Rotation tool, not key-loss +recovery; covered by `contracts/escrow/tests/transfer_payee.rs`. diff --git a/contract-changes.d/README.md b/contract-changes.d/README.md new file mode 100644 index 00000000..ae6c37e9 --- /dev/null +++ b/contract-changes.d/README.md @@ -0,0 +1,61 @@ +# contract-changes.d + +One new file per PR that changes the escrow contract +(`contracts/escrow/src/lib.rs`). + +When every contract PR bumped `CONTRACT_VERSION` itself, all of them edited +the same line and picked the same "next" version, so each contract merge put +every other contract PR into conflict. Now you describe the change in a +fragment, and a maintainer bumps the version once for a whole batch. + +CI (`scripts/check-contract-change.mjs`) enforces this on every PR that +touches `lib.rs`. + +## Adding your fragment + +1. Create `contract-changes.d/-.md`, for example + `contract-changes.d/35-emergency-pause.md`. +2. The first line is the bump level, then a `---` line, then a one-paragraph + summary of the contract change: + + ```markdown + bump: minor + --- + Issue #35: emergency pause (ADR 0011). New `pause`/`unpause` entry points + and `Paused`, `AlreadyPaused`, `NotPaused` errors; outbound paths are + never blocked. + ``` + + - `patch`: behaviour fix, no interface change. + - `minor`: new entry points, arguments, events or errors (backwards + compatible for existing callers). + - `major`: a breaking change to existing entry points or storage. +3. Commit it in the same PR as your contract change. + +## Don't edit `CONTRACT_VERSION` + +Leave `pub const CONTRACT_VERSION` in `lib.rs` exactly as it is on `main`. +CI fails a PR that changes it. The maintainer fold +(`node scripts/fold-contract-changes.mjs`) sets it. + +## New `Error` codes + +`Error` codes are append-only: never renumber or remove an existing variant. +For a new variant, use a **provisional** code of your issue number × 100 + n, +for example issue #35 adds `Paused = 3500`, `AlreadyPaused = 3501`, +`NotPaused = 3502`. Provisional codes can't collide with another open PR, so +two PRs adding errors can both merge without a duplicate code. The fold +renumbers provisional codes to the next free final codes; the changelog entry +it writes records the mapping. Refer to errors by name (`Error::Paused`) in +tests and the SDK, never by number. + +If two PRs append to the end of the enum, git may still show a conflict +there. Keep both sides: their codes don't clash. + +## What the maintainer fold does + +`node scripts/fold-contract-changes.mjs` bumps `CONTRACT_VERSION` by the +largest level among the fragments, renumbers provisional error codes, writes +`changelog.d/contract-.md`, and deletes the fragments. The maintainer +then refreshes test snapshots (`cargo test`) and the generated SDK bindings +(`scripts/check-generated-bindings.sh`), and commits everything in one PR. diff --git a/contracts/escrow/src/lib.rs b/contracts/escrow/src/lib.rs index 8568d2e9..dab473df 100644 --- a/contracts/escrow/src/lib.rs +++ b/contracts/escrow/src/lib.rs @@ -51,7 +51,7 @@ use soroban_sdk::{ // Bump this value whenever a contract interface or behavior change is made. // CI checks this constant against the base branch when this file changes. -pub const CONTRACT_VERSION: &str = "2.2.0"; +pub const CONTRACT_VERSION: &str = "2.3.0"; include!(concat!(env!("OUT_DIR"), "/contract_metadata.rs")); @@ -251,6 +251,13 @@ pub enum Error { /// The opted-in payee callback returned an error or could not be /// invoked. The release transaction (including its transfer) rolls back. CallbackFailed = 9, + /// `new_payee` is invalid: it is either the contract's own address + /// or the payer's address. The contract address can never sign to + /// accept a payout; the payer is excluded so a payer cannot redirect + /// the release destination to themselves via a colluding payee. + /// Provisional code (issue #45 × 100); the maintainer fold assigns the + /// final number — see contract-changes.d/README.md. + InvalidNewPayee = 4500, Overflow = 12, /// The releaser set is empty, or `threshold` is 0 or larger than the /// number of releasers — see docs/adr/0007. @@ -316,6 +323,9 @@ pub enum Error { /// contract itself, or an amount that would overflow the fee math — /// see docs/adr/0010. InvalidFee = 35, + /// An outbound release transfer failed; the funded escrow remains + /// retryable and may still use its refund path. + Undeliverable = 36, } #[contract] @@ -1351,7 +1361,7 @@ impl EscrowContract { // Effects before interactions: the state write lands before any // token call, so a re-entrant token cannot see a still-`Funded` // escrow (threat model T4). - data.status = settled; + data.status = settled.clone(); env.storage() .persistent() .set(&DataKey::Escrow(escrow_id), data); @@ -1363,12 +1373,30 @@ impl EscrowContract { Self::sub_liability(env, &data.token, data.amount)?; let token_client = token::Client::new(env, &data.token); - if let Some(recipient) = fee_recipient { - if fee > 0 { - token_client.transfer(&env.current_contract_address(), &recipient, &fee); + if settled == EscrowStatus::Released { + if let Some(recipient) = fee_recipient { + if fee > 0 { + let transfer = token_client.try_transfer( + &env.current_contract_address(), + &recipient, + &fee, + ); + if !matches!(transfer, Ok(Ok(()))) { + return Err(Error::Undeliverable); + } + } + } + let transfer = token_client.try_transfer( + &env.current_contract_address(), + &destination, + &payout, + ); + if !matches!(transfer, Ok(Ok(()))) { + return Err(Error::Undeliverable); } + } else { + token_client.transfer(&env.current_contract_address(), &destination, &payout); } - token_client.transfer(&env.current_contract_address(), &destination, &payout); if notify_payee { // The callback reports what the payee actually received — gross // minus any protocol fee — not the gross escrowed amount. @@ -1575,6 +1603,65 @@ impl EscrowContract { false } + + /// Lets the current `payee` reassign future payout rights to a new + /// address. Only the current `payee` may authorise this — no one + /// else (not the payer, not the releaser) can redirect where a + /// release will go (see invariant I1 and docs/threat-model.md). + /// + /// Restrictions: + /// - Only while the escrow is `Funded` (no effect after release or + /// refund; the transfer is a payout-claim reassignment, not an + /// undo of a settlement). + /// - `new_payee` may not be the contract's own address (it can never + /// sign to claim funds) or the `payer`'s address (preventing a + /// payer from using a colluding payee to redirect the escrow to + /// themselves). + /// + /// This helps a payee who is *rotating* their wallet — it does NOT + /// help a payee who has already *lost* their key and can no longer + /// sign: they cannot authorise this call. Key loss is an operational + /// risk the payee must mitigate off-chain before it happens. + /// + /// Emits a `pay_xfer` event with `(escrow_id, old_payee, new_payee)`. + pub fn transfer_payee( + env: Env, + escrow_id: u64, + current_payee: Address, + new_payee: Address, + ) -> Result<(), Error> { + current_payee.require_auth(); + + let mut data: EscrowData = env + .storage() + .persistent() + .get(&DataKey::Escrow(escrow_id)) + .ok_or(Error::NotFound)?; + + if current_payee != data.payee { + return Err(Error::Unauthorized); + } + if data.status != EscrowStatus::Funded { + return Err(Error::NotFunded); + } + if new_payee == env.current_contract_address() || new_payee == data.payer { + return Err(Error::InvalidNewPayee); + } + + let old_payee = data.payee.clone(); + data.payee = new_payee.clone(); + env.storage() + .persistent() + .set(&DataKey::Escrow(escrow_id), &data); + + env.events().publish( + (symbol_short!("pay_xfer"), escrow_id), + (old_payee, new_payee), + ); + Ok(()) + } + + fn next_id(env: &Env) -> u64 { let id: u64 = env.storage().instance().get(&DataKey::NextId).unwrap_or(0); env.storage().instance().set(&DataKey::NextId, &(id + 1)); @@ -1643,3 +1730,6 @@ impl EscrowContract { storage.extend_ttl(&key, LIABILITY_TTL_THRESHOLD.min(extend_to), extend_to); } } + + + diff --git a/contracts/escrow/test_snapshots/payee_can_transfer_multiple_times_before_release.1.json b/contracts/escrow/test_snapshots/payee_can_transfer_multiple_times_before_release.1.json new file mode 100644 index 00000000..827ebfdb --- /dev/null +++ b/contracts/escrow/test_snapshots/payee_can_transfer_multiple_times_before_release.1.json @@ -0,0 +1,876 @@ +{ + "generators": { + "address": 8, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "transfer_payee", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "transfer_payee", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "release", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": "4270020994084947596" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Released" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "0" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Released" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", + "key": { + "ledger_key_nonce": { + "nonce": "2032731177588607455" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/refund_after_transfer_still_returns_to_payer.1.json b/contracts/escrow/test_snapshots/refund_after_transfer_still_returns_to_payer.1.json new file mode 100644 index 00000000..bc71c02b --- /dev/null +++ b/contracts/escrow/test_snapshots/refund_after_transfer_still_returns_to_payer.1.json @@ -0,0 +1,779 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "transfer_payee", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "refund", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": "2032731177588607455" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Refunded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "0" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Refunded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "1000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/rejecting_contract_payee_returns_dedicated_error_without_settling.1.json b/contracts/escrow/test_snapshots/rejecting_contract_payee_returns_dedicated_error_without_settling.1.json new file mode 100644 index 00000000..86a3162f --- /dev/null +++ b/contracts/escrow/test_snapshots/rejecting_contract_payee_returns_dedicated_error_without_settling.1.json @@ -0,0 +1,491 @@ +{ + "generators": { + "address": 5, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "i128": "300" + }, + { + "string": "rejecting-contract-payee" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "700" + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "300" + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + }, + "durability": "persistent", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "300" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "rejecting-contract-payee" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "300" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/release_after_transfer_pays_new_payee_not_old.1.json b/contracts/escrow/test_snapshots/release_after_transfer_pays_new_payee_not_old.1.json new file mode 100644 index 00000000..528741ac --- /dev/null +++ b/contracts/escrow/test_snapshots/release_after_transfer_pays_new_payee_not_old.1.json @@ -0,0 +1,831 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "transfer_payee", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "release", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": "2032731177588607455" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Released" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "0" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Released" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_rejects_after_refund.1.json b/contracts/escrow/test_snapshots/transfer_payee_rejects_after_refund.1.json new file mode 100644 index 00000000..6cc0b694 --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_rejects_after_refund.1.json @@ -0,0 +1,733 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "refund", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Refunded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "0" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Refunded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "1000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_rejects_after_release.1.json b/contracts/escrow/test_snapshots/transfer_payee_rejects_after_release.1.json new file mode 100644 index 00000000..118d7395 --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_rejects_after_release.1.json @@ -0,0 +1,785 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "release", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Released" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "0" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Released" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_rejects_contract_address_as_new_payee.1.json b/contracts/escrow/test_snapshots/transfer_payee_rejects_contract_address_as_new_payee.1.json new file mode 100644 index 00000000..af844acb --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_rejects_contract_address_as_new_payee.1.json @@ -0,0 +1,691 @@ +{ + "generators": { + "address": 6, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "500" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_rejects_payer_acting_as_current_payee.1.json b/contracts/escrow/test_snapshots/transfer_payee_rejects_payer_acting_as_current_payee.1.json new file mode 100644 index 00000000..130d7935 --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_rejects_payer_acting_as_current_payee.1.json @@ -0,0 +1,691 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "500" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_rejects_payer_as_new_payee.1.json b/contracts/escrow/test_snapshots/transfer_payee_rejects_payer_as_new_payee.1.json new file mode 100644 index 00000000..af844acb --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_rejects_payer_as_new_payee.1.json @@ -0,0 +1,691 @@ +{ + "generators": { + "address": 6, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "500" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_rejects_releaser_acting_as_current_payee.1.json b/contracts/escrow/test_snapshots/transfer_payee_rejects_releaser_acting_as_current_payee.1.json new file mode 100644 index 00000000..130d7935 --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_rejects_releaser_acting_as_current_payee.1.json @@ -0,0 +1,691 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "500" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_rejects_stranger.1.json b/contracts/escrow/test_snapshots/transfer_payee_rejects_stranger.1.json new file mode 100644 index 00000000..b3779002 --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_rejects_stranger.1.json @@ -0,0 +1,691 @@ +{ + "generators": { + "address": 8, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "500" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_rejects_unknown_escrow_id.1.json b/contracts/escrow/test_snapshots/transfer_payee_rejects_unknown_escrow_id.1.json new file mode 100644 index 00000000..22db8e35 --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_rejects_unknown_escrow_id.1.json @@ -0,0 +1,690 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "500" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/transfer_payee_updates_stored_payee.1.json b/contracts/escrow/test_snapshots/transfer_payee_updates_stored_payee.1.json new file mode 100644 index 00000000..54c425c0 --- /dev/null +++ b/contracts/escrow/test_snapshots/transfer_payee_updates_stored_payee.1.json @@ -0,0 +1,735 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "500" + }, + { + "string": "opaque-condition-ref" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "transfer_payee", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "opaque-condition-ref" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "500" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Funded" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/test_snapshots/unauthorized_sac_payee_leaves_escrow_funded_and_can_be_retried.1.json b/contracts/escrow/test_snapshots/unauthorized_sac_payee_leaves_escrow_funded_and_can_be_retried.1.json new file mode 100644 index 00000000..cc9a2b13 --- /dev/null +++ b/contracts/escrow/test_snapshots/unauthorized_sac_payee_leaves_escrow_funded_and_can_be_retried.1.json @@ -0,0 +1,873 @@ +{ + "generators": { + "address": 6, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "create_escrow", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + }, + { + "i128": "300" + }, + { + "string": "undeliverable-sac-payee" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "void", + { + "bool": false + }, + "void", + "void", + "void" + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": "300" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_authorized", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "bool": false + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "function_name": "set_authorized", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "bool": true + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "release", + "args": [ + { + "u64": "0" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 2, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "4270020994084947596" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": "8370022561469687789" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Escrow" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accepted_at" + }, + "val": "void" + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "300" + } + }, + { + "key": { + "symbol": "condition_ref" + }, + "val": { + "string": "undeliverable-sac-payee" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": "void" + }, + { + "key": { + "symbol": "fee_recipient" + }, + "val": "void" + }, + { + "key": { + "symbol": "notify_payee" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "payee" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "payer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "refund_after" + }, + "val": "void" + }, + { + "key": { + "symbol": "refund_to" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "release_not_before" + }, + "val": "void" + }, + { + "key": { + "symbol": "releasers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "requires_acceptance" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Released" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Liability" + }, + { + "address": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL" + } + ] + }, + "durability": "persistent", + "val": { + "i128": "0" + } + } + }, + "ext": "v0" + }, + "live_until": 2073600 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Status" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "symbol": "Released" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "AllowedTokens" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NextId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "700" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "300" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBEPDNVYXQGWB5YUBXKJWYJA7OXTZW5LFLNO5JRRGE6Z6C5OSUZPCCEL", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/escrow/tests/create_escrow.rs b/contracts/escrow/tests/create_escrow.rs index 3c381de1..2c0bff70 100644 --- a/contracts/escrow/tests/create_escrow.rs +++ b/contracts/escrow/tests/create_escrow.rs @@ -3,7 +3,7 @@ // // release()/refund() are Phase E2 — see tests/release_refund.rs. -use docforum_escrow::{EscrowContract, EscrowContractClient, EscrowStatus}; +use docforum_escrow::{EscrowContract, EscrowContractClient, EscrowStatus, CONTRACT_VERSION}; use soroban_sdk::{ testutils::{Address as _, Events as _, MockAuth, MockAuthInvoke}, token::{StellarAssetClient, TokenClient}, @@ -24,7 +24,10 @@ fn version_reports_the_contract_semver() { let contract_id = env.register(EscrowContract, (Vec::
::new(&env),)); let client = EscrowContractClient::new(&env, &contract_id); - assert_eq!(client.version(), String::from_str(&env, "2.2.0")); + // Compared with the constant, not a literal: the version is bumped by the + // maintainer fold (contract-changes.d/), and a literal here broke every + // open contract PR whenever it moved. + assert_eq!(client.version(), String::from_str(&env, CONTRACT_VERSION)); } #[test] diff --git a/contracts/escrow/tests/transfer_payee.rs b/contracts/escrow/tests/transfer_payee.rs new file mode 100644 index 00000000..8e0a5964 --- /dev/null +++ b/contracts/escrow/tests/transfer_payee.rs @@ -0,0 +1,269 @@ +// Phase E5 tests — transfer_payee(). +// +// Invariant under test: only the current payee may reassign the payout +// destination; no other party (payer, releaser, stranger) may redirect +// funds. After a successful transfer, release sends funds to the new +// address — and refund still goes back to the payer. +// +// transfer_payee is only valid while Funded. Rejected targets: +// - the contract's own address +// - the payer's address + +use docforum_escrow::{EscrowContract, EscrowContractClient, EscrowStatus}; +use soroban_sdk::{ + testutils::Address as _, + token::{StellarAssetClient, TokenClient}, + Address, Env, String, Vec, +}; + +struct Fixture<'a> { + client: EscrowContractClient<'a>, + token: TokenClient<'a>, + payer: Address, + payee: Address, + releaser: Address, + contract_id: Address, + escrow_id: u64, +} + +fn setup(env: &Env) -> Fixture<'_> { + env.mock_all_auths(); + + let token_contract = env.register_stellar_asset_contract_v2(Address::generate(env)); + let token_id = token_contract.address(); + let token = TokenClient::new(env, &token_id); + let asset = StellarAssetClient::new(env, &token_id); + + let payer = Address::generate(env); + let payee = Address::generate(env); + let releaser = Address::generate(env); + asset.mint(&payer, &1_000); + + let contract_id = env.register(EscrowContract, (Vec::
::new(env),)); + let client = EscrowContractClient::new(env, &contract_id); + + let escrow_id = client.create_escrow( + &payer, + &payee, + &token_id, + &500, + &String::from_str(env, "opaque-condition-ref"), + &releaser, + &None, + &false, + &None, + &None, + &None, + ); + + Fixture { + client, + token, + payer, + payee, + releaser, + contract_id, + escrow_id, + } +} + +// --- happy path --- + +#[test] +fn transfer_payee_updates_stored_payee() { + let env = Env::default(); + let f = setup(&env); + let new_payee = Address::generate(&env); + + f.client + .transfer_payee(&f.escrow_id, &f.payee, &new_payee); + + let data = f.client.get_escrow(&f.escrow_id); + assert_eq!(data.payee, new_payee); + assert_eq!(data.status, EscrowStatus::Funded); +} + +#[test] +fn release_after_transfer_pays_new_payee_not_old() { + let env = Env::default(); + let f = setup(&env); + let new_payee = Address::generate(&env); + + f.client + .transfer_payee(&f.escrow_id, &f.payee, &new_payee); + f.client.release(&f.escrow_id, &f.releaser); + + assert_eq!(f.token.balance(&new_payee), 500); + assert_eq!(f.token.balance(&f.payee), 0); // old payee gets nothing + assert_eq!( + f.client.get_status(&f.escrow_id), + EscrowStatus::Released + ); +} + +#[test] +fn refund_after_transfer_still_returns_to_payer() { + let env = Env::default(); + let f = setup(&env); + let new_payee = Address::generate(&env); + + f.client + .transfer_payee(&f.escrow_id, &f.payee, &new_payee); + f.client.refund(&f.escrow_id, &f.releaser); + + assert_eq!(f.token.balance(&f.payer), 1_000); // full refund + assert_eq!(f.token.balance(&new_payee), 0); + assert_eq!( + f.client.get_status(&f.escrow_id), + EscrowStatus::Refunded + ); +} + +#[test] +fn payee_can_transfer_multiple_times_before_release() { + let env = Env::default(); + let f = setup(&env); + let payee_b = Address::generate(&env); + let payee_c = Address::generate(&env); + + f.client + .transfer_payee(&f.escrow_id, &f.payee, &payee_b); + f.client + .transfer_payee(&f.escrow_id, &payee_b, &payee_c); + f.client.release(&f.escrow_id, &f.releaser); + + assert_eq!(f.token.balance(&payee_c), 500); + assert_eq!(f.token.balance(&f.payee), 0); + assert_eq!(f.token.balance(&payee_b), 0); +} + +// --- auth --- + +#[test] +fn transfer_payee_rejects_stranger() { + let env = Env::default(); + let f = setup(&env); + let stranger = Address::generate(&env); + let new_payee = Address::generate(&env); + + let result = f + .client + .try_transfer_payee(&f.escrow_id, &stranger, &new_payee); + + assert!(result.is_err()); + // payee unchanged + assert_eq!(f.client.get_escrow(&f.escrow_id).payee, f.payee); +} + +#[test] +fn transfer_payee_rejects_payer_acting_as_current_payee() { + let env = Env::default(); + let f = setup(&env); + let new_payee = Address::generate(&env); + + // The payer is not the current payee — even if they try to claim it. + let result = f + .client + .try_transfer_payee(&f.escrow_id, &f.payer, &new_payee); + + assert!(result.is_err()); + assert_eq!(f.client.get_escrow(&f.escrow_id).payee, f.payee); +} + +#[test] +fn transfer_payee_rejects_releaser_acting_as_current_payee() { + let env = Env::default(); + let f = setup(&env); + let new_payee = Address::generate(&env); + + let result = f + .client + .try_transfer_payee(&f.escrow_id, &f.releaser, &new_payee); + + assert!(result.is_err()); + assert_eq!(f.client.get_escrow(&f.escrow_id).payee, f.payee); +} + +// --- rejected new_payee targets --- + +#[test] +fn transfer_payee_rejects_contract_address_as_new_payee() { + let env = Env::default(); + let f = setup(&env); + + // new_payee == the contract's own address is rejected — it can never + // sign to claim a payout, so funds would be permanently locked. + let result = f + .client + .try_transfer_payee(&f.escrow_id, &f.payee, &f.contract_id); + + assert!(result.is_err()); + assert_eq!(f.client.get_escrow(&f.escrow_id).payee, f.payee); +} + +#[test] +fn transfer_payee_rejects_payer_as_new_payee() { + let env = Env::default(); + let f = setup(&env); + + // new_payee == payer is rejected: it would let the payer claw back + // the escrow via a release (bypassing refund's auth), undermining + // the payee's claim. Even a colluding current_payee cannot do this. + let result = f + .client + .try_transfer_payee(&f.escrow_id, &f.payee, &f.payer); + + assert!(result.is_err()); + assert_eq!(f.client.get_escrow(&f.escrow_id).payee, f.payee); +} + +// --- state checks --- + +#[test] +fn transfer_payee_rejects_after_release() { + let env = Env::default(); + let f = setup(&env); + let new_payee = Address::generate(&env); + + f.client.release(&f.escrow_id, &f.releaser); + let result = f + .client + .try_transfer_payee(&f.escrow_id, &f.payee, &new_payee); + + assert!(result.is_err()); + assert_eq!( + f.client.get_status(&f.escrow_id), + EscrowStatus::Released + ); +} + +#[test] +fn transfer_payee_rejects_after_refund() { + let env = Env::default(); + let f = setup(&env); + let new_payee = Address::generate(&env); + + f.client.refund(&f.escrow_id, &f.releaser); + let result = f + .client + .try_transfer_payee(&f.escrow_id, &f.payee, &new_payee); + + assert!(result.is_err()); + assert_eq!( + f.client.get_status(&f.escrow_id), + EscrowStatus::Refunded + ); +} + +#[test] +fn transfer_payee_rejects_unknown_escrow_id() { + let env = Env::default(); + let f = setup(&env); + let new_payee = Address::generate(&env); + + let result = f + .client + .try_transfer_payee(&999u64, &f.payee, &new_payee); + + assert!(result.is_err()); +} diff --git a/contracts/escrow/tests/undeliverable.rs b/contracts/escrow/tests/undeliverable.rs new file mode 100644 index 00000000..89744a7d --- /dev/null +++ b/contracts/escrow/tests/undeliverable.rs @@ -0,0 +1,158 @@ +use docforum_escrow::{Error, EscrowContract, EscrowContractClient, EscrowStatus}; +use soroban_sdk::{ + contract, contractimpl, contracttype, symbol_short, + testutils::{Address as _, IssuerFlags}, + token::{StellarAssetClient, TokenClient}, + Address, Env, String, +}; + +#[test] +fn unauthorized_sac_payee_leaves_escrow_funded_and_can_be_retried() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let token_id = env.register_stellar_asset_contract_v2(admin); + token_id.issuer().set_flag(IssuerFlags::RevocableFlag); + let token = TokenClient::new(&env, &token_id.address()); + let asset = StellarAssetClient::new(&env, &token_id.address()); + let payer = Address::generate(&env); + let payee = Address::generate(&env); + let releaser = Address::generate(&env); + asset.mint(&payer, &1_000); + + let contract_id = env.register(EscrowContract, (soroban_sdk::Vec::
::new(&env),)); + let client = EscrowContractClient::new(&env, &contract_id); + let escrow_id = client.create_escrow( + &payer, + &payee, + &token_id.address(), + &300, + &String::from_str(&env, "undeliverable-sac-payee"), + &releaser, + &None, + &false, + &None, + &None, + &None, + ); + + // This uses the SAC's actual authorization flag, rather than a mock + // token return value. A deauthorized destination rejects transfer. + asset.set_authorized(&payee, &false); + let rejected = client.try_release(&escrow_id, &releaser); + assert_eq!(rejected, Err(Ok(Error::Undeliverable))); + assert_eq!(client.get_status(&escrow_id), EscrowStatus::Funded); + assert_eq!(token.balance(&contract_id), 300); + assert_eq!(token.balance(&payee), 0); + + asset.set_authorized(&payee, &true); + client.release(&escrow_id, &releaser); + assert_eq!(client.get_status(&escrow_id), EscrowStatus::Released); + assert_eq!(token.balance(&payee), 300); +} + +#[contract] +struct RejectingPayee; + +#[contractimpl] +impl RejectingPayee { + pub fn receive(_env: Env) { + panic!("payee rejected transfer"); + } +} + +#[contracttype] +#[derive(Clone)] +enum CallbackTokenKey { + Balance(Address), + Escrow(Address), +} + +fn callback_balance(env: &Env, address: &Address) -> i128 { + env.storage() + .persistent() + .get(&CallbackTokenKey::Balance(address.clone())) + .unwrap_or(0) +} + +#[contract] +struct CallbackToken; + +#[contractimpl] +impl CallbackToken { + pub fn set_balance(env: Env, address: Address, amount: i128) { + env.storage() + .persistent() + .set(&CallbackTokenKey::Balance(address), &amount); + } + + pub fn set_escrow(env: Env, escrow: Address) { + env.storage() + .persistent() + .set(&CallbackTokenKey::Escrow(escrow), &()); + } + + pub fn balance(env: Env, address: Address) -> i128 { + callback_balance(&env, &address) + } + + pub fn transfer(env: Env, from: Address, to: Address, amount: i128) { + // When funds are sent out of the escrow, model a token/receiver + // integration that calls the contract payee and propagates its + // rejection. The outer escrow call must recover this failure. + if env + .storage() + .persistent() + .has(&CallbackTokenKey::Escrow(from.clone())) + { + let _: () = + env.invoke_contract(&to, &symbol_short!("receive"), soroban_sdk::vec![&env]); + } else if from != to { + // Inbound funding transfer to the escrow. + let from_balance = callback_balance(&env, &from); + let to_balance = callback_balance(&env, &to); + env.storage() + .persistent() + .set(&CallbackTokenKey::Balance(from), &(from_balance - amount)); + env.storage() + .persistent() + .set(&CallbackTokenKey::Balance(to), &(to_balance + amount)); + } + } +} + +#[test] +fn rejecting_contract_payee_returns_dedicated_error_without_settling() { + let env = Env::default(); + env.mock_all_auths(); + + let token_id = env.register(CallbackToken, ()); + let token = CallbackTokenClient::new(&env, &token_id); + let payer = Address::generate(&env); + token.set_balance(&payer, &1_000); + let payee_id = env.register(RejectingPayee, ()); + let releaser = Address::generate(&env); + let contract_id = env.register(EscrowContract, (soroban_sdk::Vec::
::new(&env),)); + token.set_escrow(&contract_id); + let client = EscrowContractClient::new(&env, &contract_id); + let escrow_id = client.create_escrow( + &payer, + &payee_id, + &token_id, + &300, + &String::from_str(&env, "rejecting-contract-payee"), + &releaser, + &None, + &false, + &None, + &None, + &None, + ); + + let rejected = client.try_release(&escrow_id, &releaser); + assert_eq!(rejected, Err(Ok(Error::Undeliverable))); + assert_eq!(client.get_status(&escrow_id), EscrowStatus::Funded); + assert_eq!(token.balance(&contract_id), 300); + assert_eq!(token.balance(&payee_id), 0); +} diff --git a/docs/threat-model.md b/docs/threat-model.md index f4afe5b3..e35fe287 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -48,10 +48,11 @@ and contributor-resource exhaustion; §8 traceability gains matching rows.* | # | Invariant | Enforced by | |---|---|---| -| I1 | Funds only leave an escrow to that escrow's `payee` (on release, subject to the `release_not_before` time-lock guard) or the escrow's stored `refund_to` (on refund; equals `payer` unless a different one was set at creation) — or, on a **pooled** escrow (issue #113, ADR 0011), back to each recorded `contributor` in that contributor's exact recorded amount via the pull-based `claim_refund`. No other destination exists in either mode. | Both destinations are written once in `create_escrow` under the funder's auth and read from storage, never from call arguments (`lib.rs:165`, `lib.rs:203`). The `refund_after` timeout path (issue #11, ADR 0004) adds a new *caller*, not a new destination, and `refund_to` (issue #28, ADR 0009) is a second stored-at-creation destination, not a payout-time choice: nothing sets it after creation. The `release_not_before` field (issue #43) gates the `release` entry point — release before this time is rejected with `ReleaseTooEarly`. For pooled escrows the push paths (`refund`, `refund_with_approvals`, `cancel`) are rejected outright (`NotSupportedForPooled`), so `refund_to` can never drain a pool; `claim_refund` pays only the calling contributor's own record, under that contributor's `require_auth`, and only while the escrow has not been released. | +| I1 | Funds only leave an escrow to that escrow's `payee` (on release, subject to the `release_not_before` time-lock guard) or the escrow's stored `refund_to` (on refund; equals `payer` unless a different one was set at creation) — or, on a **pooled** escrow (issue #113, ADR 0011), back to each recorded `contributor` in that contributor's exact recorded amount via the pull-based `claim_refund`. No other destination exists in either mode. | Both destinations are written once in `create_escrow` under the funder's auth and read from storage, never from call arguments (`lib.rs:165`, `lib.rs:203`). The `refund_after` timeout path (issue #11, ADR 0004) adds a new *caller*, not a new destination, and `transfer_payee` (issue #45, Phase E5) only reassigns *who* the stored `payee` is — under that payee's own auth — never a destination outside storage; and `refund_to` (issue #28, ADR 0009) is a second stored-at-creation destination, not a payout-time choice: nothing sets it after creation. The `release_not_before` field (issue #43) gates the `release` entry point — release before this time is rejected with `ReleaseTooEarly`. For pooled escrows the push paths (`refund`, `refund_with_approvals`, `cancel`) are rejected outright (`NotSupportedForPooled`), so `refund_to` can never drain a pool; `claim_refund` pays only the calling contributor's own record, under that contributor's `require_auth`, and only while the escrow has not been released. | | I2 | Only the escrow's releasers can move funds out — `threshold` distinct ones when the escrow was created M-of-N (ADR 0007); release additionally requires payee acceptance when configured — or, once `refund_after` has passed, anyone at all, and then still only to the stored `refund_to`. Rotate‑releaser changes the stored releaser set only when both the current releaser and the payer authorize the change (`rotate_releaser`). `top_up` adds funds to a `Funded` escrow, authorized only by the stored `payer`. The one non-releaser movement that exists is pooled (issue #113): each `contributor` may pull back **only its own recorded amount** via `claim_refund` under its own signature, only from a failed round (deadline passed, target unmet), never after a release — `top_up`, `cancel` and both push-refund paths are rejected on pooled escrows (`NotSupportedForPooled`). | `require_auth()` per caller/approver + membership in the stored `releasers` set + the threshold check (`check_single_caller`, `check_approvals`), relaxed solely by the deadline check in `refund`. Duplicate approvers are rejected. `rotate_releaser` requires auth from both the current releaser and the payer, and rejects if the new releaser is the contract or the payee (`lib.rs:369-408`). `top_up` reads the stored `payer` from escrow data and rejects if `payer != caller` (`lib.rs:412-439`). | | I3 | Each escrow pays out at most once — and on a pooled escrow (issue #113), each contribution is refunded at most once; a release and a refund can never spend the same tokens. | `status == Funded` check and terminal status write before transfer/callback; failures roll back atomically. Additionally, `cancel` (ADR 0010) is a terminal status — once `Cancelled`, `Released`, or `Refunded`, the escrow cannot be settled again. The accept/cancel race is resolved by ledger-order: whichever transaction lands first wins, the other fails. For pooled escrows, `claim_refund` writes the `refunded` flag and decrements the pooled total *before* the transfer (checks-effects-interactions), so a second claim fails `AlreadyRefunded` and a claim after release fails `NotFunded`; release requires `funded == target`, which becomes permanently false after any claim of a failed round. | | I4 | An escrow only exists, or grows, if the declared funds were actually transferred in — including every contribution to a pooled escrow. | `payer.require_auth()` + shared exact-balance-delta verification on create/top-up before storage is updated. `top_up` verified the transferred amount matches the top‑up amount before updating `data.amount`. `contribute` (issue #113) routes through the same `transfer_in_exact`, and updates both the per-payer record and the pooled total only after the delta is verified. | + | I5 | The contract never interprets `condition_ref`. | No code reads it after storage (ADR 0001). | | I6 | An escrow created with `requires_acceptance` cannot be settled (released/refunded/canceled) without the payee's explicit `accept` call first. | `release`/`refund`/`cancel` all check `data.accepted_at` — `AcceptanceRequired` if absent, `NotFunded` if already terminal. The accept/cancel race on one ledger state is resolved by ordering: first to commit wins. | | I7 | A declared fee takes exactly once per release: `⌊amount × fee_bps ÷ 10 000⌋` (≤ 10 %) to the `fee_recipient` fixed at creation, the remainder to `payee` — the two sum to exactly `amount` — and no fee ever moves on the refund path. | Fee is validated before funds are locked at creation (`InvalidFee` for a half-set pair, `bps` > 1 000 or a self-recipient; overflow rejected via checked math), computed with floor rounding at release (`fee_amount`), re-checked on `top_up` (which grows `amount`, and therefore the fee), and `refund` never reads the fee fields (ADR 0010, issue #30). Split-payout features (if any land later) must divide the fee-free net, not re-charge the bps. | @@ -72,11 +73,12 @@ escrow; the integrity of each escrow's stored `EscrowData`. | Actor | Can do | Trusted for | |---|---|---| | `payer` | Create escrows by funding them; chooses `payee`, `token`, `releaser`, and optionally a distinct `refund_to` — all under its single creation signature | Nothing after creation. Has no on-chain power to cancel. | -| `payee` | Receive funds; optionally accept an escrow before release | Without the opt-in acceptance gate, has no on-chain power to object to release or refund. | +| `payee` | Receive funds; optionally accept an escrow before release; reassign the future payout destination to another address while `Funded` via `transfer_payee` (issue #45), which needs only its own auth | Nothing beyond the payee-transfer path: it can pick **which** address is paid, never force a release or block a refund. Without the opt-in acceptance gate it has no on-chain power to object to release or refund. | | `releaser` (one address, or an M-of-N `releasers` set, ADR 0007) | `release` or `refund` its escrows, once — a quorum escrow needs `threshold` distinct releasers on one call | Choosing the correct outcome. This is the main trust assumption; a quorum splits it across the set. | | `rotate_releaser` (single‑releaser escrow only, ADR 0009) | `rotate_releaser` — both the current releaser and the payer must authorize; the replacement cannot be the contract or the payee | Current releaser key safety: the payer's consent prevents a compromised releaser from silently appointing an attacker. | | `top_up` (single‑releaser escrow only, Phase E5) | `top_up` — only the original payer may add funds to a `Funded` escrow | Payer‑controlled fund growth; the escrow amount increases but parties and rules remain unchanged. | | `contributor` (pooled escrows, issue #113) | `contribute` its own funds to any open pooled escrow before its funding deadline; after a missed deadline, `claim_refund` back its own exact recorded amount | Nothing. Contributions are self-funding (you can only send your own tokens) and claims can only reach the caller's own record. | + | `token` contract | Executes transfers | Behaving like a standard SEP-41 token (see T5). | | Anyone | Call `create_escrow` with their own funds, call `get_status`/`get_escrow`, and — on an escrow whose `refund_after` has passed — call `refund`, which can only send funds to that escrow's stored `refund_to` | Nothing. | | `attester` (**planned**, not implemented) | Would publish signed attestations referenced by an escrow's `condition_ref` | Nothing on-chain; the contract never reads attestations. See T12. | @@ -713,6 +715,45 @@ escrow. *Key: "Covered" = at least one test explicitly exercises the threat and verifies the mitigation. "Residual risk: accepted" = the threat is understood and intentionally tolerated with a documented mitigation. "Uncovered" = no test or mitigation exists — should be evaluated for a future release.* +### T11 — Payee key compromise or loss · **Medium (new surface from issue #45)** +- **What changed:** `transfer_payee` (Phase E5) gives the current `payee` + the ability to redirect the release destination to a new address, while + the escrow is `Funded`. This is the first on-chain power the payee has + had. It adds a new attack surface. +- **Key compromised:** if an attacker steals the payee's key they can + transfer the payee claim to an address they control, then wait for + the releaser to release (or, if a `refund_after` deadline is in the + past, call `refund` — still only to the payer, so the payer does not + lose funds in the refund path). The realistic theft scenario is: + attacker calls `transfer_payee` to their address, releaser then + releases normally, attacker gets the payout. + - Blast radius: limited to escrows where the attacker knows (or can + scan for) the payee address and the escrow is still `Funded`. + - The payer's and releaser's keys are unaffected; the releaser can + still refund rather than release if they detect the compromise. +- **Key lost:** if the payee loses their key they **cannot** call + `transfer_payee` (they can't sign). This function is a rotation tool, + not a recovery tool. A payee who has lost their key cannot reassign + their claim. Document this limitation clearly to consumers. + - After key loss, the only on-chain resolution is for the `releaser` + to refund to the payer, or to wait for a `refund_after` timeout + (if one was set). There is no payee-side recovery path. +- **Mitigations:** + - Payees: rotate wallet keys before the old device or key material is + compromised — use `transfer_payee` proactively. + - Consumers: before relying on a `Funded` escrow, check `get_escrow` + to confirm the current `payee` matches your expected address (the + payee may have already rotated). + - The contract prevents the two most obvious misuse vectors: + `new_payee == contract_address` (would lock funds) and + `new_payee == payer` (would let a colluding payee redirect to payer, + turning a release into a de-facto payer refund that bypasses refund + auth). These are rejected with `Error::InvalidNewPayee` (provisional + code 4500 until the maintainer fold assigns the final number). + - The releaser cannot use `transfer_payee` — they have no power over + the payee field. This is enforced by `current_payee.require_auth()` + plus the `current_payee == data.payee` check. + ## 4. SDK-specific notes (`sdk/src/index.ts`) - **Defaults are testnet only** (hard rule 4). A caller can still pass a @@ -803,6 +844,8 @@ Leave findings as comments on the PR that adds this file, or on issue #6. A review only counts toward E4 if the reviewer is not the implementer (see issue #6). +A rejected outbound token transfer during `release` returns `Undeliverable` and leaves the escrow funded. The releaser can retry after the payee becomes reachable or use the existing refund path. + ## T4 intermediate-contract re-entry regression coverage Token callbacks must be treated as hostile even when they route through another contract. The regression suite exercises a helper contract that attempts to call back into escrow during a token transfer; the invocation must fail closed and leave the escrow status and balance unchanged. \ No newline at end of file diff --git a/scripts/check-contract-change.mjs b/scripts/check-contract-change.mjs new file mode 100644 index 00000000..f5d64f28 --- /dev/null +++ b/scripts/check-contract-change.mjs @@ -0,0 +1,99 @@ +#!/usr/bin/env node +// CI rule for pull requests that touch the escrow contract. +// +// Contributors no longer edit CONTRACT_VERSION. When nine open PRs each bumped +// that one line, every contract merge put all the others into conflict. Now a +// PR that changes contracts/escrow/src/lib.rs adds a fragment under +// contract-changes.d/ instead, and a maintainer bumps the version once per +// batch with scripts/fold-contract-changes.mjs (see contract-changes.d/README.md). +// +// The same goes for `Error` codes: new variants use a provisional discriminant +// (issue number × 100 + n, so they can't collide between PRs), and the fold +// renumbers them to the next free codes. +// +// Fails when lib.rs changed and: +// - no fragment was added, or +// - CONTRACT_VERSION changed (only a fold PR, which deletes fragments, may), or +// - an existing `Error` variant was renumbered or removed, or +// - a new `Error` variant uses a non-provisional code (below 1000). +// +// node scripts/check-contract-change.mjs # e.g. origin/main +import { execFileSync } from 'node:child_process'; + +const LIB = 'contracts/escrow/src/lib.rs'; +const FRAGMENTS = 'contract-changes.d/'; +const PROVISIONAL_MIN = 1000; + +const base = process.argv[2]; +if (!base) { + console.error('usage: node scripts/check-contract-change.mjs '); + process.exit(2); +} + +const git = (...args) => execFileSync('git', args, { encoding: 'utf8' }); +const mergeBase = git('merge-base', base, 'HEAD').trim(); +const show = (rev) => git('show', `${rev}:${LIB}`); + +if (!git('diff', '--name-only', mergeBase, 'HEAD', '--', LIB).trim()) process.exit(0); + +const changed = git('diff', '--name-status', mergeBase, 'HEAD', '--', FRAGMENTS) + .split('\n') + .filter((l) => l.trim() && !l.endsWith('README.md')); +const added = changed.filter((l) => l.startsWith('A')); +const deleted = changed.filter((l) => l.startsWith('D')); +const isFold = deleted.length > 0 && added.length === 0; + +const version = (src) => (src.match(/^pub const CONTRACT_VERSION: &str = "([^"]+)";/m) || [])[1]; +function errorCodes(src) { + const body = (src.match(/^pub enum Error \{([\s\S]*?)^\}/m) || [])[1] || ''; + const codes = new Map(); + for (const m of body.matchAll(/^\s*([A-Z][A-Za-z0-9]*)\s*=\s*(\d+)\s*,/gm)) codes.set(m[1], Number(m[2])); + return codes; +} + +const before = show(mergeBase); +const after = show('HEAD'); +const problems = []; + +if (!isFold && added.length === 0) { + problems.push( + `${LIB} changed, but no fragment was added under ${FRAGMENTS}. ` + + `Add ${FRAGMENTS}-.md (see ${FRAGMENTS}README.md).`, + ); +} +if (!isFold && version(before) !== version(after)) { + problems.push( + `CONTRACT_VERSION changed (${version(before)} -> ${version(after)}). ` + + `Leave it as it is on main: a maintainer bumps it when folding ${FRAGMENTS}.`, + ); +} + +const old = errorCodes(before); +const now = errorCodes(after); +for (const [name, code] of old) { + if (!now.has(name)) problems.push(`Error::${name} (= ${code}) was removed. Error codes are append-only.`); + else if (now.get(name) !== code && !(isFold && code >= PROVISIONAL_MIN)) { + problems.push(`Error::${name} was renumbered (${code} -> ${now.get(name)}). Error codes are append-only.`); + } +} +if (!isFold) { + for (const [name, code] of now) { + if (!old.has(name) && code < PROVISIONAL_MIN) { + problems.push( + `New Error::${name} uses code ${code}. Use a provisional code (your issue number × 100 + n, ` + + `e.g. issue #35 -> 3500, 3501); the maintainer fold assigns the final number.`, + ); + } + } +} +const seen = new Map(); +for (const [name, code] of now) { + if (seen.has(code)) problems.push(`Error::${name} and Error::${seen.get(code)} share code ${code}.`); + seen.set(code, name); +} + +if (problems.length) { + for (const p of problems) console.error(`error: ${p}`); + process.exit(1); +} +console.log(isFold ? 'OK: contract-change fold.' : `OK: ${added.length} contract-change fragment(s) added.`); diff --git a/scripts/fold-contract-changes.mjs b/scripts/fold-contract-changes.mjs new file mode 100644 index 00000000..9712500c --- /dev/null +++ b/scripts/fold-contract-changes.mjs @@ -0,0 +1,95 @@ +#!/usr/bin/env node +// Folds the fragments in contract-changes.d/ into one contract release: +// +// 1. bumps CONTRACT_VERSION in contracts/escrow/src/lib.rs once, by the +// largest `bump:` level across the fragments (major > minor > patch); +// 2. renumbers provisional `Error` codes (>= 1000, see the README) to the +// next free codes after the highest final one, in ascending order; +// 3. writes changelog.d/contract-.md so scripts/fold-changelog.mjs +// records the release in ROADMAP.md, and deletes the fragments. +// +// Maintainers run this and commit the result in its own PR (contributors only +// add fragments, so their PRs never touch the version line). Afterwards, +// refresh the outputs that depend on the contract and commit them too: +// +// (cd contracts/escrow && cargo test) # refreshes test_snapshots/ +// scripts/check-generated-bindings.sh # prints the regenerate steps +// +// node scripts/fold-contract-changes.mjs # fold and delete fragments +// node scripts/fold-contract-changes.mjs --dry-run # print what would change +import { execFileSync } from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; + +const dryRun = process.argv.includes('--dry-run'); +const root = execFileSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' }).trim(); +const dir = path.join(root, 'contract-changes.d'); +const libPath = path.join(root, 'contracts/escrow/src/lib.rs'); +const PROVISIONAL_MIN = 1000; +const LEVELS = ['patch', 'minor', 'major']; + +const files = fs.existsSync(dir) + ? fs.readdirSync(dir).filter((f) => f.endsWith('.md') && f !== 'README.md').sort() + : []; +if (files.length === 0) { + console.log('No contract-change fragments to fold.'); + process.exit(0); +} + +const fragments = files.map((file) => { + const text = fs.readFileSync(path.join(dir, file), 'utf8'); + const m = text.match(/^bump:\s*(major|minor|patch)\s*\n---\s*\n([\s\S]*)$/); + if (!m) { + console.error(`${file}: expected a "bump: major|minor|patch" line, then "---", then the summary.`); + process.exit(1); + } + return { file, bump: m[1], summary: m[2].trim() }; +}); + +let lib = fs.readFileSync(libPath, 'utf8'); +const versionRe = /^pub const CONTRACT_VERSION: &str = "(\d+)\.(\d+)\.(\d+)";/m; +const vm = lib.match(versionRe); +if (!vm) { + console.error('Could not find CONTRACT_VERSION in lib.rs.'); + process.exit(1); +} +const level = fragments.reduce((max, f) => Math.max(max, LEVELS.indexOf(f.bump)), 0); +let [major, minor, patch] = vm.slice(1).map(Number); +if (level === 2) [major, minor, patch] = [major + 1, 0, 0]; +else if (level === 1) [minor, patch] = [minor + 1, 0]; +else patch += 1; +const oldVersion = vm.slice(1).join('.'); +const newVersion = `${major}.${minor}.${patch}`; +lib = lib.replace(versionRe, `pub const CONTRACT_VERSION: &str = "${newVersion}";`); + +const enumRe = /^pub enum Error \{([\s\S]*?)^\}/m; +const body = lib.match(enumRe)[1]; +const variants = [...body.matchAll(/^(\s*)([A-Z][A-Za-z0-9]*)(\s*=\s*)(\d+)(\s*,)/gm)]; +let next = Math.max(0, ...variants.map((v) => Number(v[4])).filter((c) => c < PROVISIONAL_MIN)) + 1; +const renumbered = []; +const byCode = variants.filter((v) => Number(v[4]) >= PROVISIONAL_MIN).sort((a, b) => a[4] - b[4]); +const finalCode = new Map(byCode.map((v) => [v[2], next++])); +const newBody = body.replace(/^(\s*)([A-Z][A-Za-z0-9]*)(\s*=\s*)(\d+)(\s*,)/gm, (all, ws, name, eq, code, comma) => { + if (!finalCode.has(name)) return all; + renumbered.push(`Error::${name} ${code} -> ${finalCode.get(name)}`); + return `${ws}${name}${eq}${finalCode.get(name)}${comma}`; +}); +lib = lib.replace(enumRe, (all) => all.replace(body, newBody)); + +const entry = [ + `Contract ${newVersion} (was ${oldVersion}), folded from ${files.length} change(s):`, + '', + ...fragments.map((f) => `- ${f.summary.replace(/\s*\n\s*/g, ' ')}`), + ...(renumbered.length ? ['', `Final error codes: ${renumbered.join(', ')}.`] : []), + '', +].join('\n'); + +console.log(`CONTRACT_VERSION ${oldVersion} -> ${newVersion} (${LEVELS[level]})`); +for (const r of renumbered) console.log(` ${r}`); +for (const f of fragments) console.log(` ${f.bump.padEnd(5)} ${f.file}`); +if (dryRun) process.exit(0); + +fs.writeFileSync(libPath, lib); +fs.writeFileSync(path.join(root, 'changelog.d', `contract-${newVersion}.md`), entry); +for (const f of files) fs.rmSync(path.join(dir, f)); +console.log(`\nFolded ${files.length} fragment(s). Now run cargo test (snapshots) and regenerate the SDK bindings.`); diff --git a/sdk/src/generated/contract-client.ts b/sdk/src/generated/contract-client.ts index f995b60b..ec53275b 100644 --- a/sdk/src/generated/contract-client.ts +++ b/sdk/src/generated/contract-client.ts @@ -66,6 +66,15 @@ export const Errors = { * invoked. The release transaction (including its transfer) rolls back. */ 9: {message:"CallbackFailed"}, + /** + * `new_payee` is invalid: it is either the contract's own address + * or the payer's address. The contract address can never sign to + * accept a payout; the payer is excluded so a payer cannot redirect + * the release destination to themselves via a colluding payee. + * Provisional code (issue #45 × 100); the maintainer fold assigns the + * final number — see contract-changes.d/README.md. + */ + 4500: {message:"InvalidNewPayee"}, 12: {message:"Overflow"}, /** * The releaser set is empty, or `threshold` is 0 or larger than the @@ -170,7 +179,12 @@ export const Errors = { * contract itself, or an amount that would overflow the fee math — * see docs/adr/0010. */ - 35: {message:"InvalidFee"} + 35: {message:"InvalidFee"}, + /** + * An outbound release transfer failed; the funded escrow remains + * retryable and may still use its refund path. + */ + 36: {message:"Undeliverable"} } @@ -535,6 +549,31 @@ export interface Client { */ create_escrows: ({payer, items}: {payer: string, items: Array}, options?: MethodOptions) => Promise>>> + /** + * Construct and simulate a transfer_payee transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. + * Lets the current `payee` reassign future payout rights to a new + * address. Only the current `payee` may authorise this — no one + * else (not the payer, not the releaser) can redirect where a + * release will go (see invariant I1 and docs/threat-model.md). + * + * Restrictions: + * - Only while the escrow is `Funded` (no effect after release or + * refund; the transfer is a payout-claim reassignment, not an + * undo of a settlement). + * - `new_payee` may not be the contract's own address (it can never + * sign to claim funds) or the `payer`'s address (preventing a + * payer from using a colluding payee to redirect the escrow to + * themselves). + * + * This helps a payee who is *rotating* their wallet — it does NOT + * help a payee who has already *lost* their key and can no longer + * sign: they cannot authorise this call. Key loss is an operational + * risk the payee must mitigate off-chain before it happens. + * + * Emits a `pay_xfer` event with `(escrow_id, old_payee, new_payee)`. + */ + transfer_payee: ({escrow_id, current_payee, new_payee}: {escrow_id: u64, current_payee: string, new_payee: string}, options?: MethodOptions) => Promise>> + /** * Construct and simulate a rotate_releaser transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. * Rotates a funded escrow's releaser. Both the current releaser and @@ -641,7 +680,7 @@ export class Client extends ContractClient { } constructor(public readonly options: ContractClientOptions) { super( - new ContractSpec([ "AAAABAAAAAAAAAAAAAAABUVycm9yAAAAAAAAIQAAAAAAAAAITm90Rm91bmQAAAABAAAAAAAAAA1JbnZhbGlkQW1vdW50AAAAAAAAAgAAAAAAAAAMVW5hdXRob3JpemVkAAAAAwAAAAAAAAAJTm90RnVuZGVkAAAAAAAABAAAALpgcmVmdW5kX2FmdGVyYCB3YXMgbm90IHN0cmljdGx5IGluIHRoZSBmdXR1cmUgYXQgY3JlYXRpb24g4oCUIHNlZQpkb2NzL2Fkci8wMDA0OiBhIGRlYWRsaW5lIHRoYXQgaGFzIGFscmVhZHkgcGFzc2VkIHdvdWxkIGxldAphbnlvbmUgcmVmdW5kIHRoZSBlc2Nyb3cgYmVmb3JlIHRoZSByZWxlYXNlciBjb3VsZCBldmVyIGFjdC4AAAAAABJJbnZhbGlkUmVmdW5kQWZ0ZXIAAAAAAAUAAACjVGhlIGNvbnRyYWN0J3MgdG9rZW4gYmFsYW5jZSBkaWRuJ3QgcmlzZSBieSBleGFjdGx5IGBhbW91bnRgCmFjcm9zcyBgY3JlYXRlX2VzY3Jvd2AncyB0cmFuc2ZlciAoYSBseWluZyBvciBzaG9ydC1kZWxpdmVyaW5nCnRva2VuKSDigJQgc2VlIGRvY3MvdGhyZWF0LW1vZGVsLm1kIFQ1LgAAAAAPQmFsYW5jZU1pc21hdGNoAAAAAAYAAAEAYGNvbmRpdGlvbl9yZWZgIGV4Y2VlZGVkIHRoZSBtYXhpbXVtIGFsbG93ZWQgbGVuZ3RoIChjdXJyZW50bHkKNjQgYnl0ZXMpIOKAlCBzZWUgZG9jcy90aHJlYXQtbW9kZWwubWQgVDEwIGFuZCBST0FETUFQLm1kIFBoYXNlIEU1LgpCb3VuZGVkIHRvIGtlZXAgc3RvcmFnZSBhbmQgZXZlbnQgY29zdHMgcHJlZGljdGFibGU7IHJlamVjdCBhdApjcmVhdGlvbiBzbyBubyBvbi1jaGFpbiBzdG9yYWdlIGlzIHdhc3RlZCBvbiBhbiBvdmVyc2l6ZWQgcmVmLgAAABNDb25kaXRpb25SZWZUb29Mb25nAAAAAAcAAAA2YHRva2VuYCBpcyBub3QgaW4gdGhlIGltbXV0YWJsZSBkZXBsb3ktdGltZSBhbGxvd2xpc3QuAAAAAAAPRGlzYWxsb3dlZFRva2VuAAAAAAgAAACDVGhlIG9wdGVkLWluIHBheWVlIGNhbGxiYWNrIHJldHVybmVkIGFuIGVycm9yIG9yIGNvdWxkIG5vdCBiZQppbnZva2VkLiBUaGUgcmVsZWFzZSB0cmFuc2FjdGlvbiAoaW5jbHVkaW5nIGl0cyB0cmFuc2Zlcikgcm9sbHMgYmFjay4AAAAADkNhbGxiYWNrRmFpbGVkAAAAAAAJAAAAAAAAAAhPdmVyZmxvdwAAAAwAAABsVGhlIHJlbGVhc2VyIHNldCBpcyBlbXB0eSwgb3IgYHRocmVzaG9sZGAgaXMgMCBvciBsYXJnZXIgdGhhbiB0aGUKbnVtYmVyIG9mIHJlbGVhc2VycyDigJQgc2VlIGRvY3MvYWRyLzAwMDcuAAAAEEludmFsaWRUaHJlc2hvbGQAAAANAAAAQ01vcmUgdGhhbiBgTUFYX1JFTEVBU0VSU2AgKDEwKSBhZGRyZXNzZXMgd2VyZSBzdXBwbGllZCBhdCBjcmVhdGlvbi4AAAAAEFRvb01hbnlSZWxlYXNlcnMAAAAOAAAAn0Zld2VyIGRpc3RpbmN0IGFwcHJvdmFscyB3ZXJlIHN1cHBsaWVkIHRoYW4gdGhlIGVzY3JvdydzIHRocmVzaG9sZCwKb3IgYSBzaW5nbGUgcmVsZWFzZXIgdHJpZWQgdG8gc2V0dGxlIGEgcXVvcnVtIGVzY3JvdyB0aHJvdWdoIHRoZQpzaW5nbGUtY2FsbGVyIGVudHJ5IHBvaW50LgAAAAAPVGhyZXNob2xkTm90TWV0AAAAAA8AAABoVGhlIHNhbWUgYWRkcmVzcyBhcHBlYXJlZCB0d2ljZSBpbiBvbmUgYXBwcm92YWwgbGlzdC4gRHVwbGljYXRlcwpuZXZlciBjb3VudCB0d2ljZSB0b3dhcmQgdGhlIHRocmVzaG9sZC4AAAARRHVwbGljYXRlQXBwcm92ZXIAAAAAAAAQAAAAQFRoZSBzYW1lIGFkZHJlc3MgYXBwZWFyZWQgdHdpY2UgaW4gdGhlIHJlbGVhc2VyIHNldCBhdCBjcmVhdGlvbi4AAAARRHVwbGljYXRlUmVsZWFzZXIAAAAAAAARAAAAAAAAABJBY2NlcHRhbmNlUmVxdWlyZWQAAAAAABIAAAAAAAAAF0FjY2VwdGFuY2VOb3RDb25maWd1cmVkAAAAABMAAAAAAAAAD0FscmVhZHlBY2NlcHRlZAAAAAAUAAAAOFRoZSBuZXcgcmVsZWFzZXIgY2Fubm90IGJlIHRoZSBlc2Nyb3cgY29udHJhY3Qgb3IgcGF5ZWUuAAAAD0ludmFsaWRSZWxlYXNlcgAAAAAYAAAAfGByZWZ1bmRfdG9gIHdhcyB0aGUgZXNjcm93IGNvbnRyYWN0J3Mgb3duIGFkZHJlc3Mg4oCUIGZ1bmRzIHNlbnQKdGhlcmUgb24gcmVmdW5kIGNvdWxkIG5ldmVyIGJlIG1vdmVkIGFnYWluIChkb2NzL2Fkci8wMDA5KS4AAAAPSW52YWxpZFJlZnVuZFRvAAAAABUAAABEVGhlIGNvbmZpZ3VyZWQgcmVsZWFzZSB0aW1lIGlzIGluIHRoZSBwYXN0IG9yIGFmdGVyIHRoZSByZWZ1bmQgdGltZS4AAAAXSW52YWxpZFJlbGVhc2VOb3RCZWZvcmUAAAAAFgAAADFSZWxlYXNlIHdhcyBhdHRlbXB0ZWQgYmVmb3JlIHRoZSBjb25maWd1cmVkIHRpbWUuAAAAAAAAD1JlbGVhc2VUb29FYXJseQAAAAAXAAAArUEgYmF0Y2ggY2FsbCB3YXMgcGFzc2VkIG1vcmUgdGhhbiBgTUFYX0JBVENIX1NJWkVgIGl0ZW1zIOKAlCBzZWUKZG9jcy9hZHIvMDAwNS4gQ2FsbGVycyBtdXN0IGNodW5rLiBBcHBlbmRlZCBhdCB0aGUgZW5kIHNvIGV4aXN0aW5nCmRpc2NyaW1pbmFudHMga2VlcCB0aGVpciBvbi1jaGFpbiB2YWx1ZXMuAAAAAAAADUJhdGNoVG9vTGFyZ2UAAAAAAAAZAAAAiGBjb250cmlidXRlYC9gY2xhaW1fcmVmdW5kYC9gZ2V0X2NvbnRyaWJ1dGlvbmAgb24gYSBub24tcG9vbGVkCmVzY3Jvdywgb3IgYGdldF9wb29sZWRgIG9uIGEgbm9uLXBvb2xlZC91bmtub3duIGlkIOKAlCBzZWUKZG9jcy9hZHIvMDAxMS4AAAAJTm90UG9vbGVkAAAAAAAAGgAAAL9BIGNvbnRyaWJ1dGlvbiBhcnJpdmVkIGFmdGVyIHRoZSBwb29sZWQgZXNjcm93J3MgZnVuZGluZyBkZWFkbGluZS4KTGF0ZSBjb250cmlidXRpb25zIGNhbiBuZXZlciBiZSBhY2NlcHRlZDogdGhlIHJvdW5kJ3Mgb3V0Y29tZQoocmVsZWFzZSB2cyBwZXItY29udHJpYnV0b3IgcmVmdW5kcykgaXMgZml4ZWQgYXQgdGhlIGRlYWRsaW5lLgAAAAAVRnVuZGluZ0RlYWRsaW5lUGFzc2VkAAAAAAAAGwAAAL9BIGNvbnRyaWJ1dGlvbiB3b3VsZCBwdXNoIHRoZSBwb29sZWQgdG90YWwgcGFzdCB0aGUgZnVuZGluZyB0YXJnZXQKKG92ZXJmdW5kaW5nIGlzIHJlamVjdGVkLCBub3QgYWNjZXB0ZWQpLCB0aGUgdGFyZ2V0IGlzIGFscmVhZHkgbWV0LApvciBhIHJlZnVuZCB3YXMgY2xhaW1lZCBvbiBhIGZ1bGx5IGZ1bmRlZCBwb29sZWQgZXNjcm93LgAAAAAURnVuZGluZ1RhcmdldFJlYWNoZWQAAAAcAAAAdGByZWxlYXNlYCBvbiBhIHBvb2xlZCBlc2Nyb3cgd2hvc2UgZnVuZGVkIHRvdGFsIGlzIGJlbG93IHRoZQpmdW5kaW5nIHRhcmdldCDigJQgcGFydGlhbCBmdW5kaW5nIGlzIG5ldmVyIHJlbGVhc2FibGUuAAAAEUZ1bmRpbmdJbmNvbXBsZXRlAAAAAAAAHQAAAIZgY2xhaW1fcmVmdW5kYCBiZWZvcmUgdGhlIGZ1bmRpbmcgZGVhZGxpbmUgcGFzc2VkIG9uIGEgcm91bmQgdGhhdAppcyBzdGlsbCAob3Igbm93IGZ1bGx5KSBmdW5kZWQuIENsYWltcyBvcGVuIG9ubHkgZm9yIGEgZmFpbGVkIHJvdW5kLgAAAAAADVJlZnVuZE5vdE9wZW4AAAAAAAAeAAAAM1RoZSBzYW1lIGNvbnRyaWJ1dG9yIHRyaWVkIHRvIGNsYWltIGEgcmVmdW5kIHR3aWNlLgAAAAAPQWxyZWFkeVJlZnVuZGVkAAAAAB8AAAA7YGNsYWltX3JlZnVuZGAgYnkgYW4gYWRkcmVzcyB3aXRoIG5vIHJlY29yZGVkIGNvbnRyaWJ1dGlvbi4AAAAADk5vQ29udHJpYnV0aW9uAAAAAAAgAAAA82ByZWZ1bmRgL2ByZWZ1bmRfd2l0aF9hcHByb3ZhbHNgL2BjYW5jZWxgL2B0b3BfdXBgIG9uIGEgcG9vbGVkCmVzY3JvdzogcHVzaGluZyB0aGUgd2hvbGUgcG9vbGVkIHRvdGFsIHRvIG9uZSBhZGRyZXNzIHdvdWxkIHZpb2xhdGUKcGVyLWNvbnRyaWJ1dG9yIGFjY291bnRpbmcuIFBvb2xlZCByZWZ1bmRzIGFyZSBwdWxsLWJhc2VkCihgY2xhaW1fcmVmdW5kYCk7IHBvb2xlZCBmdW5kaW5nIGlzIGBjb250cmlidXRlYC1vbmx5LgAAAAAVTm90U3VwcG9ydGVkRm9yUG9vbGVkAAAAAAAAIQAAAEBUaGUgZnVuZGluZyBkZWFkbGluZSB3YXMgbm90IHN0cmljdGx5IGluIHRoZSBmdXR1cmUgYXQgY3JlYXRpb24uAAAAFkludmFsaWRGdW5kaW5nRGVhZGxpbmUAAAAAACIAAADSVGhlIG9wdGlvbmFsIHByb3RvY29sIGZlZSB3YXMgbWlzY29uZmlndXJlZCBhdCBjcmVhdGlvbjogYGJwc2AKYWJvdmUgW2BNQVhfRkVFX0JQU2BdICgxMCAlKSwgYSByZWNpcGllbnQgZXF1YWwgdG8gdGhlIGVzY3Jvdwpjb250cmFjdCBpdHNlbGYsIG9yIGFuIGFtb3VudCB0aGF0IHdvdWxkIG92ZXJmbG93IHRoZSBmZWUgbWF0aCDigJQKc2VlIGRvY3MvYWRyLzAwMTAuAAAAAAAKSW52YWxpZEZlZQAAAAAAIw==", + new ContractSpec([ "AAAABAAAAAAAAAAAAAAABUVycm9yAAAAAAAAIwAAAAAAAAAITm90Rm91bmQAAAABAAAAAAAAAA1JbnZhbGlkQW1vdW50AAAAAAAAAgAAAAAAAAAMVW5hdXRob3JpemVkAAAAAwAAAAAAAAAJTm90RnVuZGVkAAAAAAAABAAAALpgcmVmdW5kX2FmdGVyYCB3YXMgbm90IHN0cmljdGx5IGluIHRoZSBmdXR1cmUgYXQgY3JlYXRpb24g4oCUIHNlZQpkb2NzL2Fkci8wMDA0OiBhIGRlYWRsaW5lIHRoYXQgaGFzIGFscmVhZHkgcGFzc2VkIHdvdWxkIGxldAphbnlvbmUgcmVmdW5kIHRoZSBlc2Nyb3cgYmVmb3JlIHRoZSByZWxlYXNlciBjb3VsZCBldmVyIGFjdC4AAAAAABJJbnZhbGlkUmVmdW5kQWZ0ZXIAAAAAAAUAAACjVGhlIGNvbnRyYWN0J3MgdG9rZW4gYmFsYW5jZSBkaWRuJ3QgcmlzZSBieSBleGFjdGx5IGBhbW91bnRgCmFjcm9zcyBgY3JlYXRlX2VzY3Jvd2AncyB0cmFuc2ZlciAoYSBseWluZyBvciBzaG9ydC1kZWxpdmVyaW5nCnRva2VuKSDigJQgc2VlIGRvY3MvdGhyZWF0LW1vZGVsLm1kIFQ1LgAAAAAPQmFsYW5jZU1pc21hdGNoAAAAAAYAAAEAYGNvbmRpdGlvbl9yZWZgIGV4Y2VlZGVkIHRoZSBtYXhpbXVtIGFsbG93ZWQgbGVuZ3RoIChjdXJyZW50bHkKNjQgYnl0ZXMpIOKAlCBzZWUgZG9jcy90aHJlYXQtbW9kZWwubWQgVDEwIGFuZCBST0FETUFQLm1kIFBoYXNlIEU1LgpCb3VuZGVkIHRvIGtlZXAgc3RvcmFnZSBhbmQgZXZlbnQgY29zdHMgcHJlZGljdGFibGU7IHJlamVjdCBhdApjcmVhdGlvbiBzbyBubyBvbi1jaGFpbiBzdG9yYWdlIGlzIHdhc3RlZCBvbiBhbiBvdmVyc2l6ZWQgcmVmLgAAABNDb25kaXRpb25SZWZUb29Mb25nAAAAAAcAAAA2YHRva2VuYCBpcyBub3QgaW4gdGhlIGltbXV0YWJsZSBkZXBsb3ktdGltZSBhbGxvd2xpc3QuAAAAAAAPRGlzYWxsb3dlZFRva2VuAAAAAAgAAACDVGhlIG9wdGVkLWluIHBheWVlIGNhbGxiYWNrIHJldHVybmVkIGFuIGVycm9yIG9yIGNvdWxkIG5vdCBiZQppbnZva2VkLiBUaGUgcmVsZWFzZSB0cmFuc2FjdGlvbiAoaW5jbHVkaW5nIGl0cyB0cmFuc2Zlcikgcm9sbHMgYmFjay4AAAAADkNhbGxiYWNrRmFpbGVkAAAAAAAJAAABdWBuZXdfcGF5ZWVgIGlzIGludmFsaWQ6IGl0IGlzIGVpdGhlciB0aGUgY29udHJhY3QncyBvd24gYWRkcmVzcwpvciB0aGUgcGF5ZXIncyBhZGRyZXNzLiBUaGUgY29udHJhY3QgYWRkcmVzcyBjYW4gbmV2ZXIgc2lnbiB0bwphY2NlcHQgYSBwYXlvdXQ7IHRoZSBwYXllciBpcyBleGNsdWRlZCBzbyBhIHBheWVyIGNhbm5vdCByZWRpcmVjdAp0aGUgcmVsZWFzZSBkZXN0aW5hdGlvbiB0byB0aGVtc2VsdmVzIHZpYSBhIGNvbGx1ZGluZyBwYXllZS4KUHJvdmlzaW9uYWwgY29kZSAoaXNzdWUgIzQ1IMOXIDEwMCk7IHRoZSBtYWludGFpbmVyIGZvbGQgYXNzaWducyB0aGUKZmluYWwgbnVtYmVyIOKAlCBzZWUgY29udHJhY3QtY2hhbmdlcy5kL1JFQURNRS5tZC4AAAAAAAAPSW52YWxpZE5ld1BheWVlAAAAEZQAAAAAAAAACE92ZXJmbG93AAAADAAAAGxUaGUgcmVsZWFzZXIgc2V0IGlzIGVtcHR5LCBvciBgdGhyZXNob2xkYCBpcyAwIG9yIGxhcmdlciB0aGFuIHRoZQpudW1iZXIgb2YgcmVsZWFzZXJzIOKAlCBzZWUgZG9jcy9hZHIvMDAwNy4AAAAQSW52YWxpZFRocmVzaG9sZAAAAA0AAABDTW9yZSB0aGFuIGBNQVhfUkVMRUFTRVJTYCAoMTApIGFkZHJlc3NlcyB3ZXJlIHN1cHBsaWVkIGF0IGNyZWF0aW9uLgAAAAAQVG9vTWFueVJlbGVhc2VycwAAAA4AAACfRmV3ZXIgZGlzdGluY3QgYXBwcm92YWxzIHdlcmUgc3VwcGxpZWQgdGhhbiB0aGUgZXNjcm93J3MgdGhyZXNob2xkLApvciBhIHNpbmdsZSByZWxlYXNlciB0cmllZCB0byBzZXR0bGUgYSBxdW9ydW0gZXNjcm93IHRocm91Z2ggdGhlCnNpbmdsZS1jYWxsZXIgZW50cnkgcG9pbnQuAAAAAA9UaHJlc2hvbGROb3RNZXQAAAAADwAAAGhUaGUgc2FtZSBhZGRyZXNzIGFwcGVhcmVkIHR3aWNlIGluIG9uZSBhcHByb3ZhbCBsaXN0LiBEdXBsaWNhdGVzCm5ldmVyIGNvdW50IHR3aWNlIHRvd2FyZCB0aGUgdGhyZXNob2xkLgAAABFEdXBsaWNhdGVBcHByb3ZlcgAAAAAAABAAAABAVGhlIHNhbWUgYWRkcmVzcyBhcHBlYXJlZCB0d2ljZSBpbiB0aGUgcmVsZWFzZXIgc2V0IGF0IGNyZWF0aW9uLgAAABFEdXBsaWNhdGVSZWxlYXNlcgAAAAAAABEAAAAAAAAAEkFjY2VwdGFuY2VSZXF1aXJlZAAAAAAAEgAAAAAAAAAXQWNjZXB0YW5jZU5vdENvbmZpZ3VyZWQAAAAAEwAAAAAAAAAPQWxyZWFkeUFjY2VwdGVkAAAAABQAAAA4VGhlIG5ldyByZWxlYXNlciBjYW5ub3QgYmUgdGhlIGVzY3JvdyBjb250cmFjdCBvciBwYXllZS4AAAAPSW52YWxpZFJlbGVhc2VyAAAAABgAAAB8YHJlZnVuZF90b2Agd2FzIHRoZSBlc2Nyb3cgY29udHJhY3QncyBvd24gYWRkcmVzcyDigJQgZnVuZHMgc2VudAp0aGVyZSBvbiByZWZ1bmQgY291bGQgbmV2ZXIgYmUgbW92ZWQgYWdhaW4gKGRvY3MvYWRyLzAwMDkpLgAAAA9JbnZhbGlkUmVmdW5kVG8AAAAAFQAAAERUaGUgY29uZmlndXJlZCByZWxlYXNlIHRpbWUgaXMgaW4gdGhlIHBhc3Qgb3IgYWZ0ZXIgdGhlIHJlZnVuZCB0aW1lLgAAABdJbnZhbGlkUmVsZWFzZU5vdEJlZm9yZQAAAAAWAAAAMVJlbGVhc2Ugd2FzIGF0dGVtcHRlZCBiZWZvcmUgdGhlIGNvbmZpZ3VyZWQgdGltZS4AAAAAAAAPUmVsZWFzZVRvb0Vhcmx5AAAAABcAAACtQSBiYXRjaCBjYWxsIHdhcyBwYXNzZWQgbW9yZSB0aGFuIGBNQVhfQkFUQ0hfU0laRWAgaXRlbXMg4oCUIHNlZQpkb2NzL2Fkci8wMDA1LiBDYWxsZXJzIG11c3QgY2h1bmsuIEFwcGVuZGVkIGF0IHRoZSBlbmQgc28gZXhpc3RpbmcKZGlzY3JpbWluYW50cyBrZWVwIHRoZWlyIG9uLWNoYWluIHZhbHVlcy4AAAAAAAANQmF0Y2hUb29MYXJnZQAAAAAAABkAAACIYGNvbnRyaWJ1dGVgL2BjbGFpbV9yZWZ1bmRgL2BnZXRfY29udHJpYnV0aW9uYCBvbiBhIG5vbi1wb29sZWQKZXNjcm93LCBvciBgZ2V0X3Bvb2xlZGAgb24gYSBub24tcG9vbGVkL3Vua25vd24gaWQg4oCUIHNlZQpkb2NzL2Fkci8wMDExLgAAAAlOb3RQb29sZWQAAAAAAAAaAAAAv0EgY29udHJpYnV0aW9uIGFycml2ZWQgYWZ0ZXIgdGhlIHBvb2xlZCBlc2Nyb3cncyBmdW5kaW5nIGRlYWRsaW5lLgpMYXRlIGNvbnRyaWJ1dGlvbnMgY2FuIG5ldmVyIGJlIGFjY2VwdGVkOiB0aGUgcm91bmQncyBvdXRjb21lCihyZWxlYXNlIHZzIHBlci1jb250cmlidXRvciByZWZ1bmRzKSBpcyBmaXhlZCBhdCB0aGUgZGVhZGxpbmUuAAAAABVGdW5kaW5nRGVhZGxpbmVQYXNzZWQAAAAAAAAbAAAAv0EgY29udHJpYnV0aW9uIHdvdWxkIHB1c2ggdGhlIHBvb2xlZCB0b3RhbCBwYXN0IHRoZSBmdW5kaW5nIHRhcmdldAoob3ZlcmZ1bmRpbmcgaXMgcmVqZWN0ZWQsIG5vdCBhY2NlcHRlZCksIHRoZSB0YXJnZXQgaXMgYWxyZWFkeSBtZXQsCm9yIGEgcmVmdW5kIHdhcyBjbGFpbWVkIG9uIGEgZnVsbHkgZnVuZGVkIHBvb2xlZCBlc2Nyb3cuAAAAABRGdW5kaW5nVGFyZ2V0UmVhY2hlZAAAABwAAAB0YHJlbGVhc2VgIG9uIGEgcG9vbGVkIGVzY3JvdyB3aG9zZSBmdW5kZWQgdG90YWwgaXMgYmVsb3cgdGhlCmZ1bmRpbmcgdGFyZ2V0IOKAlCBwYXJ0aWFsIGZ1bmRpbmcgaXMgbmV2ZXIgcmVsZWFzYWJsZS4AAAARRnVuZGluZ0luY29tcGxldGUAAAAAAAAdAAAAhmBjbGFpbV9yZWZ1bmRgIGJlZm9yZSB0aGUgZnVuZGluZyBkZWFkbGluZSBwYXNzZWQgb24gYSByb3VuZCB0aGF0CmlzIHN0aWxsIChvciBub3cgZnVsbHkpIGZ1bmRlZC4gQ2xhaW1zIG9wZW4gb25seSBmb3IgYSBmYWlsZWQgcm91bmQuAAAAAAANUmVmdW5kTm90T3BlbgAAAAAAAB4AAAAzVGhlIHNhbWUgY29udHJpYnV0b3IgdHJpZWQgdG8gY2xhaW0gYSByZWZ1bmQgdHdpY2UuAAAAAA9BbHJlYWR5UmVmdW5kZWQAAAAAHwAAADtgY2xhaW1fcmVmdW5kYCBieSBhbiBhZGRyZXNzIHdpdGggbm8gcmVjb3JkZWQgY29udHJpYnV0aW9uLgAAAAAOTm9Db250cmlidXRpb24AAAAAACAAAADzYHJlZnVuZGAvYHJlZnVuZF93aXRoX2FwcHJvdmFsc2AvYGNhbmNlbGAvYHRvcF91cGAgb24gYSBwb29sZWQKZXNjcm93OiBwdXNoaW5nIHRoZSB3aG9sZSBwb29sZWQgdG90YWwgdG8gb25lIGFkZHJlc3Mgd291bGQgdmlvbGF0ZQpwZXItY29udHJpYnV0b3IgYWNjb3VudGluZy4gUG9vbGVkIHJlZnVuZHMgYXJlIHB1bGwtYmFzZWQKKGBjbGFpbV9yZWZ1bmRgKTsgcG9vbGVkIGZ1bmRpbmcgaXMgYGNvbnRyaWJ1dGVgLW9ubHkuAAAAABVOb3RTdXBwb3J0ZWRGb3JQb29sZWQAAAAAAAAhAAAAQFRoZSBmdW5kaW5nIGRlYWRsaW5lIHdhcyBub3Qgc3RyaWN0bHkgaW4gdGhlIGZ1dHVyZSBhdCBjcmVhdGlvbi4AAAAWSW52YWxpZEZ1bmRpbmdEZWFkbGluZQAAAAAAIgAAANJUaGUgb3B0aW9uYWwgcHJvdG9jb2wgZmVlIHdhcyBtaXNjb25maWd1cmVkIGF0IGNyZWF0aW9uOiBgYnBzYAphYm92ZSBbYE1BWF9GRUVfQlBTYF0gKDEwICUpLCBhIHJlY2lwaWVudCBlcXVhbCB0byB0aGUgZXNjcm93CmNvbnRyYWN0IGl0c2VsZiwgb3IgYW4gYW1vdW50IHRoYXQgd291bGQgb3ZlcmZsb3cgdGhlIGZlZSBtYXRoIOKAlApzZWUgZG9jcy9hZHIvMDAxMC4AAAAAAApJbnZhbGlkRmVlAAAAAAAjAAAAa0FuIG91dGJvdW5kIHJlbGVhc2UgdHJhbnNmZXIgZmFpbGVkOyB0aGUgZnVuZGVkIGVzY3JvdyByZW1haW5zCnJldHJ5YWJsZSBhbmQgbWF5IHN0aWxsIHVzZSBpdHMgcmVmdW5kIHBhdGguAAAAAA1VbmRlbGl2ZXJhYmxlAAAAAAAAJA==", "AAAAAQAAAHJPbmUgZW50cnkgb2YgYSBgY3JlYXRlX2VzY3Jvd3NgIGJhdGNoLiBNaXJyb3JzIHRoZSBzaW5nbGUtZXNjcm93CmNyZWF0aW9uIHBhcmFtZXRlcnMgbWludXMgdGhlIGJhdGNoLXdpZGUgYHBheWVyYC4AAAAAAAAAAAAKQ3JlYXRlSXRlbQAAAAAABgAAAAAAAAAGYW1vdW50AAAAAAALAAAAAAAAAA1jb25kaXRpb25fcmVmAAAAAAAAEAAAAAAAAAAFcGF5ZWUAAAAAAAATAAAAAAAAAAxyZWZ1bmRfYWZ0ZXIAAAPoAAAABgAAAAAAAAAIcmVsZWFzZXIAAAATAAAAAAAAAAV0b2tlbgAAAAAAABM=", "AAAAAQAAAAAAAAAAAAAACkVzY3Jvd0RhdGEAAAAAABAAAAA1TGVkZ2VyIHRpbWVzdGFtcCBhdCB3aGljaCB0aGUgcGF5ZWUgYWNjZXB0ZWQsIGlmIGFueS4AAAAAAAALYWNjZXB0ZWRfYXQAAAAD6AAAAAYAAAAAAAAABmFtb3VudAAAAAAACwAAAAAAAAANY29uZGl0aW9uX3JlZgAAAAAAABAAAACnRmVlIHJhdGUgaW4gYmFzaXMgcG9pbnRzIG9mIGBhbW91bnRgIChjYXBwZWQgYXQgW2BNQVhfRkVFX0JQU2BdCj0gMTAgJSksIHRha2VuIG9uY2UgYXQgcmVsZWFzZSwgcm91bmRlZCAqKmRvd24qKiB3aXRoIHRoZQpyZW1haW5kZXIgdG8gdGhlIHBheWVlIOKAlCBzZWUgZG9jcy9hZHIvMDAxMC4AAAAAB2ZlZV9icHMAAAAD6AAAAAQAAAF7T3B0aW9uYWwgcHJvdG9jb2wgZmVlIHJlY2lwaWVudCwgc2V0IG9uY2UgYXQgYGNyZWF0ZV9lc2Nyb3dgIHRpbWUKYW5kIHBhaWQgYXQgcmVsZWFzZSAobmV2ZXIgb24gcmVmdW5kKSDigJQgc2VlIGRvY3MvYWRyLzAwMTAuIFN0b3JlZAphcyBvbmUgKHJlY2lwaWVudCwgYnBzKSBwYWlyIGluIHR3byBmaWVsZHMgc28gYm90aCBhcmUgYWx3YXlzIHNldAp0b2dldGhlciBvciBub3QgYXQgYWxsIChjcmVhdGlvbi10aW1lIHJ1bGUsIGBJbnZhbGlkRmVlYApvdGhlcndpc2UpLiBgTm9uZWAgKHdpdGggbm8gYnBzKSBtZWFucyBubyBmZWU6IHRoZSBwYXllZSByZWNlaXZlcwp0aGUgZnVsbCBgYW1vdW50YCwgZXhhY3RseSBhcyBiZWZvcmUgdGhpcyBmaWVsZCBleGlzdGVkLgAAAAANZmVlX3JlY2lwaWVudAAAAAAAA+gAAAATAAAAhklmIHRydWUsIGludm9rZSB0aGUgY29udHJhY3QgcGF5ZWUncyBgb25fZXNjcm93X3JlbGVhc2VkYCBob29rIGFmdGVyCnRoZSBwYXlvdXQgdHJhbnNmZXIuIEEgZmFpbGVkIGNhbGxiYWNrIHJldmVydHMgdGhlIHdob2xlIHJlbGVhc2UuAAAAAAAMbm90aWZ5X3BheWVlAAAAAQAAAAAAAAAFcGF5ZWUAAAAAAAATAAAAelRoZSBmdW5kZXI6IGF1dGhvcmlzZXMgYW5kIHBheXMgZm9yIHRoZSBlc2Nyb3cgYXQgY3JlYXRpb24uIEFsc28KdGhlIHJlZnVuZCBkZXN0aW5hdGlvbiB1bmxlc3MgYHJlZnVuZF90b2Agc2F5cyBvdGhlcndpc2UuAAAAAAAFcGF5ZXIAAAAAAAATAAAAxU9wdGlvbmFsIGRlYWRsaW5lICh1bml4IHNlY29uZHMpIGFmdGVyIHdoaWNoIGByZWZ1bmRgIG9wZW5zIHRvCmFueW9uZSDigJQgc3RpbGwgb25seSB0byBgcmVmdW5kX3RvYC4gYE5vbmVgIG1lYW5zIG5vIHRpbWVvdXQsCmJlaGF2aW91ciBpZGVudGljYWwgdG8gYmVmb3JlIHRoaXMgZmllbGQgZXhpc3RlZCDigJQgc2VlIGRvY3MvYWRyLzAwMDQuAAAAAAAADHJlZnVuZF9hZnRlcgAAA+gAAAAGAAAA4VdoZXJlICoqZXZlcnkqKiByZWZ1bmQgcGF0aCAocmVsZWFzZXIsIHRpbWVvdXQpIHNlbmRzIHRoZSBmdW5kcy4KRml4ZWQgYXQgY3JlYXRpb24gdW5kZXIgdGhlIGZ1bmRlcidzIGF1dGggYW5kIG5ldmVyIGNob3NlbiBhdApwYXlvdXQsIHNvIGludmFyaWFudCBJMSBob2xkczsgZGVmYXVsdHMgdG8gYHBheWVyYCB3aGVuIG9taXR0ZWQgYXQKY3JlYXRpb24g4oCUIHNlZSBkb2NzL2Fkci8wMDA5LgAAAAAAAAlyZWZ1bmRfdG8AAAAAAAATAAAANkVhcmxpZXN0IGxlZGdlciB0aW1lc3RhbXAgYXQgd2hpY2ggcmVsZWFzZSBpcyBhbGxvd2VkLgAAAAAAEnJlbGVhc2Vfbm90X2JlZm9yZQAAAAAD6AAAAAYAAAC9QWRkcmVzc2VzIHBlcm1pdHRlZCB0byBzZXR0bGUgdGhpcyBlc2Nyb3cg4oCUIHNlZSBkb2NzL2Fkci8wMDAyIGZvciB0aGUKcGVyLWVzY3JvdyByZWxlYXNlciwgYW5kIGRvY3MvYWRyLzAwMDcgZm9yIE0tb2YtTiBzZXRzLiBBIHBsYWluCnNpbmdsZS1yZWxlYXNlciBlc2Nyb3cgc3RvcmVzIGV4YWN0bHkgb25lIGVudHJ5IGhlcmUuAAAAAAAACXJlbGVhc2VycwAAAAAAA+oAAAATAAAAOVdoZXRoZXIgcmVsZWFzZSByZXF1aXJlcyB0aGUgcGF5ZWUncyBleHBsaWNpdCBhY2NlcHRhbmNlLgAAAAAAABNyZXF1aXJlc19hY2NlcHRhbmNlAAAAAAEAAAAAAAAABnN0YXR1cwAAAAAH0AAAAAxFc2Nyb3dTdGF0dXMAAAC6SG93IG1hbnkgKmRpc3RpbmN0KiBhZGRyZXNzZXMgZnJvbSBgcmVsZWFzZXJzYCBtdXN0IGF1dGhvcml6ZSBvbmUKc2V0dGxlbWVudC4gQWx3YXlzIGA+PSAxYCBhbmQgYDw9IHJlbGVhc2Vycy5sZW4oKWA7IGAxYCBtZWFucyBhbnkKc2luZ2xlIHJlbGVhc2VyIGNhbiBzZXR0bGUgKHRoZSBwcmUtcXVvcnVtIGJlaGF2aW91cikuAAAAAAAJdGhyZXNob2xkAAAAAAAABAAAAAAAAAAFdG9rZW4AAAAAAAAT", "AAAAAQAAAYBPbmUgZW50cnkgb2YgYSBgY3JlYXRlX2VzY3Jvd3NgIGJhdGNoLiBNaXJyb3JzIHRoZSBzaW5nbGUtZXNjcm93CmNyZWF0aW9uIHBhcmFtZXRlcnMgbWludXMgdGhlIGJhdGNoLXdpZGUgYHBheWVyYC4KSW1tdXRhYmxlIGZ1bmRpbmcgY29uZmlndXJhdGlvbiBvZiBhIHBvb2xlZCBlc2Nyb3cgKGlzc3VlICMxMTMsCmRvY3MvYWRyLzAwMTEpLiBFeGlzdGVuY2Ugb2YgdGhpcyByZWNvcmQgdW5kZXIgYERhdGFLZXk6OlBvb2xlZChpZClgIGlzCndoYXQgbWFrZXMgYW4gZXNjcm93ICJwb29sZWQiOyB0aGUgYWdncmVnYXRlIGZ1bmRlZCBhbW91bnQgbGl2ZXMgaW4KYEVzY3Jvd0RhdGEuYW1vdW50YCAob25lIHNvdXJjZSBvZiB0cnV0aCBzaGFyZWQgd2l0aCBgc2V0dGxlKClgKS4AAAAAAAAAClBvb2xlZERhdGEAAAAAAAIAAAEJVW5peCBzZWNvbmRzIHVudGlsIHdoaWNoIGBjb250cmlidXRlYCBpcyBhY2NlcHRlZC4gV2hlbiBpdCBwYXNzZXMKd2l0aCB0aGUgdGFyZ2V0IHVubWV0LCB0aGUgcm91bmQgaGFzIGZhaWxlZDogY29udHJpYnV0aW9ucyBhcmUKZnJvemVuIGZvcmV2ZXIgYW5kIGV2ZXJ5IGNvbnRyaWJ1dG9yIG1heSBwdWxsIHRoZWlyIGV4YWN0IHJlY29yZGVkCmFtb3VudCBiYWNrIHdpdGggYGNsYWltX3JlZnVuZGAg4oCUIHRoZSBlc2Nyb3cgY2FuIG5ldmVyIGJlIHJlbGVhc2VkLgAAAAAAABBmdW5kaW5nX2RlYWRsaW5lAAAABgAAAIFUb3RhbCB0aGUgY29udHJpYnV0b3JzIG11c3QgcmVhY2ggZm9yIHJlbGVhc2UgdG8gYmVjb21lIHBvc3NpYmxlLgpTdHJpY3RseSBwb3NpdGl2ZSwgZml4ZWQgYXQgY3JlYXRpb24sIG5ldmVyIGNoYW5nZWQgYWZ0ZXJ3YXJkcy4AAAAAAAAOZnVuZGluZ190YXJnZXQAAAAAAAs=", @@ -664,6 +703,7 @@ export class Client extends ContractClient { "AAAAAAAAAHtTZXRzIHRoZSBpbW11dGFibGUgdG9rZW4gYWxsb3dsaXN0IGF0IGRlcGxveW1lbnQuIEFuIGVtcHR5IGxpc3QKcHJlc2VydmVzIHRoZSBsZWdhY3kgYmVoYXZpb3IgYW5kIGFsbG93cyBhbnkgdG9rZW4gYWRkcmVzcy4AAAAADV9fY29uc3RydWN0b3IAAAAAAAABAAAAAAAAAA5hbGxvd2VkX3Rva2VucwAAAAAD6gAAABMAAAAA", "AAAAAAAABABMb2NrcyBgYW1vdW50YCBvZiBgdG9rZW5gIHB1bGxlZCBmcm9tIGBwYXllcmAsIGhlbGQgZm9yIGBwYXllZWAsCmRvY3MvdGhyZWF0LW1vZGVsLm1kIFQxMCBhbmQgUk9BRE1BUC5tZCBQaGFzZSBFNSkuIGByZWxlYXNlcmAgaXMgdGhlCmFkZHJlc3MgcGVybWl0dGVkIHRvIGNhbGwgYHJlbGVhc2VgL2ByZWZ1bmRgIG9uIHRoaXMgZXNjcm93Cihkb2NzL2Fkci8wMDAyKS4gYHJlZnVuZF9hZnRlcmAgaXMgb3B0aW9uYWwgKGRvY3MvYWRyLzAwMDQpLgpgbm90aWZ5X3BheWVlYCBvcHRzIGFuIGltcGxlbWVudGluZyBjb250cmFjdCBwYXllZSBpbnRvCmBvbl9lc2Nyb3dfcmVsZWFzZWQoZXNjcm93X2lkLCBhbW91bnQpYCAoZG9jcy9hZHIvMDAwNSkuIFRoZSBwYXllcgptdXN0IGF1dGhvcml6ZSBjcmVhdGlvbiwgYW5kIHRoZSBwYXllZSBtdXN0IGFsc28gYXV0aG9yaXplIGlmCmBub3RpZnlfcGF5ZWVgIGlzIHRydWUuIGByZWZ1bmRfdG9gIGlzIHRoZSBvcHRpb25hbCByZWZ1bmQKZGVzdGluYXRpb24gZm9yIGEgc3BvbnNvcmVkIGVzY3JvdyB3aGVyZSB0aGUgZnVuZGVyIChgcGF5ZXJgKSBpcwpub3Qgd2hvIHNob3VsZCBnZXQgdGhlIG1vbmV5IGJhY2sgKGRvY3MvYWRyLzAwMDkpOiBgTm9uZWAgbWVhbnMKYHBheWVyYDsgaXQgbWF5IG5vdCBiZSB0aGlzIGNvbnRyYWN0J3Mgb3duIGFkZHJlc3MsIGFuZCB0aGUKYHBheWVyYCdzIGF1dGggb24gdGhpcyBjYWxsIGNvdmVycyBpdC4gRm9yIE0tb2YtTiByZWxlYXNlcnMgdXNlCmBjcmVhdGVfZXNjcm93X3dpdGhfcmVsZWFzZXJzYC4KYGZlZV9yZWNpcGllbnRgL2BmZWVfYnBzYCBhcmUgdGhlIG9wdGlvbmFsIHByb3RvY29sIGZlZSwgZml4ZWQgYXQKY3JlYXRpb24gYW5kIHRha2VuIGF0IHJlbGVhc2Ug4oCUIG5ldmVyIG9uIHJlZnVuZCDigJQgd2l0aCBgZmVlX2JwcyDiiaRgCltgTUFYX0ZFRV9CUFNgXSAoMTAgJSksIGZsb29yIHJvdW5kaW5nLCBhbmQgYm90aCBnaXZlbiB0b2dldGhlciBvcgpub3QgYXQgYWxsIChkb2NzL2Fkci8wMDEwKS4gYE5vbmVgAAAADWNyZWF0ZV9lc2Nyb3cAAAAAAAALAAAAAAAAAAVwYXllcgAAAAAAABMAAAAAAAAABXBheWVlAAAAAAAAEwAAAAAAAAAFdG9rZW4AAAAAAAATAAAAAAAAAAZhbW91bnQAAAAAAAsAAAAAAAAADWNvbmRpdGlvbl9yZWYAAAAAAAAQAAAAAAAAAAhyZWxlYXNlcgAAABMAAAAAAAAADHJlZnVuZF9hZnRlcgAAA+gAAAAGAAAAAAAAAAxub3RpZnlfcGF5ZWUAAAABAAAAAAAAAAlyZWZ1bmRfdG8AAAAAAAPoAAAAEwAAAAAAAAANZmVlX3JlY2lwaWVudAAAAAAAA+gAAAATAAAAAAAAAAdmZWVfYnBzAAAAA+gAAAAEAAAAAQAAA+kAAAAGAAAAAw==", "AAAAAAAAAaNCYXRjaCB2ZXJzaW9uIG9mIGBjcmVhdGVfZXNjcm93YC4gQ3JlYXRlcyBvbmUgZXNjcm93IHBlciBpdGVtLCBpbgppbnB1dCBvcmRlciwgYW5kIHJldHVybnMgdGhlIG5ldyBpZHMgaW4gdGhlIHNhbWUgb3JkZXIgYXMgYGl0ZW1zYC4KYHBheWVyYCBhdXRob3JpemVzIG9uY2UgZm9yIHRoZSB3aG9sZSBjYWxsLiBGYWlscyBhdG9taWNhbGx5OiBpZgphbnkgaXRlbSBpcyBpbnZhbGlkIChiYWQgYW1vdW50LCBwYXN0IGByZWZ1bmRfYWZ0ZXJgLCBvdmVyc2l6ZWQKYGNvbmRpdGlvbl9yZWZgLCBzaG9ydC1kZWxpdmVyaW5nIHRva2VuKSB0aGUgd2hvbGUgY2FsbCByZXZlcnRzIGFuZApubyBlc2Nyb3dzIGFyZSBjcmVhdGVkLgoKYGl0ZW1zLmxlbigpYCBtdXN0IGJlIGA8PSBNQVhfQkFUQ0hfU0laRWAg4oCUIHNlZSBkb2NzL2Fkci8wMDA1LgAAAAAOY3JlYXRlX2VzY3Jvd3MAAAAAAAIAAAAAAAAABXBheWVyAAAAAAAAEwAAAAAAAAAFaXRlbXMAAAAAAAPqAAAH0AAAAApDcmVhdGVJdGVtAAAAAAABAAAD6QAAA+oAAAAGAAAAAw==", + "AAAAAAAAA6VMZXRzIHRoZSBjdXJyZW50IGBwYXllZWAgcmVhc3NpZ24gZnV0dXJlIHBheW91dCByaWdodHMgdG8gYSBuZXcKYWRkcmVzcy4gT25seSB0aGUgY3VycmVudCBgcGF5ZWVgIG1heSBhdXRob3Jpc2UgdGhpcyDigJQgbm8gb25lCmVsc2UgKG5vdCB0aGUgcGF5ZXIsIG5vdCB0aGUgcmVsZWFzZXIpIGNhbiByZWRpcmVjdCB3aGVyZSBhCnJlbGVhc2Ugd2lsbCBnbyAoc2VlIGludmFyaWFudCBJMSBhbmQgZG9jcy90aHJlYXQtbW9kZWwubWQpLgoKUmVzdHJpY3Rpb25zOgotIE9ubHkgd2hpbGUgdGhlIGVzY3JvdyBpcyBgRnVuZGVkYCAobm8gZWZmZWN0IGFmdGVyIHJlbGVhc2Ugb3IKcmVmdW5kOyB0aGUgdHJhbnNmZXIgaXMgYSBwYXlvdXQtY2xhaW0gcmVhc3NpZ25tZW50LCBub3QgYW4KdW5kbyBvZiBhIHNldHRsZW1lbnQpLgotIGBuZXdfcGF5ZWVgIG1heSBub3QgYmUgdGhlIGNvbnRyYWN0J3Mgb3duIGFkZHJlc3MgKGl0IGNhbiBuZXZlcgpzaWduIHRvIGNsYWltIGZ1bmRzKSBvciB0aGUgYHBheWVyYCdzIGFkZHJlc3MgKHByZXZlbnRpbmcgYQpwYXllciBmcm9tIHVzaW5nIGEgY29sbHVkaW5nIHBheWVlIHRvIHJlZGlyZWN0IHRoZSBlc2Nyb3cgdG8KdGhlbXNlbHZlcykuCgpUaGlzIGhlbHBzIGEgcGF5ZWUgd2hvIGlzICpyb3RhdGluZyogdGhlaXIgd2FsbGV0IOKAlCBpdCBkb2VzIE5PVApoZWxwIGEgcGF5ZWUgd2hvIGhhcyBhbHJlYWR5ICpsb3N0KiB0aGVpciBrZXkgYW5kIGNhbiBubyBsb25nZXIKc2lnbjogdGhleSBjYW5ub3QgYXV0aG9yaXNlIHRoaXMgY2FsbC4gS2V5IGxvc3MgaXMgYW4gb3BlcmF0aW9uYWwKcmlzayB0aGUgcGF5ZWUgbXVzdCBtaXRpZ2F0ZSBvZmYtY2hhaW4gYmVmb3JlIGl0IGhhcHBlbnMuCgpFbWl0cyBhIGBwYXlfeGZlcmAgZXZlbnQgd2l0aCBgKGVzY3Jvd19pZCwgb2xkX3BheWVlLCBuZXdfcGF5ZWUpYC4AAAAAAAAOdHJhbnNmZXJfcGF5ZWUAAAAAAAMAAAAAAAAACWVzY3Jvd19pZAAAAAAAAAYAAAAAAAAADWN1cnJlbnRfcGF5ZWUAAAAAAAATAAAAAAAAAAluZXdfcGF5ZWUAAAAAAAATAAAAAQAAA+kAAAACAAAAAw==", "AAAAAAAAAPhSb3RhdGVzIGEgZnVuZGVkIGVzY3JvdydzIHJlbGVhc2VyLiBCb3RoIHRoZSBjdXJyZW50IHJlbGVhc2VyIGFuZApwYXllciBtdXN0IGF1dGhvcml6ZSB0aGUgY2hhbmdlOyB0aGUgcGF5ZXIncyBjb25zZW50IHByZXZlbnRzIGEKY29tcHJvbWlzZWQgcmVsZWFzZXIgZnJvbSBzaWxlbnRseSBhcHBvaW50aW5nIGFuIGF0dGFja2VyLiBUaGUKcmVwbGFjZW1lbnQgY2Fubm90IGJlIHRoZSBjb250cmFjdCBpdHNlbGYgb3IgdGhlIHBheWVlLgAAAA9yb3RhdGVfcmVsZWFzZXIAAAAAAwAAAAAAAAAJZXNjcm93X2lkAAAAAAAABgAAAAAAAAAGY2FsbGVyAAAAAAATAAAAAAAAAAxuZXdfcmVsZWFzZXIAAAATAAAAAQAAA+kAAAACAAAAAw==", "AAAAAAAAARRSZWFkLW9ubHk6IG9uZSBjb250cmlidXRvcidzIHJlY29yZCBvbiBhIHBvb2xlZCBlc2Nyb3cg4oCUIHRoZSBleGFjdAphbW91bnQgdGhleSBjYW4gY2xhaW0gYmFjayBmcm9tIGEgZmFpbGVkIHJvdW5kLCBhbmQgd2hldGhlciBpdCBoYXMKYWxyZWFkeSBiZWVuIGNsYWltZWQuIGBOb25lYCBtZWFucyB0aGUgYWRkcmVzcyBuZXZlciBjb250cmlidXRlZC4KRXJyb3JzIGBOb3RGb3VuZGAgb24gYW4gdW5rbm93biBpZCBhbmQgYE5vdFBvb2xlZGAgb24gYQpub24tcG9vbGVkIGVzY3Jvdy4AAAAQZ2V0X2NvbnRyaWJ1dGlvbgAAAAIAAAAAAAAACWVzY3Jvd19pZAAAAAAAAAYAAAAAAAAAC2NvbnRyaWJ1dG9yAAAAABMAAAABAAAD6QAAA+gAAAfQAAAADENvbnRyaWJ1dGlvbgAAAAM=", "AAAAAAAAA1VDcmVhdGVzIGEgcG9vbGVkIGVzY3JvdyBmdW5kZWQgYnkgbWFueSBwYXllcnMgKGlzc3VlICMxMTMsCmRvY3MvYWRyLzAwMTEpLiBgY3JlYXRvcmAgc2V0cyB0aGUgZGVhbCDigJQgcGF5ZWUsIHRva2VuLCByZWxlYXNlciwKb3BhcXVlIGBjb25kaXRpb25fcmVmYCwgYW4gZXhwbGljaXQgYGZ1bmRpbmdfdGFyZ2V0YCAoPiAwKSBhbmQgYQpgZnVuZGluZ19kZWFkbGluZWAgKHVuaXggc2Vjb25kcywgc3RyaWN0bHkgaW4gdGhlIGZ1dHVyZSkg4oCUIGJ1dApmdW5kcyBub3RoaW5nIGF0IGNyZWF0aW9uOiBgRXNjcm93RGF0YS5hbW91bnRgIHN0YXJ0cyBhdCAwIGFuZCBncm93cwphcyBjb250cmlidXRvcnMgY2FsbCBgY29udHJpYnV0ZWAuIFJlbGVhc2UgYmVjb21lcyBwb3NzaWJsZSBvbmx5Cm9uY2UgY29udHJpYnV0aW9ucyByZWFjaCB0aGUgdGFyZ2V0IGV4YWN0bHk7IGlmIHRoZSBkZWFkbGluZSBwYXNzZXMKZmlyc3QsIHRoZSByb3VuZCBoYXMgZmFpbGVkIGFuZCBldmVyeSBjb250cmlidXRvciBwdWxscyB0aGVpciBvd24KcmVjb3JkZWQgYW1vdW50IGJhY2sgd2l0aCBgY2xhaW1fcmVmdW5kYC4gYGNyZWF0b3JgIGlzIHN0b3JlZCBhcwp0aGUgZXNjcm93J3MgYHBheWVyYCAoY28tYXV0aG9yaXphdGlvbiBmb3IgYHJvdGF0ZV9yZWxlYXNlcmAgb25seSkKYW5kIGFzIHRoZSBgcmVmdW5kX3RvYCBwbGFjZWhvbGRlcjsgbm8gcHVzaCByZWZ1bmQgcGF0aCBleGlzdHMgZm9yCnBvb2xlZCBlc2Nyb3dzLiBObyBgcmVmdW5kX2FmdGVyYCwgbm8gYWNjZXB0YW5jZSBnYXRlLCBubyBjYWxsYmFjazoKcG9vbGVkIHNldHRsZW1lbnQgcmV1c2VzIHRoZSBwbGFpbiByZWxlYXNlci90aHJlc2hvbGQgcnVsZXMuAAAAAAAAFGNyZWF0ZV9wb29sZWRfZXNjcm93AAAABwAAAAAAAAAHY3JlYXRvcgAAAAATAAAAAAAAAAVwYXllZQAAAAAAABMAAAAAAAAABXRva2VuAAAAAAAAEwAAAAAAAAAOZnVuZGluZ190YXJnZXQAAAAAAAsAAAAAAAAADWNvbmRpdGlvbl9yZWYAAAAAAAAQAAAAAAAAAAhyZWxlYXNlcgAAABMAAAAAAAAAEGZ1bmRpbmdfZGVhZGxpbmUAAAAGAAAAAQAAA+kAAAAGAAAAAw==", @@ -691,6 +731,7 @@ export class Client extends ContractClient { claim_refund: this.txFromJSON>, create_escrow: this.txFromJSON>, create_escrows: this.txFromJSON>>, + transfer_payee: this.txFromJSON>, rotate_releaser: this.txFromJSON>, get_contribution: this.txFromJSON>>, create_pooled_escrow: this.txFromJSON>,