Crypto escrow system development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Crypto escrow system development
Medium
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1238
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1167
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    867
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1080
  • image_logo-advance_0.png
    B2B Advance company logo design
    563
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    829

Development of Crypto Escrow System

In a transaction between two strangers without escrow — one pays first and hopes. It works until the first scammer. Traditional escrow services solve this through a trusted intermediary, but in crypto "trusted intermediary" is either a centralized platform (breaks with regulatory issues) or a smart contract (doesn't sleep, takes no bribes, executes conditions deterministically).

Basic Mechanics and Where It Breaks

Simplest escrow contract: buyer deposits funds → seller fulfills condition → buyer confirms → funds released. Problem — what if buyer doesn't confirm? Funds are locked forever.

Basic contract without timeout isn't an escrow, it's a trap. Minimal correct scheme requires:

  1. Timeout with automatic refund — if buyer doesn't confirm in N days, seller can request refund. Or vice versa — if seller doesn't fulfill condition, buyer withdraws deposit.
  2. Arbitration — third party with right to override the decision. Can be specific arbiter (address), multisig, or DAO.
  3. Dispersive model — arbiter doesn't receive funds, only decides proportion of return (75% to buyer, 25% to seller).

In Depth: Arbitration Model and Collusion Prevention

The most complex part of escrow design is not basic mechanics but arbitration model. Problem: if arbiter has absolute power over funds, they become attack target (bribes, key compromise). If arbiter is chosen by parties — collusion risk appears.

Practical patterns we apply:

Commit-reveal arbitration. Both parties independently send encrypted decision to arbiter, arbiter reveals decision only after receiving both. Doesn't eliminate collusion but complicates it.

Claimant-opponent arbitration (ERC-792 style). Each party provides evidence (document hashes, IPFS CID), arbiter votes publicly. Decision is recorded in contract and auditable.

Random arbiter from pool. Kleros Protocol implements this via decentralized court — random juror selection from stakers, economic incentive to vote honestly. Integrate via IArbitrable / IArbitrator interfaces.

Contract structure with Kleros support:

contract Escrow is IArbitrable {
    IArbitrator public immutable arbitrator;
    uint256 public disputeId;
    
    enum Status { Pending, Active, Disputed, Resolved }
    
    struct Deal {
        address buyer;
        address seller;
        uint256 amount;
        uint256 timeout;
        Status status;
        uint8 buyerPercent; // arbiter decision
    }
    
    function raiseDispute(uint256 dealId) external payable {
        Deal storage deal = deals[dealId];
        require(deal.status == Status.Active);
        require(msg.value >= arbitrator.arbitrationCost(""));
        deal.status = Status.Disputed;
        disputeId = arbitrator.createDispute{value: msg.value}(
            2, // NUMBER_OF_CHOICES: buyer wins / seller wins
            ""
        );
        emit Dispute(arbitrator, disputeId, dealId);
    }
    
    function rule(uint256 _disputeId, uint256 _ruling) 
        external override 
    {
        require(msg.sender == address(arbitrator));
        // _ruling: 1 = buyer wins, 2 = seller wins
        _executeRuling(_disputeId, _ruling);
    }
}

ERC-20 vs Native ETH: Non-obvious Differences

Escrow with native ETH is simpler — send msg.value, return via call. Escrow with ERC-20 requires approve before deposit. This creates two attack scenarios:

Token approval front-running. Classic attack: user does approve(spender, 100), then approve(spender, 200). Attacker-spender manages to withdraw 100 twice in between. Solution: always do approve(spender, 0) before new approve, or use permit (EIP-2612) — signature instead of on-chain approve.

Fee-on-transfer tokens. Deflationary tokens deduct fee on every transfer. Contract receives less than was deposited. Need to verify actually received amount: uint256 before = token.balanceOf(address(this)); token.transferFrom(...); uint256 received = token.balanceOf(address(this)) - before;

Multi-Currency Escrow

If system must support both ETH and ERC-20 — create unified interface via "zero address for ETH" pattern:

function deposit(address token, uint256 amount) external payable {
    if (token == address(0)) {
        require(msg.value == amount);
    } else {
        require(msg.value == 0);
        IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
    }
}

SafeERC20 from OpenZeppelin is mandatory — standard transfer on some tokens (USDT) doesn't return bool, safeTransfer handles this correctly.

Development Process

Design mechanics (0.5-1 day). Determine: who is arbiter (EOA, multisig, Kleros), what timeouts, supported tokens, need partial release.

Development and tests (2-4 days). Foundry with fuzzing — test boundary cases for timeouts, edge cases with fee-on-transfer tokens, dispute resolution scenarios. Separate tests for reentrancy via ReentrancyGuard.

Audit and deployment. For systems with TVL > $100K — external audit from at least one provider. Audit timeline: 1-2 weeks. Deploy with verification on Etherscan/Polygonscan.