Documentation

Developer Reference for Lucy Protocol

Quick Start

Lucy is an immutable OTC escrow protocol. Makers lock tokenA, define the target tokenB amount and acceptance threshold, and contributors supply tokenB liquidity. Once an order meets the minimum fill, the maker releases tokenA to contributors and receives the matched tokenB minus protocol fees.

Contract Address

Base Mainnet deterministic deployment:

Loading...

Supported Chains

Additional networks will appear here once deployed.

Core Functions

createOrder

function createOrder(
  address tokenA,
  uint256 amountA,
  address wantedTokenB,
  uint256 wantedAmountB,
  uint16 minAcceptBps,
  uint40 matchWindowSeconds,
  bool allowCrowdFill
) external payable returns (uint256 orderId)

Makers escrow tokenA and define desired terms for wantedTokenB.

setOrderWhitelist

function setOrderWhitelist(
  uint256 orderId,
  address whitelist,
  bool whitelistOnly
) external

Makers may restrict contributors before any tokenB is deposited. Orders must still be Open and untouched.

updateOrderTerms

function updateOrderTerms(
  uint256 orderId,
  uint256 newWantedAmountB,
  uint16 newMinAcceptBps
) external

Adjust target tokenB amount or minimum acceptance while the order remains open with zero contributions. New values honor the same floors and caps as creation.

contributeToOrder

function contributeToOrder(
  uint256 orderId,
  uint256 offeredAmountB
) external payable

Contributors deposit tokenB subject to match window, whitelist rules, and contributor caps.

release

function release(uint256 orderId) external

Maker-settlement callable once the order is matched and within the release window.

Cancellation Paths

withdraw

function withdraw(address token) external

Pull claimable balances (native or ERC20). Reverts when nothing is available, preventing gas griefing.

View Helpers

Constants & Limits

Integration Guide

Using Ethers.js v6

import { ethers } from 'ethers'

const provider = new ethers.BrowserProvider(window.ethereum)
const signer = await provider.getSigner()

const contract = new ethers.Contract(
  LUCY_ADDRESS,
  LUCY_ABI,
  signer
)

const tokenA = '0x...'
const tokenB = '0x...'
const amountA = ethers.parseUnits('1000', 18)
const wantedAmountB = ethers.parseUnits('500', 6)
const minAcceptBps = 9000 // 90% minimum
const matchWindowSeconds = 3 * 24 * 60 * 60 // 3 days

// Approve tokenA first when using ERC20
const erc20 = new ethers.Contract(tokenA, ERC20_ABI, signer)
await erc20.approve(LUCY_ADDRESS, amountA)

const tx = await contract.createOrder(
  tokenA,
  amountA,
  tokenB,
  wantedAmountB,
  minAcceptBps,
  matchWindowSeconds,
  true // allow crowd-fill
)
await tx.wait()

Reading Order State

const order = await contract.orders(orderId)

console.log({
  maker: order.maker,
  tokenA: order.tokenA,
  wantedTokenB: order.wantedTokenB,
  amountA: order.amountA,
  wantedAmountB: order.wantedAmountB,
  minAcceptBps: order.minAcceptBps,
  matchExpiry: order.matchExpiry,
  releaseExpiry: order.releaseExpiry,
  allowCrowdFill: order.allowCrowdFill,
  whitelist: order.whitelist,
  whitelistOnly: order.whitelistOnly,
  totalB: order.totalB,
  state: order.state // 0=Open, 1=Partial, 2=Matched, 3=Released, 4=Cancelled
})

Verifying the Eternal Field

The eternal version is hosted on IPFS and pinned to multiple providers.

Access Points

Verification Steps

  1. Check the IPFS hash displayed in the eternal version footer
  2. Compare it to the hash advertised here: QmS78vnnjZjrsLvHaVz4qjSYiZ9yjpounF1STTBWjGbAhM
  3. Access the content via multiple gateways to verify consistency
  4. Optionally run your own IPFS node and fetch: ipfs cat QmXXX

If Everything Fails

In 2030, if all Lucy infrastructure is gone:

⚠️ Important: The eternal version uses your wallet's RPC provider. If you're using a public RPC, it may be rate-limited. For best results, configure a private RPC endpoint in your wallet or use the dynamic version.

Security Considerations

Immutability

Lucy has no owner, no admin keys, and no upgrade path. The contract cannot be paused, stopped, or modified. Interact at your own risk.

Fee-on-Transfer Tokens

Lucy supports fee-on-transfer tokens by measuring actual received amounts after each transfer.

Reentrancy Protection

All state-changing functions use a custom nonReentrant modifier to prevent reentrancy attacks.

Pull-Payment Pattern

Tokens are not sent automatically. Users must call withdraw() to claim, preventing gas griefing and external call failures from blocking settlements.