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):
| Contract | Address |
|---|
BagsFactory | 0x46aD6f53A3C26C8027826e2104cF0595b7b24D40 |
BagsLens | 0xcF8DA63Dd1cb58daDd2c1B350ac756ffA43EF2d4 |
BagsV4Hook | 0x208378dDc05eD5De1833624a30EB9C1d26f86EcC |
BagsVault | 0x26e421917aeA64B615A3127A2BA3AC3051C3ab80 |
| UniversalRouter (modified) | 0x8876789976dEcBfCbBbe364623C63652db8C0904 |
| V4Quoter | 0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94 |
| StateView | 0xF3334192D15450CdD385c8B70e03f9A6bD9E673b |
| PoolManager | 0x8366a39CC670B4001A1121B8F6A443A643e40951 |
| Permit2 | 0x000000000022D473030F116dDEE9F6B43aC78BA3 |
| WETH (aeWETH proxy) | 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 |
| Multicall3 | 0xcA11bde05977b3631167028862bE2a173976CA11 |
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:
| Parameter | Value |
|---|
fee | 0x800000 (dynamic fee flag) |
tickSpacing | 60 |
hooks | BagsV4Hook address |
| Pair | token / WETH, sorted by numeric address |
poolId = keccak256(abi.encode(currency0, currency1, fee, tickSpacing, hooks)). Prefer the on-chain poolId from TokenCreated or BagsLens.getTokenState.