The Coinbase Commerce Onchain Payment Protocol allows payers and merchants to transact using the blockchain as a settlement layer and source of truth. It provides the following benefits over "traditional" cryptocurrency payments:
As of July 31, 2024, the Commerce Onchain Payment Protocol is deployed in the following locations:
Chain | Environment | Address |
---|---|---|
Ethereum | Mainnet | 0x1DAe28D7007703196d6f456e810F67C33b51b25C |
Ethereum | Sepolia Testnet | 0x96A08D8e8631b6dB52Ea0cbd7232d9A85d239147 |
Polygon | Mainnet | 0xc2252Ce3348B8dAf90583E53e07Be53d3aE728FB |
Polygon | Amoy Testnet | 0x1A8f790a10D26bAd97dB8Da887D212eA49461cCC |
Base | Mainnet | 0xeADE6bE02d043b3550bE19E960504dbA14A14971 |
Base | Sepolia Testnet | 0x96A08D8e8631b6dB52Ea0cbd7232d9A85d239147 |
Since the contract is non-upgradeable, these addresses will change when new versions are deployed.
The core source code can be found in Transfers.sol.
Excluded from this repo is a copy of Uniswap/permit2,
which would be copied to contracts/permit2
in order to compile.
The Transfers contract facilitates payments from a payer to a merchant. Before it may be used, an "operator" must register with the contract and specify a destination for fees. This operator is responsible for setting merchants up with the protocol and providing a UI for both merchants and payers to interact with it. Registering as an operator is permissionless, and Coinbase maintains control of an address used as the operator for Coinbase Commerce.
Once an operator is registered, they may begin facilitating payments. Individual
payments use a primitive called a TransferIntent
, represented by a Solidity
struct of the same name. This struct specifies the following:
Along with these attributes, a TransferIntent
must be signed by the operator.
This allows an operator to be selective about what payments to allow based on
internal policies, legal requirements, or other reasons. It also ensures that
a TransferIntent
cannot be forged or have its data modified in any way.
The contract ensures that, for a given valid TransferIntent
:
Depending on the settlement token and the input token, along with the way
in which the payer allows movement of their input token, a frontend must select
the appropriate method by which to pay a TransferIntent
. These methods are:
transferNative
: The merchant wants ETH and the payer wants to pay ETHtransferToken
: The merchant wants a token and the payer wants to pay with
that token. Uses Permit2 for token movement.transferTokenPreApproved
: Same as transferToken
, except the Transfers
contract is directly approved by the payer for the payment tokenwrapAndTransfer
: The merchant wants WETH and the payer wants to pay ETHunwrapAndTransfer
: The merchant wants ETH and the payer wants to pay WETHunwrapAndTransferPreApproved
: Same as unwrapAndTransfer
, except the
Transfers contract is directly approved by the payer for WETHswapAndTransferUniswapV3Native
: The merchant wants a token and the payer
wants to pay ETH. The token must have sufficient liquidity with ETH on Uniswap
V3.swapAndTransferUniswapV3Token
: The merchant wants either ETH or a token and
the payer wants to pay with a different token. The payment token must have
sufficient liquidity with the settlement token on Uniswap V3.swapAndTransferUniswapV3TokenPreApproved
: Same as
swapAndTransferUniswapV3Token
, except the Transfers contract is directly
approved by the payer for the payment tokenFor any EVM-compatible network where ETH is not the native/gas currency, the above descriptions should substitute that currency. For example, payments on Polygon would use MATIC in the above descriptions.
When the payment is successful, a Transferred
event is emitted by the contract
with details about:
TransferIntent
In the case of errors, a specific error type is returned with details about what went wrong.