Proof-of-concept bundle-assisted OTC NFT trades. Purchase funds are escrowed by a smart contract, but the token transfer is performed by the seller as part of an atomic bundle of transactions submitted to a block builder that also validate and withdraw the funds.
This would allow for OTC sales of tokens that explicitly forbid all but direct transfers by validated EOAs, where the only trusted party is the block builder and their private mempool.
A sale consists of four transactions made in two stages:
The buyer submits a deposit to pay for a specific token (address + ID) as well as a recipient address of the token. The deposit is held in escrow by the contract and may be withdrawn at any time.
To prevent front-running of withdrawals, the buyer must provide the seller with a signature of the following struct:
struct Claim {
address tokenAddress;
uint256 tokenId;
uint256 expiredTimestamp;
}
To somewhat mitigate signature collection, the expiredTimestamp must be at most 30 minutes in the future.
The seller submits a bundle of transactions to a block builder on the condition that they all must succeed.
- The seller calls
commitClaim
to commit to selling a specific token (address + ID) to a specific buyer for a specific amount.- The seller is verified to be the owner of the token. The seller, the buyer, and the amount are stored along with the current block number.
- The seller transfers the token to the specified recipient according to the buyer's deposit.
- The seller calls
claimDeposit
with the Claim struct, buyer address, and buyer-provided signature.- The signature and commitments are validated, ownership of the token is verified to be the buyer-specified recipient, and the deposit entry is cleared with the amount forwarded to the seller specified in the commitment.
- The seller must be able to submit a bundle of transactions to a block builder on the condition that they all must succeed.
- The block builder must honor this bundle and its conditions.
- The network must process all transactions as part of the same block. On some networks, each transaction is its own block.