Skip to main content
This page is the reference for the Bags contracts on Robinhood Chain. For step-by-step usage, see the Launch, Trade, Read State, and Claim Fees guides.

Addresses

Protocol singletons and shared infrastructure on Robinhood Chain mainnet (chain ID 4663):
ContractAddress
BagsFactory0x46aD6f53A3C26C8027826e2104cF0595b7b24D40
BagsLens0xcF8DA63Dd1cb58daDd2c1B350ac756ffA43EF2d4
BagsV4Hook0x208378dDc05eD5De1833624a30EB9C1d26f86EcC
BagsVault0x26e421917aeA64B615A3127A2BA3AC3051C3ab80
UniversalRouter (modified)0x8876789976dEcBfCbBbe364623C63652db8C0904
V4Quoter0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94
StateView0xF3334192D15450CdD385c8B70e03f9A6bD9E673b
PoolManager0x8366a39CC670B4001A1121B8F6A443A643e40951
Permit20x000000000022D473030F116dDEE9F6B43aC78BA3
WETH (aeWETH proxy)0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73
Multicall30xcA11bde05977b3631167028862bE2a173976CA11
BagsToken, BagsBondingCurve, and BagsFeeShare are per-token EIP-1167 clones — resolve them via the TokenCreated event, factory.curveForToken / factory.feeShareForToken, or BagsLens.getTokenState.

ABI Downloads

The full ABIs (including custom error definitions used for revert decoding) are bundled with these docs and mirror the robinhood-abi directory of the public bagsfm/bags-idl repository:
Import the full ABIs so your EVM library can decode custom errors (e.g. BagsBondingCurve_SlippageExceeded) into readable messages instead of raw revert data.

BagsFactory

Launch entry point and on-chain registry.

Functions

// Launch (payable)
function create(string name, string symbol, string metadataURI, address partner, uint16 partnerBps, address[] claimers, uint16[] bps) payable returns (address token, address curve);
function createAndBuy(string name, string symbol, string metadataURI, address partner, uint16 partnerBps, address[] claimers, uint16[] bps) payable returns (address token, address curve);

// Registry / config (view)
function creationFee() returns (uint256);
function graduationThreshold() returns (uint256);
function curveForToken(address token) returns (address);
function feeShareForToken(address token) returns (address);
function tokenForPoolId(bytes32 poolId) returns (address);
function getTokens(uint256 offset, uint256 limit) returns (address[]);
function allTokens(uint256 index) returns (address);
function allTokensLength() returns (uint256);

Events

event TokenCreated(address indexed token, address indexed curve, address indexed creator, address feeShare, bytes32 poolId, string name, string symbol, string metadataURI);
event CreationFeeUpdated(uint256 newFee);
event GraduationThresholdUpdated(uint256 oldThreshold, uint256 newThreshold);

Key errors

BagsFactory_InsufficientCreationFee(required, sent), BagsFactory_InvalidClaimers, BagsFactory_NoClaimers, BagsFactory_InvalidPartnerBps(partnerBps), BagsFactory_NoBuyValue, BagsFactory_BuyFailed(curve, value), BagsFactory_RefundFailed(to, amount).

BagsBondingCurve

Per-token pre-migration AMM (virtual x * y = k). Resolve its address per token.

Functions

// Trade
function buy(uint256 minTokensOut) payable;
function buyFor(address recipient, uint256 minTokensOut) payable;
function sell(uint256 tokensIn, uint256 minQuoteOut);
function sellFor(address recipient, uint256 tokensIn, uint256 minQuoteOut);
function migrate(); // manual migration if the threshold is already met

// Quotes (view)
function quoteBuy(uint256 quoteIn) returns (uint256 tokensOut, uint256 feeQuote, uint256 netQuoteIn, uint256 grossUsed, uint256 refundQuote);
function quoteSell(uint256 tokensIn) returns (uint256 quoteToSeller, uint256 feeQuote, uint256 grossQuoteOut);

// State (view)
function migrated() returns (bool);
function paused() returns (bool);
function currentPrice() returns (uint256);        // ETH wei per whole token
function bondingProgress() returns (uint256);      // 0-100
function thresholdQuote() returns (uint256);
function realQuoteReserves() returns (uint256);
function realTokenReserves() returns (uint256);
function getVirtualReserves() returns (uint256 vToken, uint256 vQuote);
function creator() returns (address);
function TX_FEE_BPS() returns (uint256);           // 200 (2%)

Events

event TokensBought(address indexed buyer, address indexed recipient, uint256 grossQuoteIn, uint256 netQuoteIn, uint256 tokensOut, uint256 feeQuote, uint256 vaultFeeQuote, uint256 creatorFeeWETH, uint256 refundQuote, uint256 price, uint256 virtualTokenReserves, uint256 virtualQuoteReserves);
event TokensSold(address indexed seller, address indexed recipient, uint256 tokensIn, uint256 grossQuoteOut, uint256 netQuoteToRecipient, uint256 feeQuote, uint256 vaultFeeQuote, uint256 creatorFeeWETH, uint256 price, uint256 virtualTokenReserves, uint256 virtualQuoteReserves);
event Migrated(address indexed creator, address indexed platformAdmin, address indexed token, uint256 lpQuote, uint256 lpTokens, bytes32 poolId, uint160 sqrtPriceX96);
event FeesSplit(address indexed payer, address indexed vault, address indexed feeShare, uint256 vaultFeeQuote, uint256 creatorFeeWETH);

Key errors

BagsBondingCurve_SlippageExceeded(minExpected, actualOut), BagsBondingCurve_AlreadyMigrated, BagsBondingCurve_NotInitialized, BagsBondingCurve_ThresholdNotReached(have, need), BagsBondingCurve_NoQuoteSent, BagsBondingCurve_ZeroInputAmount, EnforcedPause.

BagsFeeShare

Per-token creator-fee accounting (accrues in WETH). Resolve its address per token.

Functions

function claim(bool unwrap);                        // unwrap = true pays native ETH
function claimable(address user) returns (uint256);
function getClaimers() returns (address[] addrs, uint16[] bps);
function claimerBps(address user) returns (uint16);
function PARTNER() returns (address);
function PARTNER_BPS() returns (uint16);
function poolId() returns (bytes32);
function hook() returns (address);
function bondingCurve() returns (address);

Events

event Claimed(address indexed user, uint256 amount, bool unwrap);
event FeeNotified(uint256 amount, uint256 partnerShare, uint256 claimerPot);
event ClaimersUpdated(address[] claimers, uint16[] bps);

Key errors

BagsFeeShare_NothingToClaim, BagsFeeShare_NotAuthorized(caller), BagsFeeShare_BpsSumInvalid(sum), BagsFeeShare_DuplicateClaimer(claimer), BagsFeeShare_TooManyClaimers(length, max).

BagsLens

Stateless read aggregator. Preferred entry point for reads.

Functions

function getTokenState(address token) returns (TokenState);
function getTokenStates(address[] tokens) returns (TokenState[]);
function claimableOf(address token, address user) returns (uint256);
function FACTORY() returns (address);

TokenState struct

struct TokenState {
    bool exists;
    bool migrated;
    address curve;
    address feeShare;
    bytes32 poolId;
    uint256 thresholdQuote;
    uint256 realQuoteReserves;
    uint256 realTokenReserves;
    uint256 virtualTokenReserves;
    uint256 virtualQuoteReserves;
    uint256 priceQuotePerToken; // freezes at migration
    uint256 bondingProgressPct; // 0-99 bonding; 100 migrated
    uint256 totalRaised;
}

BagsToken

Per-token ERC-20 with a fixed 1e9 supply (18 decimals). Standard ERC-20 surface (name, symbol, decimals, totalSupply, balanceOf, approve, allowance, transfer, transferFrom) plus:
function metadataURI() returns (string); // reverts on non-Bags ERC-20s

BagsV4Hook

Singleton Uniswap v4 hook shared by all Bags pools. It takes the 2% fee on the WETH leg of post-migration swaps, locks liquidity, and routes creator fees to each token’s fee-share.

Functions

function pools(bytes32 poolId) returns (address bondingCurve, address feeShare, uint128 pendingFees, bool minted);
function sweep(bytes32 poolId);               // flush pending fees to vault + fee-share (permissionless)
function register(bytes32 poolId, address bondingCurve, address feeShare); // factory-only
function factory() returns (address);

Events

event HookFeeTaken(bytes32 indexed poolId, uint256 amount);
event FeesSwept(bytes32 indexed poolId, uint256 bagsShare, uint256 creatorShare);
event PoolRegistered(bytes32 indexed poolId, address indexed bondingCurve, address indexed feeShare);
event PoolMinted(bytes32 indexed poolId, address indexed currency0, address indexed currency1);

Key errors

BagsV4Hook_ExactOutputWETHSpecifiedUnsupported (exact-out WETH is rejected by design), BagsV4Hook_LiquidityLocked, BagsV4Hook_PoolNotRegistered(poolId), BagsV4Hook_PoolMissingWETH.

BagsVault

Platform treasury holding native ETH (the platform 1% of trade fees and the launch fee). Owner-controlled withdrawals; no integrator-facing calls.
function balance() returns (uint256 nativeBalance);

Periphery ABIs

The Uniswap-style infrastructure is not part of the Bags ABI export. These are the minimal fragments used by the Trade Tokens and Read State guides.

UniversalRouter (modified fork)

Only execute is called directly. The v4 swap struct carries an extra uint256 minHopPriceX36 field vs vanilla Uniswap (set it to 0), so encode the calldata manually.
function execute(bytes commands, bytes[] inputs, uint256 deadline) payable;
The v4 swap params tuple (encoded manually for SWAP_EXACT_IN_SINGLE):
struct SwapExactInSingle {
    PoolKey poolKey;        // (currency0, currency1, fee, tickSpacing, hooks)
    bool zeroForOne;
    uint128 amountIn;
    uint128 amountOutMinimum;
    uint256 minHopPriceX36; // Robinhood-only field — always 0
    bytes hookData;         // "0x"
}
Command / action bytes: command V4_SWAP = 0x10; actions SWAP_EXACT_IN_SINGLE = 0x06, SETTLE_ALL = 0x0c, TAKE_ALL = 0x0f.

Permit2

function approve(address token, address spender, uint160 amount, uint48 expiration);
function allowance(address owner, address token, address spender) returns (uint160 amount, uint48 expiration, uint48 nonce);

V4Quoter (call via eth_call / simulate, not on-chain)

function quoteExactInputSingle((PoolKey poolKey, bool zeroForOne, uint128 exactAmount, bytes hookData) params) returns (uint256 amountOut, uint256 gasEstimate);
quoteExactInputSingle is nonpayable, not view — it must be simulated via eth_call (viem’s simulateContract), never called as a plain read. The Trade Tokens guide does this. Output already includes the 2% hook fee — apply slippage only.

StateView

function getSlot0(bytes32 poolId) returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee);
function getLiquidity(bytes32 poolId) returns (uint128 liquidity);

WETH (aeWETH proxy)

WETH9-compatible interface. Never rely on its bytecode/codehash — it’s an upgradeable proxy.
function deposit() payable;
function withdraw(uint256 amount);
function approve(address spender, uint256 amount) returns (bool);
function balanceOf(address account) returns (uint256);

Pool key parameters

Bags pools use these exact values — they must match the factory or derived pool IDs will be wrong:
ParameterValue
fee0x800000 (dynamic fee flag)
tickSpacing60
hooksBagsV4Hook address
Pairtoken / WETH, sorted by numeric address
poolId = keccak256(abi.encode(currency0, currency1, fee, tickSpacing, hooks)). Prefer the on-chain poolId from TokenCreated or BagsLens.getTokenState.