feat(distribute): define atomic batch-distribution semantics (#1032) - #1093
Open
Phantomcall wants to merge 1 commit into
Open
feat(distribute): define atomic batch-distribution semantics (#1032)#1093Phantomcall wants to merge 1 commit into
Phantomcall wants to merge 1 commit into
Conversation
…Org#1032) - Replace broken tuple/list arg with parallel Vec<Address> + Vec<i128> (Soroban contract methods disallow custom-type / tuple generic args). - Reject duplicate recipients in Phase 1 before any state change. - Document all-or-nothing + value-conservation semantics. - Add test_batch module covering empty, max-size, duplicate, invalid, mid-batch-failure, and value-conservation. - Fix invalid 'callora.v1' event Symbol (dots not allowed) -> callora_v1.
Author
|
i was able to solve this issue in an ample amount of time |
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.
Define atomic batch-distribution semantics (#1032)
Closes #1032
Summary
Defines and enforces all-or-nothing (atomic) semantics for the
batch_distributeentrypoint incontracts/distribute, so a single invalidrecipient or transfer failure can never leave hidden partial accounting. The
entire batch is validated before any USDC is moved, and any failure reverts the
whole call.
Why the signature changed
The old
batch_distributetookVec<(Address, i128)>, which Soroban contractmacros reject ("generics unsupported on user-defined types in contract
functions"), so the function never compiled as a contract entrypoint. It now
takes two parallel built-in lists —
recipients: Vec<Address>andamounts: Vec<i128>(equal length) — which is a valid contract-facing ABI andstill preserves duplicate recipients so they can be rejected explicitly.
Atomicity model: all-or-nothing
per-leg cap, valid recipient, no duplicate recipient); Phase 2 checks the
batch total against the contract's USDC balance — all before any transfer.
or a transfer fails, the entire batch reverts (no partial distribution).
amounts; after a success the contract's balance is exactly
prior_balance - total. No rounding, fees, or mint/burn.Acceptance criteria → coverage
→
DuplicateRecipientrejection in Phase 1 (lib.rs),validate_recipientfor the contract-self case.
test_batch::duplicates_are_rejected_before_any_transfertest_batch::invalid_recipient_contract_self_is_rejected→ all-or-nothing, fail-early before any transfer.
test_batch::mid_batch_failure_reverts_entire_batch→ exact strict sum.
test_batch::successful_batch_conserves_total_value→ net:
test_batch::empty_batch_is_rejected_without_mutationtest_batch::max_batch_size_is_enforcedtest_batch::leg_count_mismatch_is_rejectedSecurity / failure-mode considerations
A batch can only be sent by the admin (existing
require_admin+caller.require_auth). Duplicates, non-positive amounts, over-cap amounts,the contract itself, and balance shortfalls are all rejected before mutation,
so an attacker can neither cause a partial disbursement nor mutate state on a
rejected batch.
Verification
cargo test -p callora-distribute --lib test_batch→ 7 passed, 0 failed.Note: the broader crate has pre-existing, unrelated failures in a few
event-emission tests (e.g.
init_event_structure_validationasserts a 2-topicevent that the existing
initcode emits as 3 topics) and an integration testfile (
tests/auth_snap.rs) referencing a staleCalloraDistributeAPI. Thesepredate and are orthogonal to this batch change; they are called out for a
separate cleanup.