feat(wallet): policy- and budget-validated atomic batch execution (issue #90) - #192
Open
merciiiqode wants to merge 4 commits into
Open
feat(wallet): policy- and budget-validated atomic batch execution (issue #90)#192merciiiqode wants to merge 4 commits into
merciiiqode wants to merge 4 commits into
Conversation
…cel flows The repo was committed in a broken mid-merge state that did not compile (duplicated error enum variants beyond the XDR limit, merged functions, unclosed delimiters, stale helper signatures). Restore it so `cargo test --workspace`, `cargo fmt` and clippy all pass, and finish the escrow work this branch was opened for (issue ASTROIDX556#80). shared: - rewrite Error enum as exactly 50 #[contracterror] variants; add GraceActive / EscrowNotExpired / EscrowAlreadySettled / ReserveViolation - fix safe-arithmetic test expectations (Overflow for i128::MIN-1; mul round-trips below i128::MAX) escrow (issue ASTROIDX556#80): - implement expiration deadline handling: post-deadline/grace refunds (refund, reclaim, refund_timelock, expire) return ESCROW_EXPIRED and graceful errors, plus sender-only clawback cancel with EscrowNotExpired / GraceActive / EscrowAlreadySettled transitions into Cancelled - reconstruct multi-asset escrow (create, timelock, scheduled, milestones, override release, vesting/claiming views, structured events) - reconcile tests to new cancel semantics; fix stale helper signatures policy: - un-merge whitelist/blocklist/category functions corrupted by the merge; repair check_transfer gates (recipient whitelist, dedupe blacklist checks) - update register_policy helper to current 9-arg signature wallet: - Restore lost batch_execute (atomic sub-calls); sub-calls target external contracts (Soroban forbids self re-entry), gate on wallet Active state, surface callee errors via try_invoke_contract - Fix Val (RawVal rename), ContractCall arg encoding, set_reserve_ratio auth multisig: TooManySigners -> InvalidThreshold; budget/treasury: clippy fixes
…tion status Issue ASTROIDX556#82 already had the core chaining machinery (prerequisite ids in storage, acyclicity checks, ensure_dependencies_met enforcing the executed state before execute). This completes the acceptance criteria that were still missing: - Emit structured events whenever a dependency chain is validated: ("proposal", "dep_ok") when every prerequisite has executed, and ("proposal", "dep_fail") with the id of the first unmet prerequisite when execution is blocked. - Add an is_executed view exposing has_executed() (Executed | Closed) so downstream contracts can query a proposal's completion status directly. - Tests: blocked execution emits dep_fail (no dep_ok), satisfied chains emit dep_ok, end-to-end completion via is_executed including a Failed proposal never counting as executed. Closes ASTROIDX556#82
Adds a validated batch path to the wallet alongside the existing raw
batch_execute. Each BatchAction carries the external sub-call plus the
metadata needed to gate it: policy envelope id (asset/recipient/amount are
checked against the wired policy contract) and budget envelope id (consumed
from the wired budget contract). Empty ids skip the corresponding gate.
batch_execute_validated is two-phase:
1. Validate every action and aggregate its value with checked math in a
single iteration pass (one budget consumption per envelope, no
speculative pre-flights).
2. Execute the sub-calls sequentially.
Any failure — policy denial, budget overrun, cumulative overflow, failing
sub-call — reverts the whole transaction, so validation and execution are
atomic. On success an aggregated BatchReceipt (executed, total_amount,
budget_remaining) is returned and ("wallet", "batch_validated") is
published.
Contract-level set_policy/set_budget (admin) wire the gates, mirroring the
treasury convention. Tests cover success, policy denial rollback, budget
insufficiency rollback, cumulative overflow, unwired-gate refusal,
envelope-less execution, mixed-asset aggregation, and the standard empty /
role / frozen gates.
Closes ASTROIDX556#90
|
@merciiiqode Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
4 tasks
Contributor
|
resolve conflict on this issue |
Contributor
|
resolve conflict on this issue @merciiiqode |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #90
Summary
Adds batch validation of execution calls to the wallet contract. The existing
raw
batch_executestays for un-gated sub-calls; the newbatch_execute_validatedgates every action against the policy and budgetcontracts before any value moves, executes the batch atomically, and returns
an aggregated receipt.
What was added
BatchAction— a sub-call plus validation metadata:policy_id(envelope id, asset/recipient/amount checked against
check_transfer),budget_id(envelope consumed viaconsume),asset,recipientandamount. An empty id skips that gate for the action.batch_execute_validated— two-phase entry point (wallet,Role::Agent):single iteration pass (one budget consumption per envelope, no
speculative pre-flights → minimized gas), then
Any failure — policy denial, budget overrun, cumulative
i128overflow,or a failing sub-call — reverts the entire transaction (atomicity). On
success it returns a
BatchReceipt { executed, total_amount, budget_remaining }and publishes("wallet", "batch_validated").set_policy/set_budget(contract admin) wire the gate contracts,mirroring the treasury convention.
BatchReceipt— the aggregated result of the run.Atomicity
Soroban's runtime rollback guarantees no partial effect: policy/budget
checks and the cumulative-value calculation all happen in phase 1, before any
sub-call fires, so a denied batch moves nothing and does not debit budgets.
Acceptance criteria
contracts/walletBatchReceipt), revert on failureVerification
cargo test --package astroid-wallet— 56 tests pass (10 new)cargo test --workspace— 342 tests passcargo clippy --workspace -- -D warnings— cleancargo fmt --all --check— cleanNote: branches back to the accumulated repair/feature work (PRs #189, #190,
#191) because upstream
maindoes not compile; merge those first.