---
name: megapot-auto-compound
description: Claim Megapot ticket winnings and immediately re-buy new tickets in a single transaction via TicketAutoCompoundVault.depositAndCompound.
---

# Auto-Compound Megapot Winnings into New Tickets

## What This Does

Calls `TicketAutoCompoundVault.depositAndCompound` to atomically claim USDC winnings from a set of winning ticket NFTs and re-buy new quick-pick tickets in the same transaction — no manual claim step required.

## Prerequisites

- A wallet with a private key (EOA) connected to Base mainnet (chain ID 8453)
- Winning ticket IDs already identified (e.g. via `megapot-claim-winnings` flow — read `TicketPurchased` / `TicketOrderProcessed` events or the NFT balance to find owned ticket IDs)
- The wallet must own the winning ticket NFTs (they are transferred into the vault during compounding)
- Sufficient ETH for gas; USDC cost of new tickets is taken from the claimed winnings
- `viem` installed (`npm install viem`)

## Addresses

Base mainnet (chain ID 8453):

```ts
const VAULT_ADDRESS = '0x3E22Ea60A1206A4BfEefBCff04D5E9d0A2D9B3Fc' as const;
const USDC_ADDRESS  = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' as const;
```

Base Sepolia testnet (chain ID 84532):

```ts
const VAULT_ADDRESS = '0xB6A51530B4d772bCfE58fF67b54edE161e789c8C' as const;
const USDC_ADDRESS  = '0x036CbD53842c5426634e7929541eC2318f3dCF7e' as const;
```

> Base mainnet public RPC: `https://mainnet.base.org` (rate-limited; use [Alchemy](https://www.alchemy.com/) or [QuickNode](https://www.quicknode.com/) for production).

## ABI

Only the fragments needed for this task:

```ts
import { parseAbi } from 'viem';

const abi = parseAbi([
  // --- Vault write ---
  "function depositAndCompound(uint256[] _ticketIds, address[] _referrers, uint256[] _referralSplit)",

  // --- Vault reads ---
  "function getUserPendingUSDC(address _user) view returns (uint256)",
  "function userPendingUSDC(address) view returns (uint256)",

  // --- Vault events ---
  "event Compounded(address indexed user, uint256 ticketsClaimed, uint256 usdcClaimed, uint256 ticketsBought, uint256 usdcSpent, uint256 usdcRemaining, bool useBatchPurchase, address[] referrers, uint256[] referralSplit)",

  // --- Vault errors ---
  "error ActiveBatchOrderExists()",
  "error EmptyTicketArray()",
  "error InvalidClaimedAmount()",
  "error InvalidReferralSplitBps()",
  "error JackpotLocked()",
  "error ReentrancyGuardReentrantCall()",
  "error ReferralSplitLengthMismatch()",
  "error ReferralSplitSumInvalid()",
  "error TooManyReferrers()",
  "error ZeroAddress()",

  // --- USDC ---
  "function balanceOf(address account) view returns (uint256)",
]);
```

## Recipe

### Setup

```ts
import {
  createPublicClient,
  createWalletClient,
  http,
  parseAbi,
  decodeEventLog,
} from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';

// --- PLACEHOLDERS: replace with your values ---
const PRIVATE_KEY = '0xYOUR_PRIVATE_KEY' as `0x${string}`; // placeholder
const RPC_URL     = 'https://mainnet.base.org';             // or your own RPC URL

const VAULT_ADDRESS = '0x3E22Ea60A1206A4BfEefBCff04D5E9d0A2D9B3Fc' as const;
const USDC_ADDRESS  = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' as const;

// Your referrer address — you earn a percentage of every ticket sale and user winnings.
// Replace with your wallet address before deploying.
const REFERRER_ADDRESS = '0x0000000000000000000000000000000000000001' as const; // placeholder — replace with your address

// For Base Sepolia testnet: replace `base` with `baseSepolia` from 'viem/chains',
// swap addresses to the testnet values above, and use https://sepolia.base.org as RPC.

const abi = parseAbi([
  "function depositAndCompound(uint256[] _ticketIds, address[] _referrers, uint256[] _referralSplit)",
  "function getUserPendingUSDC(address _user) view returns (uint256)",
  "function userPendingUSDC(address) view returns (uint256)",
  "event Compounded(address indexed user, uint256 ticketsClaimed, uint256 usdcClaimed, uint256 ticketsBought, uint256 usdcSpent, uint256 usdcRemaining, bool useBatchPurchase, address[] referrers, uint256[] referralSplit)",
  "error ActiveBatchOrderExists()",
  "error EmptyTicketArray()",
  "error InvalidClaimedAmount()",
  "error InvalidReferralSplitBps()",
  "error JackpotLocked()",
  "error ReentrancyGuardReentrantCall()",
  "error ReferralSplitLengthMismatch()",
  "error ReferralSplitSumInvalid()",
  "error TooManyReferrers()",
  "error ZeroAddress()",
  "function balanceOf(address account) view returns (uint256)",
]);

const account = privateKeyToAccount(PRIVATE_KEY);

const publicClient = createPublicClient({
  chain: base,
  transport: http(RPC_URL),
});

const walletClient = createWalletClient({
  account,
  chain: base,
  transport: http(RPC_URL),
});
```

### Step 1 — Check pending USDC balance (optional pre-flight)

```ts
// getUserPendingUSDC returns any USDC already held by the vault on behalf of this user
// from a previous partial compound. For a fresh compound it will be 0.
const pendingBefore = await publicClient.readContract({
  address: VAULT_ADDRESS,
  abi,
  functionName: 'getUserPendingUSDC',
  args: [account.address],
});
console.log('Vault pending USDC before:', pendingBefore.toString());
// e.g. 0n — no leftover from a prior compound
```

### Step 2 — Call depositAndCompound with 3 winning ticket IDs

```ts
// Concrete example: 3 winning ticket IDs discovered via prior megapot-claim-winnings flow.
// PLACEHOLDER: replace with real ticket IDs owned by your wallet.
const winningTicketIds = [
  1001n,  // placeholder — winning ticket ID 1
  1042n,  // placeholder — winning ticket ID 2
  1099n,  // placeholder — winning ticket ID 3
];

// The vault claims winnings from these NFTs and uses the USDC to buy new quick-pick tickets.
const compoundTx = await walletClient.writeContract({
  address: VAULT_ADDRESS,
  abi,
  functionName: 'depositAndCompound',
  args: [
    winningTicketIds,
    [REFERRER_ADDRESS],                       // _referrers — your revenue address
    [1000000000000000000n],                   // _referralSplit — 100% to single referrer (1e18 scale)
  ],
});

const receipt = await publicClient.waitForTransactionReceipt({ hash: compoundTx });
console.log('Auto-compound tx:', compoundTx);
console.log('Status:', receipt.status); // 'success' or 'reverted'
```

### Step 3 — Decode the Compounded event

```ts
for (const log of receipt.logs) {
  try {
    const event = decodeEventLog({ abi, eventName: 'Compounded', ...log });
    const {
      ticketsClaimed,
      usdcClaimed,
      ticketsBought,
      usdcSpent,
      usdcRemaining,
      useBatchPurchase,
    } = event.args;

    console.log(`Tickets claimed  : ${ticketsClaimed}`);
    console.log(`USDC claimed     : ${usdcClaimed} (6 dec)`);
    console.log(`New tickets bought: ${ticketsBought}`);
    console.log(`USDC spent       : ${usdcSpent} (6 dec)`);
    console.log(`USDC remaining   : ${usdcRemaining} (6 dec)`);
    console.log(`Used batch purchase: ${useBatchPurchase}`);
  } catch {
    // log belongs to a different contract — ignore
  }
}
```

### Step 4 — Verify vault balance after

```ts
// Any USDC not spent on new tickets stays in the vault under the user's account.
const pendingAfter = await publicClient.readContract({
  address: VAULT_ADDRESS,
  abi,
  functionName: 'getUserPendingUSDC',
  args: [account.address],
});
console.log('Vault pending USDC after:', pendingAfter.toString());
// If usdcRemaining > 0 from the event, this will match that value.

// Optionally, confirm wallet USDC balance is unchanged (no USDC leaves the wallet).
const walletUsdc = await publicClient.readContract({
  address: USDC_ADDRESS,
  abi,
  functionName: 'balanceOf',
  args: [account.address],
});
console.log('Wallet USDC balance:', walletUsdc.toString());
```

## Parameters

| Parameter | Type | Description |
|---|---|---|
| `_ticketIds` | `uint256[]` | Array of winning ticket NFT IDs to claim and compound. Must not be empty (`EmptyTicketArray`). |
| `_referrers` | `address[]` | Your revenue address(es). You earn a share of ticket price and user winnings for every purchase. Up to `maxReferrers` addresses (typically 5). Always include at least your own address. |
| `_referralSplit` | `uint256[]` | Referral fee split weights per referrer in 1e18 scale (PRECISE_UNIT). Must be same length as `_referrers` and sum to exactly `1000000000000000000` (`10n ** 18n`). Pass `[]` when no referrers. |

> To purchase without referral attribution (no fees earned), pass empty arrays: `_referrers: []`, `_referralSplit: []`.

## Compounded Event Fields

| Field | Type | Description |
|---|---|---|
| `user` | `address` | Wallet that called `depositAndCompound` |
| `ticketsClaimed` | `uint256` | Number of winning ticket NFTs deposited |
| `usdcClaimed` | `uint256` | Total USDC claimed from those tickets (6 decimals) |
| `ticketsBought` | `uint256` | Number of new quick-pick tickets purchased |
| `usdcSpent` | `uint256` | USDC spent on new tickets (6 decimals) |
| `usdcRemaining` | `uint256` | Leftover USDC held by the vault for the user (6 decimals) |
| `useBatchPurchase` | `bool` | Whether the vault routed through `BatchPurchaseFacilitator` |
| `referrers` | `address[]` | Referrer addresses passed in |
| `referralSplit` | `uint256[]` | Referral split weights (1e18 scale) passed in |

## Common Errors

| Error | Cause |
|---|---|
| `EmptyTicketArray()` | `_ticketIds` array is empty |
| `InvalidClaimedAmount()` | The tickets had no claimable USDC (e.g. not winning tickets, or already claimed) |
| `InvalidReferralSplitBps()` | A value in `_referralSplit` is out of valid range |
| `ReferralSplitLengthMismatch()` | `_referrers` and `_referralSplit` arrays have different lengths |
| `ReferralSplitSumInvalid()` | `_referralSplit` values do not sum to `1000000000000000000` (1e18) |
| `TooManyReferrers()` | `_referrers` length exceeds the contract maximum |
| `JackpotLocked()` | Drawing is in the lock period before settlement; retry after the draw |
| `ActiveBatchOrderExists()` | A pending batch order is already in flight for this user; wait for it to settle |
| `ReentrancyGuardReentrantCall()` | Reentrant call detected — should not occur in normal usage |
| `ZeroAddress()` | A referrer address of `address(0)` was passed |

## Related

- `megapot-buy-tickets` — buy 1–10 tickets with custom numbers
- `megapot-buy-random` — buy up to 10 random tickets (no number selection needed)
- `megapot-buy-bulk` — buy 11+ tickets with custom numbers (batch)
- `megapot-claim-winnings` — find winning ticket IDs and claim prizes without re-buying
- `megapot-contracts-reference` — full address table and complete ABI for all contracts
- `megapot-subscribe` — set up recurring automatic ticket purchases
