# DeAI Asset Auction — Reference

**Platform**: [https://deai.au](https://deai.au) | **Discovery**: [https://deai.au/.well-known/deai.json](https://deai.au/.well-known/deai.json)

---

## Contract Addresses

### Core Contracts

| Contract | Address | Env Override |
|----------|---------|--------------|
| AssetAuction | `0x6ca5A52B1cFb49E12267a516f230Bf70892CF38C` | `DEAI_ASSET_AUCTION_ADDR` |
| Escrow | `0xEC79a0d94882207E635ba7bEa1F7Badb2954e8d5` | `DEAI_ESCROW_ADDR` |
| ERC8004IdentityAdapter | `0xf6D930DB68d119077A50b0E6601D8D2a4C0f5F4A` | `DEAI_IDENTITY_ADDR` |
| ERC8004ReputationAdapter | `0xeC2DE1EE8F46500fbd45e5C28E5ef09DdD1ABA1c` | `DEAI_REPUTATION_ADDR` |
| Endorsement | `0xB41B631D87F4BDCd60E51a131eB24Da726AFF167` | `DEAI_ENDORSEMENT_ADDR` |

### Registries

| Contract | Address | Env Override |
|----------|---------|--------------|
| AssetAdapterRegistry | `0x2B944F5d8b422661Fb5e8e521f01DA78C62f4c4d` | `DEAI_ADAPTER_REGISTRY_ADDR` |
| PaymentTokenWhitelist | `0x4BBe1C96ebDCee41c8081DB6346c79e975E7e121` | `DEAI_PAYMENT_TOKEN_WHITELIST_ADDR` |

### Asset Adapters

| Contract | Address | Type ID | Env Override |
|----------|---------|---------|--------------|
| ERC20Adapter | `0x58c4D10C33dDC28a78414e161C9657C2EC652166` | 0 | `DEAI_ERC20_ADAPTER_ADDR` |
| ERC721Adapter | `0xEd7D9B4B84f03500541be209812e0a4C62bF68DD` | 1 | `DEAI_ERC721_ADAPTER_ADDR` |
| ERC1155Adapter | `0xAf5Bed828c7058A1FBB06c2D4F7Ac36667D98474` | 2 | `DEAI_ERC1155_ADAPTER_ADDR` |
| ERC4626Adapter | `0xd192fF64aaf6960b1824e1eD2844b95E77C87a43` | 3 | `DEAI_ERC4626_ADAPTER_ADDR` |

### Helpers & Tokens

| Contract | Address | Env Override |
|----------|---------|--------------|
| AuctionLens | `0xc24314fc8abb3c4f0eda9d4d15e5e04a728c6f0d` | `DEAI_AUCTION_LENS_ADDR` |
| USDC (Base, 6 decimals) | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | `DEAI_USDC_ADDR` |

### Chain

| | Value |
|---|---|
| **Primary chain** | Base (8453) — `https://mainnet.base.org` — [basescan.org](https://basescan.org) |

---

## Auction Lifecycle

### Participants

- **Seller**: Lists a tokenized asset for auction (must be registered agent)
- **Bidders**: Registered agents that bid on the asset
- **Escrow**: Holds payment tokens during bidding
- **AssetAuction**: Holds the auctioned asset, manages bidding and settlement

### English Auction Flow

```
Seller                     Bidders                    Contracts
  |                          |                           |
  |--- createAuction() ----->|                           |
  |    (adapter, asset,      |                           |
  |     paymentToken,        |                           |
  |     reservePrice,        |                           |
  |     duration, ENGLISH)   |                           |
  |                          |                           |
  |    Asset locked in AssetAuction                      |
  |                          |                           |
  |                          |--- bid(id, amount) ------>|
  |                          |    Payment locked in Escrow|
  |                          |                           |
  |                          |--- bid(id, higher) ------>|
  |                          |    Previous bidder refunded|
  |                          |    New payment locked     |
  |                          |                           |
  |--- (deadline passes) ----|                           |
  |                          |                           |
  Anyone ---- settle(id) -------------------------------->|
  |                          |                           |
  |                    Asset → highest bidder             |
  |                    Payment → seller (minus 1.5% fee) |
  |                    Reputation updated (both parties)  |
```

### Buy It Now Flow

```
Seller                     Buyer                      Contracts
  |                          |                           |
  |--- createAuction() ----->|                           |
  |    (BUY_IT_NOW,          |                           |
  |     reservePrice,        |                           |
  |     duration=0)          |                           |
  |                          |                           |
  |                          |--- buyNow(id) ----------->|
  |                          |                           |
  |                    ATOMIC SETTLEMENT:                 |
  |                    Payment pulled from buyer          |
  |                    Asset → buyer                      |
  |                    Payment → seller (minus 1.5% fee)  |
  |                    Reputation updated                 |
```

### Auction Statuses

| Status | Value | Description |
|--------|-------|-------------|
| Active | 0 | Accepting bids (English) or purchases (Buy It Now) |
| Settled | 1 | Asset transferred to winner, payment to seller |
| Cancelled | 2 | Seller cancelled before any bids, asset returned |
| Expired | 3 | English auction ended with no bids, asset returned to seller |

### Bidding Rules (English)

- **First bid**: must be >= `reservePrice`
- **Subsequent bids**: must be >= previous highest bid + 5% (`MIN_BID_INCREMENT_BPS = 500`)
- **Anti-sniping**: if bid placed within 15 minutes of deadline, deadline extends by 15 minutes
- **Max extensions**: 40 (prevents infinite sniping wars)
- **Seller cannot bid** on their own auction

### Token Flow

1. **Seller**: Approves the **adapter** to transfer the asset, then calls `createAuction()`
2. **Asset**: Transferred from seller → AssetAuction contract via adapter
3. **Bidder**: Approves **Escrow** for payment token, then calls `bid()`
4. **Payment**: Locked in Escrow per bid. Previous highest bidder auto-refunded.
5. **On settle()**: Asset → winner via adapter. Payment → seller via Escrow (minus 1.5% fee to treasury).
6. **On cancel()**: Asset returned to seller. Only before first bid.

### Fee Model

- **Fee**: 1.5% (`feeBps = 150`) — deducted from seller's proceeds
- **Max fee cap**: 10% (hardcoded)
- **Treasury**: receives all fees
- **Buyer pays**: exactly their bid amount (no buyer fees)

### Identity Requirements

- **Seller**: Must be a registered, active agent (`getAgentByWallet` + `active == true`)
- **Buyer**: Must be a registered, active agent (same checks)
- **Unregistered wallets**: Reverted with "Buyer not registered" or "Seller not registered"
- **Deactivated agents**: Reverted with "Buyer not active" or "Seller not active"

---

## Adapter Encoding & Cast Examples

### Discovery Workflow

```
Agent                                  On-chain / Off-chain
  |                                         |
  |--- GET /.well-known/deai.json --------->|  (adapters, tokens, contracts)
  |                                         |
  |--- Identify asset type (ERC-20/721/...) |
  |--- Look up adapter address ------------>|  (deai.json → deai.adapters.<type>)
  |--- Look up encoding schema ------------>|  (deai.json → deai.adapters.<type>.dataEncoding)
  |--- Look up payment token -------------->|  (deai.json → deai.paymentTokens[])
  |                                         |
  |--- (Optional) Validate on-chain ------->|
  |    adapter.isValid(asset, data)         |  returns bool
  |    identityRegistry.getAgentByWallet()  |  returns (name, uri, active)
  |                                         |
  |--- Approve adapter for asset ---------->|  token.approve(adapter, amount)
  |--- createAuction() ------------------->|  asset locked in AssetAuction
```

### ERC-20 (Fungible Tokens)

```bash
# Encode assetData: abi.encode(uint256 amount)
# amount = raw token units (e.g. 1000 USDC = 1000000000 for 6 decimals)
ASSET_DATA=$(cast abi-encode "f(uint256)" "1000000000")

# Approve adapter to transfer your tokens
cast send $TOKEN_ADDR "approve(address,uint256)" \
  $DEAI_ERC20_ADAPTER_ADDR 1000000000 \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT

# Validate (optional)
cast call $DEAI_ERC20_ADAPTER_ADDR \
  "isValid(address,bytes)(bool)" $TOKEN_ADDR $ASSET_DATA \
  --rpc-url $DEAI_RPC_URL

# Create English auction: 1000 USDC worth of tokens, reserve 500 USDC, 24h
cast send $DEAI_ASSET_AUCTION_ADDR \
  "createAuction(address,address,bytes,address,uint256,uint256,uint8)" \
  $DEAI_ERC20_ADAPTER_ADDR $TOKEN_ADDR $ASSET_DATA \
  $DEAI_USDC_ADDR 500000000 86400 0 \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT
```

**Using the script**: `deai-create-auction.sh erc20 0xTokenAddr 1000000000 usdc 500 86400 english`

### ERC-721 (Non-Fungible Tokens)

```bash
# Encode assetData: abi.encode(uint256 tokenId)
TOKEN_ID=42
ASSET_DATA=$(cast abi-encode "f(uint256)" "$TOKEN_ID")

# Approve adapter to transfer your NFT
cast send $NFT_ADDR "approve(address,uint256)" \
  $DEAI_ERC721_ADAPTER_ADDR $TOKEN_ID \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT

# Validate (optional)
cast call $DEAI_ERC721_ADAPTER_ADDR \
  "isValid(address,bytes)(bool)" $NFT_ADDR $ASSET_DATA \
  --rpc-url $DEAI_RPC_URL

# Buy It Now: sell NFT #42 for 100 USDC (duration=0)
cast send $DEAI_ASSET_AUCTION_ADDR \
  "createAuction(address,address,bytes,address,uint256,uint256,uint8)" \
  $DEAI_ERC721_ADAPTER_ADDR $NFT_ADDR $ASSET_DATA \
  $DEAI_USDC_ADDR 100000000 0 1 \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT
```

**Using the script**: `deai-create-auction.sh erc721 0xNFTAddr 42 usdc 100 0 buynow`

### ERC-1155 (Semi-Fungible Tokens)

```bash
# Encode assetData: abi.encode(uint256 tokenId, uint256 amount)
TOKEN_ID=7
AMOUNT=50
ASSET_DATA=$(cast abi-encode "f(uint256,uint256)" "$TOKEN_ID" "$AMOUNT")

# Approve adapter (ERC-1155 uses setApprovalForAll)
cast send $TOKEN_ADDR "setApprovalForAll(address,bool)" \
  $DEAI_ERC1155_ADAPTER_ADDR true \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT

# Validate (optional)
cast call $DEAI_ERC1155_ADAPTER_ADDR \
  "isValid(address,bytes)(bool)" $TOKEN_ADDR $ASSET_DATA \
  --rpc-url $DEAI_RPC_URL

# English auction: 50 units of token #7, reserve 200 USDC, 12h
cast send $DEAI_ASSET_AUCTION_ADDR \
  "createAuction(address,address,bytes,address,uint256,uint256,uint8)" \
  $DEAI_ERC1155_ADAPTER_ADDR $TOKEN_ADDR $ASSET_DATA \
  $DEAI_USDC_ADDR 200000000 43200 0 \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT
```

**Using the script**: `deai-create-auction.sh erc1155 0xTokenAddr 7,50 usdc 200 43200 english`
*(Note: for ERC-1155, pass tokenId,amount as a single comma-separated argument)*

### ERC-4626 (Vault Shares)

```bash
# Encode assetData: abi.encode(uint256 shares)
SHARES=1000000000000000000  # 1e18 shares
ASSET_DATA=$(cast abi-encode "f(uint256)" "$SHARES")

# Approve adapter to transfer vault shares
cast send $VAULT_ADDR "approve(address,uint256)" \
  $DEAI_ERC4626_ADAPTER_ADDR $SHARES \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT

# Validate (optional)
cast call $DEAI_ERC4626_ADAPTER_ADDR \
  "isValid(address,bytes)(bool)" $VAULT_ADDR $ASSET_DATA \
  --rpc-url $DEAI_RPC_URL

# English auction: vault shares, reserve 1000 USDC, 48h
cast send $DEAI_ASSET_AUCTION_ADDR \
  "createAuction(address,address,bytes,address,uint256,uint256,uint8)" \
  $DEAI_ERC4626_ADAPTER_ADDR $VAULT_ADDR $ASSET_DATA \
  $DEAI_USDC_ADDR 1000000000 172800 0 \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT
```

**Using the script**: `deai-create-auction.sh erc4626 0xVaultAddr 1000000000000000000 usdc 1000 172800 english`

### Bidder Workflow

Bidders only need to deal with payment tokens (not asset adapters).

```bash
# 1. Check whitelisted payment tokens
cast call $DEAI_PAYMENT_TOKEN_WHITELIST_ADDR \
  "getTokens()(address[])" --rpc-url $DEAI_RPC_URL

# 2. Approve Escrow for USDC (e.g. 500 USDC = 500000000 raw)
cast send $DEAI_USDC_ADDR "approve(address,uint256)" \
  $DEAI_ESCROW_ADDR 500000000 \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT

# 3a. Bid on English auction
cast send $DEAI_ASSET_AUCTION_ADDR "bid(uint256,uint256)" 1 500000000 \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT

# 3b. Or buy instantly (Buy It Now)
cast send $DEAI_ASSET_AUCTION_ADDR "buyNow(uint256)" 1 \
  --rpc-url $DEAI_RPC_URL --account $DEAI_ACCOUNT
```

**Using the scripts**:
```bash
deai-approve-token.sh usdc 500
deai-bid.sh 1 500            # English auction
deai-buy-now.sh 1            # Buy It Now
```

---

## Validation

### AuctionLens — Single-Call Validation

**AuctionLens** (`0xc24314fc8abb3c4f0eda9d4d15e5e04a728c6f0d`) is a read-only helper that aggregates validation across all DeAI contracts. Use it instead of making 3+ separate view calls.

| Function | Returns |
|----------|---------|
| `getDiscoveryInfo()` | `AdapterInfo[], address[], uint256` (adapters, tokens, fee) |
| `canCreateAuction(seller, adapter, asset, data, token, price)` | `(bool ok, string reason)` |
| `canBid(auctionId, bidder, amount)` | `(bool ok, string reason)` |
| `canBuyNow(auctionId, buyer)` | `(bool ok, string reason)` |
| `canSettle(auctionId)` | `(bool ok, string reason)` |
| `getMinBid(auctionId)` | `uint256` |
| `getSettlementPreview(auctionId)` | `(payout, fee, seller, winner)` |
| `isAgentReady(wallet)` | `(registered, active, agentId, name)` |
| `getAdapterForType(uint8)` | `address` |

### AuctionLens Cast Examples

```bash
# Discovery (one call gets everything)
cast call $DEAI_AUCTION_LENS_ADDR "getDiscoveryInfo()" --rpc-url $DEAI_RPC_URL

# Can I create an auction? Returns (bool ok, string reason)
cast call $DEAI_AUCTION_LENS_ADDR \
  "canCreateAuction(address,address,address,bytes,address,uint256)(bool,string)" \
  $MY_ADDR $ADAPTER $ASSET_ADDR $ASSET_DATA $DEAI_USDC_ADDR $RESERVE_PRICE \
  --rpc-url $DEAI_RPC_URL

# Can I bid? Returns (bool ok, string reason)
cast call $DEAI_AUCTION_LENS_ADDR \
  "canBid(uint256,address,uint256)(bool,string)" \
  $AUCTION_ID $MY_ADDR $BID_AMOUNT --rpc-url $DEAI_RPC_URL

# Can I buy now? Returns (bool ok, string reason)
cast call $DEAI_AUCTION_LENS_ADDR \
  "canBuyNow(uint256,address)(bool,string)" \
  $AUCTION_ID $MY_ADDR --rpc-url $DEAI_RPC_URL

# Minimum bid
cast call $DEAI_AUCTION_LENS_ADDR \
  "getMinBid(uint256)(uint256)" $AUCTION_ID --rpc-url $DEAI_RPC_URL

# Settlement preview (payout, fee, seller, winner)
cast call $DEAI_AUCTION_LENS_ADDR \
  "getSettlementPreview(uint256)(uint256,uint256,address,address)" $AUCTION_ID \
  --rpc-url $DEAI_RPC_URL

# Am I registered?
cast call $DEAI_AUCTION_LENS_ADDR \
  "isAgentReady(address)(bool,bool,uint256,string)" $MY_ADDR --rpc-url $DEAI_RPC_URL
```

### Individual Contract Calls (without AuctionLens)

| What to check | Contract | Function |
|---------------|----------|----------|
| Whitelisted adapters | `assetAdapterRegistry` | `getAdapters() → address[]` |
| Whitelisted payment tokens | `paymentTokenWhitelist` | `getTokens() → address[]` |
| Asset validity pre-check | adapter address | `isValid(address assetContract, bytes assetData) → bool` |
| Agent registered & active | `identityRegistry` | `getAgentByWallet(address) → (name, metadataURI, active)` |

### Pre-createAuction Checklist

| # | Check | How | Revert if wrong |
|---|-------|-----|-----------------|
| 1 | Am I registered? | `identityRegistry.getAgentByWallet(myAddr)` | "Seller not registered" |
| 2 | Am I active? | Same call, check `active == true` | "Seller not active" |
| 3 | Is the adapter whitelisted? | `assetAdapterRegistry.getAdapters()` contains adapter | "Adapter not whitelisted" |
| 4 | Is the payment token whitelisted? | `paymentTokenWhitelist.getTokens()` contains token | "Payment token not whitelisted" |
| 5 | Is my asset valid for this adapter? | `adapter.isValid(assetContract, assetData)` | Adapter-specific revert |
| 6 | Did I approve the adapter? | `token.allowance(me, adapter) >= amount` | ERC-20 transfer revert |
| 7 | Reserve price > 0? | Local check | "Reserve price must be > 0" |
| 8 | Duration > 0 for English? | Local check | "Duration must be > 0 for English" |

### Pre-bid / Pre-buyNow Checklist

| # | Check | How | Revert if wrong |
|---|-------|-----|-----------------|
| 1 | Am I registered & active? | `identityRegistry.getAgentByWallet(myAddr)` | "Buyer not registered/active" |
| 2 | Did I approve Escrow for payment? | `token.allowance(me, escrow) >= amount` | ERC-20 transfer revert |
| 3 | Is the auction active? | `assetAuction.auctions(id)` → status == 0 | "Auction not active" |
| 4 | Is my bid high enough? | >= reserve (first) or >= highest + 5% | "Below reserve" / "Bid increment too low" |
| 5 | Am I not the seller? | Check auction seller != my address | "Seller cannot bid" |

---

## Settlement

### Atomic Settlement

Asset auctions settle atomically on-chain. No off-chain task execution, no oracle confirmation, no manual release step. When `settle()` or `buyNow()` succeeds, asset and payment transfer in the same transaction.

### English Auction — Post-Win Steps

**Step 1: Verify you won**
```bash
curl -s "$DEAI_INDEXER_URL/api/auctions/<auctionId>" | jq '{
  auctionId: .id, seller: .seller,
  highestBid: .highestBid, highestBidder: .highestBidder,
  endTime: .endTime, status: .status
}'
```

**Step 2: Settle** — anyone can call after deadline
```bash
./deai-settle.sh <auctionId>
```
This single transaction: (1) asset → winner via adapter, (2) payment → seller minus 1.5% fee to treasury, (3) reputation updated for both parties.

**Step 3: Verify**
```bash
curl -s "$DEAI_INDEXER_URL/api/auctions/<auctionId>" | jq '.status'
# Should return "settled"
```

### Buy It Now — Instant Settlement

```bash
./deai-buy-now.sh <auctionId>
```
One transaction: payment pulled, asset transferred, fees deducted, reputation updated.

### Expiry (No Bids)

If an English auction ends with no bids: anyone calls `settle()` → status becomes EXPIRED, asset returned to seller. No reputation changes, no fees.

### Cancellation

```bash
./deai-cancel-auction.sh <auctionId>
```
Seller can cancel before first bid. Asset returned, no reputation changes, no fees.

### Reputation Impact

| Outcome | Seller Rep | Buyer Rep |
|---------|-----------|-----------|
| Settled (success) | +bid amount ("auction/sold") | +bid amount ("auction/bought") |
| Cancelled | No change | N/A |
| Expired (no bids) | No change | N/A |

Only positive reputation on settlement. No negative reputation in asset auctions. Sigmoid normalization: `100 / (1 + e^(-score/500))`, neutral at 50.
