Organization
- @coinbase
Engagement Type
Cantina Reviews
Period
-
Repositories
Findings
Informational
3 findings
3 fixed
0 acknowledged
Informational3 findings
Zero-fee documentation conflicts with fixed fee receiver validation
Severity
- Severity: Informational
Submitted by
Sujith S
Description
The documentation in
docs/Fees.md:133states thatfeeAmount = 0 with feeReceiver = address(0)succeeds whenPaymentInfo.feeReceiveris a fixed nonzero address. However,_validateFee()unconditionally compares both receiver addresses and reverts with InvalidFeeReceiver. Integrations following the documentation may therefore unexpectedly fail charge() or capture() calls.Recommendation
Align the documentation and implementation. Either require the configured receiver in the example, or skip receiver matching when
feeAmount == 0.Coinbase: Fixed in 94367139.
Cantina: Verified fix. No code changes made, the fix is documentation-only.
Capture fragmentation bypasses the aggregate minimum fee
Severity
- Severity: Informational
Submitted by
Sujith S
Description
Each capture independently computes
minFee = floor(captureAmount × minFeeBps / 10,000). An authorized operator can fragment a payment into sufficiently small captures so every minimum rounds to zero.For a zero-decimal token, a 100-token authorization with a fixed 1% fee requires 1 token when captured once, but 100 one-token captures each accept
feeAmount = 0. Exploitation is constrained by operator trust (as fee receiver will be the operator at present), transaction costs, and token denomination. If the operator trust model changes this may become profitable for low-decimal high-value tokens.Recommendation
Document this as "accepted risk". Alternatively, explicitly define
minFeeBpsas a per-capture guarantee and restrict uneconomically small captures.Coinbase: Fixed in 94367139.
Cantina: Verified fix. No code changes made, the fix is documentation-only.
Changed event signatures silently break offchain consumers filtering by topic0
Severity
- Severity: Informational
Submitted by
Cryptara
Description
The PR changes
uint16 feeBpstouint256 feeAmountin thePaymentChargedandPaymentCapturedevents. Because an event's topic0 is the keccak256 of its full signature, both events get new selectors.Offchain indexers, reconciliation and monitoring that filter logs by the old topic0 will not error — they will simply observe zero events from the new deployment. The failure mode is silent data loss rather than a crash, so it can go unnoticed.
Two aggravating factors:
- The currently deployed AuthCaptureEscrow instances on Base mainnet/Sepolia emit the old-format events, so both formats will coexist during migration.
- The third data field changes meaning from a rate (bps) to an absolute token amount; a consumer migrated to the new address but decoding with the old ABI would misinterpret values (e.g. reading
25e6as bps) rather than fail.
Recommendation
Call out the selector change explicitly in release/migration notes, publish both topic0 values for integrators, and version the deployment docs + SDK ABIs together with the redeployment.
Coinbase: Fixed in 94367139.
Cantina: Verified fix. No code changes made, the fix is documentation-only.