DEV Community

Sriram Ramakrishnan
Sriram Ramakrishnan

Posted on

An agent paid, and a gate stopped two payments, with receipts

Stablecoin payments don't have chargebacks. Once an agent signs, the money is gone. So the check has to happen before signing, and a claim about that check is worthless without a log, a transaction, and a third party who replayed it.

On 1 November, my agent proposed payments and sra-riskgate 0.15.0 checked each one before signing. This is what happened, on two testnets.

Arc testnet, through Circle Gateway

  • 0.01 USDC to a known payee: APPROVE. Submitted to Circle Gateway, batch c1491e17-cc2b-472c-b444-62beb83300fc.
  • Unlimited USDC approval for "auto-billing": HOLD (TOKEN_APPROVAL, UNLIMITED_APPROVAL). Not signed. An approve(address, uint256) lets another address spend the wallet's USDC later, effectively without limit.
  • 0.01 USDC to a look-alike payee: REJECT (LOOKALIKE_RECIPIENT). Not signed. The address imitated the known payee: same start, same end.

Settlement, checked on both sides rather than taken from the batch id:

Run Agent's Gateway balance Payee's Gateway balance
26 October (earlier Gateway run) 0.10 → 0.09 0 → 0.01
1 November 0.09 → 0.08 0.01 → 0.02

The 1 November payment landed on top of the 26 October one: the agent was debited exactly 0.01 and the payee credited exactly 0.01.

Script, log and settlement balances: gist

Base Sepolia, same version, third-party verified

The same evening, on Base Sepolia:

  • 0.01 USDC to a known payee: APPROVE, sent, then read back from the receipt and verified. Transaction
  • 2.00 USDC to an unknown payee: HOLD before signing (HIGH_VALUE_TRANSFER, NEW_COUNTERPARTY). No transaction exists for it, by design. The hold reason and log are public, so anyone can replay why it stopped: gist

Flow Executor then verified both halves from the chain, not from my claim. The approved run settled (same transaction, success, block 53339258, payee 0x870b…7DDc, matching the APPROVE). For the held run, no transaction exists, and the log shows signed: false with the same two hold reasons.

Flow verified the settlement. Flow did not run or adopt RiskGate itself, and the evidence file keeps that distinction.

The count

2 good payments settled and 3 bad payments stopped before signing, across two testnets, in one evening, all with sra-riskgate 0.15.0.

Since then, sra-riskgate 0.18.0 builds the receipt check into the library: verify_settlement() confirms a mined receipt holds exactly the approved payment, and verify_gateway_balances() does the same for Circle Gateway.

If you build agents that pay, what would you want published with a claim like this: the log, the transaction, or a third party replaying the settlement?


Top comments (0)