---
name: megapot-lp-deposit
description: Add USDC liquidity to the Megapot jackpot pool via Jackpot.lpDeposit. Deposit becomes active after the current drawing settles.
---

# LP Deposit (Add USDC Liquidity)

## What This Does

Approves USDC spend and calls `Jackpot.lpDeposit` to add USDC liquidity to the Megapot jackpot pool. The deposit is queued as a pending deposit and becomes active once the current drawing settles. USDC approval must target the **Jackpot** contract directly — not `JackpotLPManager`.

## Prerequisites

- A wallet with a private key (EOA) connected to Base mainnet (chain ID 8453)
- Sufficient USDC balance (6 decimals — 500 USDC = `500_000_000n`)
- Sufficient ETH for gas
- Pool capacity available: deposit amount must not exceed `lpPoolCap - (lpPoolTotal + pendingDeposits)`. Both the already-active pool (`lpPoolTotal`) and currently-queued deposits (`pendingDeposits`) count against the cap; ignoring `lpPoolTotal` will reliably under-report usage and overstate remaining capacity once the pool fills.
- `viem` installed (`npm install viem`)

## Addresses

Base mainnet (chain ID 8453):

```ts
const JACKPOT_ADDRESS     = '0x3bAe643002069dBCbcd62B1A4eb4C4A397d042a2' as const;
const LP_MANAGER_ADDRESS  = '0xE63E54DF82d894396B885CE498F828f2454d9dCf' as const;
const USDC_ADDRESS        = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' as const;
```

Base Sepolia testnet (chain ID 84532):

```ts
const JACKPOT_ADDRESS     = '0x465dA3c859f193A3807386387bEE941B2A4c3279' as const;
const LP_MANAGER_ADDRESS  = '0x36408921aB820305F109150003C0F90aE1CB1766' 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([
  // --- Jackpot write ---
  "function lpDeposit(uint256 _amountToDeposit)",

  // --- Jackpot errors ---
  "error DepositAmountZero()",
  "error LPDepositsNotInitialized()",
  "error EmergencyEnabled()",
  "error JackpotLocked()",

  // --- JackpotLPManager reads ---
  "function lpPoolCap() view returns (uint256)",
  "function getLPDrawingState(uint256 _drawingId) view returns ((uint256 lpPoolTotal, uint256 pendingDeposits, uint256 pendingWithdrawals))",
  "function getLpInfo(address _lpAddress) view returns ((uint256 consolidatedShares, (uint256 amount, uint256 drawingId) lastDeposit, (uint256 amountInShares, uint256 drawingId) pendingWithdrawal, uint256 claimableWithdrawals))",
  "function getLPValueBreakdown(address _lpAddress) view returns ((uint256 activeDeposits, uint256 pendingDeposits, uint256 pendingWithdrawals, uint256 claimableWithdrawals) breakdown)",

  // --- JackpotLPManager errors ---
  "error ExceedsPoolCap()",

  // --- JackpotLPManager events ---
  "event LpDeposited(address indexed lpAddress, uint256 indexed currentDrawingId, uint256 amount, uint256 totalPendingDeposits)",

  // --- Jackpot reads ---
  "function currentDrawingId() view returns (uint256)",

  // --- USDC ---
  "function balanceOf(address account) view returns (uint256)",
  "function allowance(address owner, address spender) view returns (uint256)",
  "function approve(address spender, uint256 amount) returns (bool)",
]);
```

## Recipe

### Setup

```ts
import {
  createPublicClient,
  createWalletClient,
  http,
  parseAbi,
} 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 JACKPOT_ADDRESS    = '0x3bAe643002069dBCbcd62B1A4eb4C4A397d042a2' as const;
const LP_MANAGER_ADDRESS = '0xE63E54DF82d894396B885CE498F828f2454d9dCf' as const;
const USDC_ADDRESS       = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' as const;

// 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 lpDeposit(uint256 _amountToDeposit)",
  "error DepositAmountZero()",
  "error LPDepositsNotInitialized()",
  "error EmergencyEnabled()",
  "error JackpotLocked()",
  "function lpPoolCap() view returns (uint256)",
  "function getLPDrawingState(uint256 _drawingId) view returns ((uint256 lpPoolTotal, uint256 pendingDeposits, uint256 pendingWithdrawals))",
  "function getLpInfo(address _lpAddress) view returns ((uint256 consolidatedShares, (uint256 amount, uint256 drawingId) lastDeposit, (uint256 amountInShares, uint256 drawingId) pendingWithdrawal, uint256 claimableWithdrawals))",
  "function getLPValueBreakdown(address _lpAddress) view returns ((uint256 activeDeposits, uint256 pendingDeposits, uint256 pendingWithdrawals, uint256 claimableWithdrawals) breakdown)",
  "error ExceedsPoolCap()",
  "event LpDeposited(address indexed lpAddress, uint256 indexed currentDrawingId, uint256 amount, uint256 totalPendingDeposits)",
  "function currentDrawingId() view returns (uint256)",
  "function balanceOf(address account) view returns (uint256)",
  "function allowance(address owner, address spender) view returns (uint256)",
  "function approve(address spender, uint256 amount) returns (bool)",
]);

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 pool capacity

```ts
const DEPOSIT_AMOUNT = 500_000_000n; // 500 USDC at 6 decimals

const drawingId = await publicClient.readContract({
  address: JACKPOT_ADDRESS,
  abi,
  functionName: 'currentDrawingId',
});

const [poolCap, drawingState] = await Promise.all([
  publicClient.readContract({
    address: LP_MANAGER_ADDRESS,
    abi,
    functionName: 'lpPoolCap',
  }),
  publicClient.readContract({
    address: LP_MANAGER_ADDRESS,
    abi,
    functionName: 'getLPDrawingState',
    args: [drawingId],
  }),
]);

// `lpPoolCap` constrains the *next* drawing pool, which equals `lpPoolTotal +
// pendingDeposits`. Both must be subtracted from the cap; using only
// `pendingDeposits` ignores the already-active pool and overstates capacity.
// Floor at 0n — once the effective total reaches cap, no further deposits fit.
const effectivePoolTotal = drawingState.lpPoolTotal + drawingState.pendingDeposits;
const remainingCapacity = effectivePoolTotal >= poolCap ? 0n : poolCap - effectivePoolTotal;

console.log('Pool cap:           ', poolCap);
console.log('Pool total (active):', drawingState.lpPoolTotal);
console.log('Pending deposits:   ', drawingState.pendingDeposits);
console.log('Remaining capacity: ', remainingCapacity);

if (remainingCapacity < DEPOSIT_AMOUNT) {
  throw new Error(
    `Insufficient pool capacity. Available: ${remainingCapacity}, requested: ${DEPOSIT_AMOUNT}`
  );
}
```

### Step 2 — Check USDC balance

```ts
const usdcBalance = await publicClient.readContract({
  address: USDC_ADDRESS,
  abi,
  functionName: 'balanceOf',
  args: [account.address],
});

console.log('USDC balance:', usdcBalance);

if (usdcBalance < DEPOSIT_AMOUNT) {
  throw new Error(
    `Insufficient USDC balance. Have: ${usdcBalance}, need: ${DEPOSIT_AMOUNT}`
  );
}
```

### Step 3 — Approve USDC for the Jackpot contract

```ts
// Approval target is JACKPOT_ADDRESS — lpDeposit pulls USDC through Jackpot, not LPManager
const currentAllowance = await publicClient.readContract({
  address: USDC_ADDRESS,
  abi,
  functionName: 'allowance',
  args: [account.address, JACKPOT_ADDRESS],
});

if (currentAllowance < DEPOSIT_AMOUNT) {
  const approveTx = await walletClient.writeContract({
    address: USDC_ADDRESS,
    abi,
    functionName: 'approve',
    args: [JACKPOT_ADDRESS, DEPOSIT_AMOUNT],
  });
  await publicClient.waitForTransactionReceipt({ hash: approveTx });
  console.log('USDC approved:', approveTx);
}
```

### Step 4 — Deposit 500 USDC

```ts
const depositTx = await walletClient.writeContract({
  address: JACKPOT_ADDRESS,
  abi,
  functionName: 'lpDeposit',
  args: [DEPOSIT_AMOUNT], // 500_000_000n — 500 USDC
});

const receipt = await publicClient.waitForTransactionReceipt({ hash: depositTx });
console.log('LP deposit submitted, tx:', depositTx);
```

### Step 5 — Check position (shares + USDC value)

```ts
// getLpInfo returns raw share/deposit data
const lpInfo = await publicClient.readContract({
  address: LP_MANAGER_ADDRESS,
  abi,
  functionName: 'getLpInfo',
  args: [account.address],
});

// getLPValueBreakdown returns USDC values — use this for display
const breakdown = await publicClient.readContract({
  address: LP_MANAGER_ADDRESS,
  abi,
  functionName: 'getLPValueBreakdown',
  args: [account.address],
});

console.log('LP Shares:            ', lpInfo.consolidatedShares);
console.log('Active deposits (USDC):', Number(breakdown.activeDeposits) / 1e6);
console.log('Pending deposits (USDC):', Number(breakdown.pendingDeposits) / 1e6);
console.log('Pending withdrawals:  ', Number(breakdown.pendingWithdrawals) / 1e6);
console.log('Claimable withdrawals:', Number(breakdown.claimableWithdrawals) / 1e6);

// lastDeposit.drawingId is the drawing in which the deposit was queued.
// It becomes active (earning yield) once that drawing settles and a new drawing begins.
```

## Parameters

| Parameter | Type | Description |
|---|---|---|
| `_amountToDeposit` | `uint256` | USDC amount in raw units (6 decimals). E.g. `500_000_000n` for 500 USDC. Must be > 0 and fit within remaining pool capacity. |

## Key Concepts

- **Pending deposits**: The deposit is queued under `lpInfo.lastDeposit` and does not earn yield until the current drawing settles.
- **Pool cap**: `lpPoolCap()` on `JackpotLPManager` is the hard upper limit on total LP liquidity. The cap constrains the *next-drawing* pool size, so remaining capacity is `lpPoolCap - (lpPoolTotal + pendingDeposits)` — both the active pool and queued deposits count. Depositing beyond that headroom reverts with `ExceedsPoolCap()`. `JackpotLPManager.getEstimatedNextDrawingLpPool()` is also available as a single read of the post-settlement pool total if you want to skip the arithmetic.
- **Approval target**: Always approve the **Jackpot** contract (`JACKPOT_ADDRESS`), not `JackpotLPManager`. The deposit flow goes through Jackpot, which calls LPManager internally.

## Common Errors

| Error | Cause |
|---|---|
| `DepositAmountZero()` | `_amountToDeposit` is `0` |
| `ExceedsPoolCap()` | Deposit would push total beyond `lpPoolCap` |
| `LPDepositsNotInitialized()` | The LP deposit system has not been initialized by the contract owner yet |
| `EmergencyEnabled()` | Contract is in emergency mode; deposits are halted |
| `JackpotLocked()` | Drawing is in the lock period immediately before a draw; try again after settlement |
| `SafeERC20FailedOperation` | USDC `approve` or `transferFrom` failed — check balance and allowance, and ensure approval targets Jackpot not LPManager |

## 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-contracts-reference` — full address table and complete ABI for all contracts
- `megapot-lp-withdraw` — initiate and finalize a withdrawal of LP shares
