Skip to content

feat(contracts): support signed revoke and batch buyer accounting migration - #24

Merged
sirpy merged 18 commits into
mainfrom
feat/contracts-operator-revoke-migration
Aug 31, 2026
Merged

sirpy merged 18 commits into
mainfrom
feat/contracts-operator-revoke-migration

Conversation

@sirpy

@sirpy sirpy commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR updates the Base-side AntseedBuyerOperator and the Cloudflare Worker integration around buyer/operator lifecycle management, remaining-balance accounting, signed buyer actions, and migration tooling.

The main contract changes support safer signed operations, per-buyer nonce replay protection, signed operator revocation, principal/bonus remaining-balance tracking, and one-time migration of existing buyer accounting. The Worker changes keep its API and funding behavior aligned with the updated contract surface.

What Changed

Contracts

  • Swapped the owner / admin responsibilities so:
    • owner controls upgrades, token sweeping, and privileged fund operations.
    • admin is the day-to-day operational caller.
  • Added signed operator revocation:
    • revokeOperator(address buyer, uint256 nonce, bytes buyerSig)
    • revokeOperator(address buyer) remains available for direct buyer/admin revocation.
  • Replaced timestamp-based signed authorization with incremental per-buyer nonces:
    • usedNonces[buyer] is shared by signed withdraw, revoke, request-close, and channel-withdraw actions.
    • EIP-712 type hashes now use nonce instead of timestamp.
  • Replaced custom signature recovery with OpenZeppelin ECDSA recovery helpers for malformed/malleable signature handling.
  • Added remaining-balance accounting:
    • principalRemaining
    • bonusRemaining
    • totalPrincipalWithdrawn
    • totalBonusWithdrawn
    • lastAccountedBalance
  • Added usage-aware accounting helpers so principal is consumed before bonus when current buyer deposit balance has decreased.
  • Added one-time migration helpers for existing buyers:
    • migrateBuyerAccounting(address buyer)
    • migrateBuyerAccounting(address[] buyers)
    • buyerAccountingMigrated[buyer]
  • Updated non-operator funding behavior:
    • principal funding can still proceed if this contract is no longer the buyer operator.
    • bonus is forced to zero in that case.
    • bonus-only funding with no operator reverts at the contract layer because the effective total is zero.
  • Added channel-close protection to revoke flows when reserved bonus may still exist.
  • Extended IAntseedDeposits with getBuyerBalance for usage-aware accounting.

Backend Worker

  • Updated Worker request schemas and funding ABI calls from timestamp to decimal-string nonce.
  • Added POST /v1/accounts/:account/operator-revoke:
    • body: { nonce, signature }
    • calls AntseedBuyerOperator.revokeOperator(buyer, nonce, buyerSig).
  • Added AntSeedFundingVaultClient.revokeBuyerOperator for the new revoke endpoint.
  • Added AntSeedFundingVaultClient.isBuyerOperator, which reads:
    • AntseedBuyerOperator.registry()
    • registry.deposits()
    • deposits.getOperator(buyer)
  • Updated funding behavior for bonus-only credits:
    • only skip Base funding when principalUsd === 0, bonusUsd > 0, and the on-chain operator check confirms this contract is not the buyer operator.
    • skipped revoked-operator bonus-only entries clear outstanding funding without adding phantom credited principal/bonus totals.
    • bonus-only credits still call depositForBuyerWithId when this contract remains the buyer operator.
  • Added backend/scripts/migrate-buyer-accounting.ts to discover historical funded buyers and batch-run accounting migration.

Docs And Tooling

  • Updated backend/README.md endpoint list with operator-revoke.
  • Updated docs/ARCHITECTURE.md for nonce-based auth, the revoke endpoint, and current backend/operator behavior.
  • Updated contracts/DEPLOY.md for the owner/admin naming and transferAdmin flow.
  • Switched backend CI from npm lockfile usage to Yarn/Corepack:
    • CI uses yarn install --immutable.
    • backend lint script uses Yarn commands.
    • removed backend/package-lock.json from the branch diff.

Validation

  • cd contracts && forge test --match-contract AntseedBuyerOperatorTest -> 44 passed
  • cd contracts && forge test -> 81 passed
  • cd backend && npm test -> 76 passed
  • cd backend && npm run check:worker-only && npm run typecheck -> passed

Notes

  • This PR does not add AI proxying or new runtime infrastructure; backend changes remain within the Cloudflare Worker boundary.
  • The current PR context did not include a linked issue number to reference.

Copilot AI lite review requested due to automatic review settings August 12, 2026 16:44
@sirpy
sirpy requested a review from blueogin August 12, 2026 16:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the AntseedBuyerOperator contract to improve buyer/operator lifecycle control (including an optional EIP-712 signed revoke path) and introduce a remaining-balance accounting model with one-time migration helpers, alongside interface and Foundry test updates.

Changes:

  • Added signed revoke support (REVOKE_OPERATOR_TYPEHASH, revokeOperator(buyer,timestamp,sig)) while keeping the legacy direct revoke entrypoint.
  • Introduced remaining/usage-aware accounting (principalRemaining, bonusRemaining, lastAccountedBalance) plus single/batch migration helpers.
  • Updated IAntseedDeposits to expose buyer balance (available/reserved) and expanded tests for non-operator funding behavior, revoke flows, usage accounting, and migration.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
contracts/src/AntseedBuyerOperator.sol Adds signed revoke, remaining-based accounting + migration, and adjusts funding/withdraw/revoke/transfer flows accordingly.
contracts/src/interfaces/IAntseedDeposits.sol Extends deposits interface with getBuyerBalance needed for usage/remaining accounting.
contracts/test/AntseedBuyerOperator.t.sol Updates mocks and adds coverage for signed revoke, non-operator funding bonus wipe, usage accounting, migrations, and transfer invariants.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread contracts/src/AntseedBuyerOperator.sol
Comment thread contracts/src/AntseedBuyerOperator.sol Outdated
@sirpy

sirpy commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

@blueogin please review

Comment on lines +347 to 352
function transferBuyerOperator(address buyer, address newOperator) external nonReentrant onlyAdmin {
if (buyer == address(0)) revert InvalidAddress();
_withdrawUnusedBonus(buyer);
_deposits().transferOperator(buyer, newOperator);
emit BuyerOperatorTransferred(buyer, newOperator);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_revokeOperator added CloseChannelsBeforeRevoke to stop bonus being stranded in reserved channels, but the transfer path has no equivalent check - the operator role can be handed off with bonus still locked.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats expected. added a description to the method

Comment thread backend/src/kv-credit-store.ts
@sirpy
sirpy requested a review from blueogin August 30, 2026 13:57
@sirpy
sirpy merged commit 0139744 into main Aug 31, 2026
3 checks passed
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.

3 participants