Skip to content

[Airdrop P5] Finalize script (TWAP, Merkle tree, distribution) #893

@realproject7

Description

@realproject7

Parent: #877
Depends on: #878, #890

Scope

Script to finalize the campaign: compute TWAP, determine milestone, generate Merkle tree for distribution.

Built and tested during Phase 0 test run (#892), reused at actual campaign end (month 6).

Logic

1. Freeze & Calculate TWAP

  • Query pl_daily_prices for the last 7 days before campaign end
  • Compute TWAP: AVG(mcap_usd) over 7 days
  • Determine milestone:
    • mcap >= $70M → Gold (100%)
    • mcap >= $10M → Silver (30%)
    • mcap >= $1M → Bronze (10%)
    • mcap < $1M → None (0%, full burn)

2. Compute Distribution

  • Query pl_points: SUM(points) GROUP BY address
  • Compute each user's share: user_points / total_points
  • Calculate PLOT amount: share × pool_amount × milestone_pct
  • Output: { address: string, amount: bigint }[]

3. Generate Merkle Tree

  • Use @openzeppelin/merkle-tree to build tree from (address, amount) pairs
  • Output: root hash + per-user proofs
  • Store proofs in DB or JSON file for claim API

4. Deploy MerkleClaim Contract

contract PLOTAirdrop {
    IERC20 public immutable PLOT;
    bytes32 public immutable merkleRoot;
    mapping(address => bool) public claimed;

    function claim(uint256 amount, bytes32[] calldata proof) external {
        require(!claimed[msg.sender], "Already claimed");
        bytes32 leaf = keccak256(abi.encodePacked(msg.sender, amount));
        require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof");
        claimed[msg.sender] = true;
        PLOT.transfer(msg.sender, amount);
    }
}

Standard OpenZeppelin MerkleProof-based contract.

5. Transfer & Burn

  • P7 calls unlock() on Mint Club Locker to retrieve PLOT
  • Transfer earned portion to MerkleClaim contract
  • Send burn portion to 0x000000000000000000000000000000000000dEaD

Files

  • scripts/airdrop-finalize.ts
  • contracts/MerkleClaim.sol

Acceptance Criteria

  • TWAP calculation uses last 7 days of pl_daily_prices
  • Milestone determination matches config thresholds
  • Distribution amounts sum to exactly pool_amount × milestone_pct
  • Merkle tree generated with valid proofs
  • MerkleClaim contract deployable on Base
  • Proofs stored and accessible for claim API

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/T3Assigned to T3 builder agentairdropPLOT 10x Airdrop Campaign

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions