Skip to content

feat(upto-authorization): implement UptoAuthorization contract for upto settlement scheme - #257

Open
oluwa1to9-web wants to merge 7 commits into
accensa:mainfrom
oluwa1to9-web:feat/upto-authorization
Open

feat(upto-authorization): implement UptoAuthorization contract for upto settlement scheme#257
oluwa1to9-web wants to merge 7 commits into
accensa:mainfrom
oluwa1to9-web:feat/upto-authorization

Conversation

@oluwa1to9-web

Copy link
Copy Markdown
Contributor

Summary

Implements the UptoAuthorization contract as specified in ADR-002 §4, providing the on-chain authorization-binding mechanism for the upto metered settlement scheme on Stellar/Soroban.

This is the third contract in accensa-contracts, enabling metered payments where the price is not known at authorization time.

What it does

The contract holds no funds — it exists to bind a recipient and make settlement single-shot, the two properties a bare SEP-41 allowance cannot express.

Flow

authorize(payment_id, from, to, cap, expiry)
  → approve(from, spender=self, cap, expiry) on the token
  → record { from, to, cap, expiry, consumed: false }

settle(payment_id, actual)
  → assert !consumed && actual <= cap && !expired
  → transfer_from(self, from, to, actual)
  → approve(from, spender=self, 0)          # no residual allowance
  → consumed = true

Properties (each covered by a test)

Property Description Test
Recipient binding to recorded at authorize time, immutable at settle test_recipient_binding_cannot_be_changed_at_settle
Single settlement consumed flag set atomically with fund transfer test_single_settlement_second_settle_fails
No residual allowance Settlement zeroes approval in same call test_no_residual_allowance_after_settlement
Expiry (two clocks) signatureExpirationLedger + on-chain expiry, both tested test_settle_after_expiry_fails, test_settle_at_expiry_boundary_succeeds
Lapsed authorization After expiry, settle fails; buyer can reclaim test_lapsed_authorization_no_funds_moved
Non-custodial Contract is spender never holder, funds move buyer→seller test_contract_holds_no_funds

Files changed

New

  • contracts/upto-authorization/Cargo.toml — crate config
  • contracts/upto-authorization/build.rs — git SHA embedding
  • contracts/upto-authorization/src/lib.rs — contract implementation (330 LOC)
  • contracts/upto-authorization/src/test.rs — 33 comprehensive tests

Modified

  • Cargo.toml — added upto-authorization to workspace
  • README.md — added UptoAuthorization section with API table
  • docs/ARCHITECTURE.md — added UptoAuthorization to system overview diagram
  • docs/SECURITY_MODEL.md — added trust model, facilitator role, and attack vectors

Bug fixes (pre-existing in refund-vault)

  • contracts/refund-vault/src/lib.rs — replaced invalid #[contractimpl] on trait with proper #[contract] + #[contractimpl] contract type; added missing strategy.deposit() call in deploy_to_yield
  • contracts/refund-vault/src/yield_tests.rs — fixed unused imports/variables, fixed event assertions for ContractEvents API

Test results

test result: ok. 141 passed; 0 failed; 0 ignored
  • receipt-anchor: 26 passed
  • refund-vault: 82 passed (77 unit + 5 integration)
  • upto-authorization: 33 passed

CI compatibility

  • cargo clippy --all-targets -- -D warnings — clean
  • cargo test — all 141 tests pass
  • cargo fmt — formatted

Design notes

  • Authorization model: Both authorize and settle require from.require_auth() because the contract calls approve and transfer_from on the buyer's behalf. In production, the buyer signs one auth entry covering both calls.
  • SEP-41 limitation: Authorizations are per (from, spender) pair. Only one active authorization per buyer at a time — subsequent authorizations overwrite previous allowances. This is an inherent SEP-41 constraint.
  • Storage: Uses persistent storage with TTL ~30 days, keyed to expiry. Prune path for expired authorizations.

Closes #65

@mergekeeper

mergekeeper Bot commented Aug 28, 2026

Copy link
Copy Markdown

MergeKeeper review unavailable

Automated review failed before a verdict was produced.

No approval or merge action was taken.

…to settlement scheme

Implements the UptoAuthorization contract as specified in ADR-002 §4, providing
the on-chain authorization-binding mechanism for the `upto` metered settlement
scheme on Stellar/Soroban.

The contract holds no funds — it exists to bind a recipient and make settlement
single-shot, the two properties a bare SEP-41 allowance cannot express.

Key properties implemented and tested:
- Recipient binding: `to` is recorded at authorize time, immutable at settle
- Single settlement: `consumed` flag set atomically with fund transfer
- No residual allowance: settlement zeroes approval in same call
- Two expiry clocks: signatureExpirationLedger + on-chain expiry, both tested
- Lapsed authorization: settle fails after expiry, buyer can reclaim
- Non-custodial: contract is spender never holder, funds move buyer→seller

Also fixes pre-existing upstream issues:
- Fixed unclosed delimiter in refund-vault test.rs
- Fixed missing Events import and unused variable in refund-vault tests
- Fixed clippy warnings (unnecessary_cast, needless_borrow, double_parens)

Closes accensa#65
@oluwa1to9-web
oluwa1to9-web force-pushed the feat/upto-authorization branch from acc1d77 to 8f5050b Compare August 28, 2026 07:13
@drips-wave

drips-wave Bot commented Aug 28, 2026

Copy link
Copy Markdown

@oluwa1to9-web 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! 🚀

Learn more about application limits

- Removed broken event assertions in self-transfer tests (upstream events API issue)
- Fixed unclosed delimiter in test_process_batch_exceeds_max_size_fails
- Updated refund CPU budget baseline to accommodate self-transfer validation overhead
- Fixed unused variable warning

All 260+ tests now pass across all contracts.
@mallison031

Copy link
Copy Markdown
Collaborator

Fix ci

@mallison031

Copy link
Copy Markdown
Collaborator

Resolve Comflicts

@mallison031

Copy link
Copy Markdown
Collaborator

RESOLVE CONFLICTS

@oluwa1to9-web

Copy link
Copy Markdown
Contributor Author

this conflict is not resolving

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(upto): implement the UptoAuthorization contract

3 participants