Smart Contract

Escrow Contract

A transparent ERC20 escrow design for locking crypto during P2P trades, with seller release, timeout refund, and arbiter dispute resolution.

CoinRep Standard

Clear rules before action

Contract purpose

The contract holds ERC20 tokens for a trade until the seller releases to the buyer, the seller refunds after expiry, or an arbiter resolves a dispute.

Trade creation

A trade records the buyer, seller, token, amount, expiry time, and current state. The seller funds the escrow by transferring the exact token amount into the contract.

Release path

After fiat payment is confirmed off-chain, the seller releases escrowed crypto to the buyer. A platform fee can be routed to a fee recipient if configured.

Refund path

If the trade expires without payment confirmation, the seller can refund the escrowed crypto back to their own wallet.

Dispute path

Either party can mark a funded trade as disputed. The arbiter can then resolve funds to buyer, seller, or split between both parties.

Platform controls

The owner can pause new sensitive actions, update the arbiter, and configure a capped fee recipient for released trades.

Escrow funding logic

The seller funds a created trade by transferring the exact ERC20 amount into the contract. Once funded, the trade can move to release, refund, or dispute resolution. This mirrors the trade-room flow users already see on CoinRep.

Created: trade exists but token is not locked yet.

Funded: token has moved into escrow.

Released: buyer receives crypto after payment confirmation.

Disputed: arbiter can split or resolve funds.

function fundTrade(uint256 tradeId) external nonReentrant whenNotPaused {
    Trade storage trade = trades[tradeId];
    require(msg.sender == trade.seller, "Only seller funds");
    require(trade.status == TradeStatus.Created, "Trade not fundable");

    trade.status = TradeStatus.Funded;
    trade.fundedAt = block.timestamp;
    trade.token.safeTransferFrom(msg.sender, address(this), trade.amount);
}