Skip to content

Fix trade history recording Zap contract as trader + backfill existing records #613

@realproject7

Description

@realproject7

Bug

When trading via the Zap contract, the `trade_history` table records the Zap contract address (`0xAe50C9444DA2Ac80B209dC8B416d1B4A7D3939B0`) as `user_address` instead of the actual user's wallet.

Example tx: https://basescan.org/tx/0x22a786af3c740d5edd26419c424a7684023732bde8a68b7cdfebb2a9e0d03324

Root Cause

Indexer reads the wrong field from the MCV2_Bond event.

The `Mint`/`Burn` events emit two address fields:

```solidity
event Mint(address indexed token, address indexed user, address receiver, uint256 amountMinted, address indexed reserveToken, uint256 reserveAmount);
event Burn(address indexed token, address indexed user, address receiver, uint256 amountBurned, address indexed reserveToken, uint256 refundAmount);
```

  • `user` (indexed) = `msg.sender` — the caller (Zap contract for Zap trades)
  • `receiver` (not indexed) = the actual wallet that receives/sends the tokens

The indexer currently reads `args.user`:

```typescript
// src/app/api/index/trade/route.ts:124
user_address: args.user.toLowerCase(),

// src/app/api/cron/trade-history/route.ts:218
user_address: args.user.toLowerCase(),
```

Should read `args.receiver` instead.

Fix

1. Fix the indexer — read `receiver` instead of `user`

In both trade indexing locations:

```typescript
user_address: args.receiver.toLowerCase(),
```

Files:

  • `src/app/api/index/trade/route.ts` — line 124
  • `src/app/api/cron/trade-history/route.ts` — line 218

2. Filter out intermediate Zap mints

When Zap does HUNT→PLOT conversion, it calls `BOND.mint(plotToken, ..., address(this))` — the `receiver` is the Zap contract itself (intermediate step). These should be excluded from trade history since they're internal transfers, not user trades.

Add filter: skip trades where `receiver` is the Zap contract address.

3. Backfill existing records

After deploying the fix, run a backfill to correct all existing `trade_history` rows where `user_address` is the Zap contract address. Re-decode the event logs from the original transactions and extract the `receiver` field.

```sql
-- Check how many records are affected
SELECT COUNT(*) FROM trade_history
WHERE user_address = '0xae50c9444da2ac80b209dc8b416d1b4a7d3939b0';
```

The backfill should:

  1. Query all `trade_history` rows where `user_address` = Zap contract
  2. For each, fetch the tx receipt from RPC
  3. Re-decode the Mint/Burn event and extract `receiver`
  4. Update the row with the correct `user_address`
  5. Delete rows where `receiver` = Zap contract (intermediate mints)

4. Also fix the backfill script

`src/app/api/backfill-user-address/route.ts:82` has the same bug — reads `args.user` instead of `args.receiver`.

Files to modify

  • `src/app/api/index/trade/route.ts` — read `args.receiver`
  • `src/app/api/cron/trade-history/route.ts` — read `args.receiver`
  • `src/app/api/backfill-user-address/route.ts` — read `args.receiver`
  • New: backfill migration/script to fix existing Zap trades

Branch

`task/613-fix-zap-trade-user`

Acceptance criteria

  • New Zap trades record the actual user wallet, not the Zap contract
  • Intermediate HUNT→PLOT mints (receiver = Zap) are excluded from trade history
  • Existing incorrect records backfilled with correct user addresses
  • Direct trades (non-Zap) continue to work correctly
  • Build passes

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/T3Assigned to T3 builder agent

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions