10Reference参照
Contracts
The launchpad runs on Injective EVM, chain ID 1776 — the same chain as injective-1, seen from its EVM side. Deployed on 2026-09-23 from block 184234133, every contract verified on Blockscout. Any other address presented as one of these is not.
The owner and the treasury are, for now, the deploying wallet 0x5f1A0A240136cc0CD5C48A6EDb7d185C27f37713. Not audited.
| contract | what it does | address |
|---|---|---|
PairLaunchpad | the one-transaction launch; mints bank-module coins (since 2026-09-29, block 185077101) | 0xa2e83d7a2519E808ef3B3551CA1f1aB0d82b6537 |
PairLaunchpad (first) | launched the first coins as plain ERC-20s; retired, its coins trade as before | 0x139dFBB6927C64d0D13D98265aBAD81013Fdfdb6 |
FeeVault | owns every launch's position, splits and pays the fees | 0xAAaDCdb58d1025656b26020Fd241a5Cdf430F488 |
QuoteRegistry | decides whether a pair asset is eligible, with the two bars and the owner's list | 0x583f3c105e35e37429d758df930D2Bb1dA3a7b6C |
CompositeQuoteGate | asks every measuring gate and keeps the best answer | 0xafc9926a5bbB22D9B15C0F5af371aa0D3A1d1AF1 |
InfinityQuoteGate | measures depth in Infinity CL pools | 0x61D79aAA0cd868294ca2c86e9001b67AcfC48777 |
PairZap | buys and sells a coin with INJ in one transaction | 0x3313a370b3a84d2752DC1B355eF5d09D69108252 |
CctpInjReceiver | lands bridged USDC as native INJ: completes Circle's transfer, swaps, pays the recipient — see Bridge | 0x47B29B45d6C3085Cf4cb78e2B9C520C421cDc32F |
$DOJO | the protocol token, a BankPairToken launched here — see $DOJO | 0xe5970650A11F1bD3D713C55500111F5Fe090826C |
PairBuyback | buys $DOJO back with the protocol's share and burns it | written and tested, not deployed yet |
The bridge's relayer, which pays for arrivals on Injective and receives the INJ landing's 1% fee, is
0x8Dd67071BFBa3100Cf23D7908A581b67732A869c.
Circle's CCTP v2 contracts are the same on every chain: TokenMessengerV2
0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d and MessageTransmitterV2
0x81D40F21F12A8F0E3252Bccb954D722d4c464B64.
Buying with INJ: PairZap
A coin here trades against another coin, so someone holding only INJ has two trades to make. PairZap
makes them as one transaction: an aggregator's route between INJ and the pair asset (LI.FI's router on
Injective, fixed at deployment), then the coin's own Infinity pool. A coin paired with wINJ needs no
route at all — the INJ is wrapped. You sign a single minimum that bounds both legs; if either falls
short the whole transaction reverts and you keep what you had.
It has no owner and no settings, holds nothing between trades, and keeps no allowance standing. It is a convenience, not a gate: the pool is an ordinary Infinity pool, and anything that can trade one can trade your coin without it. It has not been audited.
Your coin's own contract
Every coin launched here is a BankPairToken, and every one of them will show as verified without
anyone submitting it. That is not a courtesy — it takes no constructor arguments (it calls back into
the launchpad for its name, symbol and supply), so the creation bytecode is byte-identical every time.
Verifying the first coin lets the explorer match every other one, including coins that do not exist yet.
Its balances live in Injective's bank module, following the MultiVM Token Standard: the contract is
the ERC-20 face of the denom erc20:<its address>. So the coin is one asset on both sides of Injective
at once, with no bridge and no wrapped copy — it trades in its Infinity pool on the EVM side, and shows
in Keplr, Leap and the Injective Hub, and moves over IBC, on the Cosmos side.
What that source says, and what it therefore cannot do: the whole supply is minted once, in the launch's
own transaction, by a one-shot initialize only the launchpad can call (Injective's bank precompile
refuses a contract still under construction, so this cannot sit in the constructor). After that,
nothing calls mint or burn: no transfer tax, no blacklist, no pause, no owner. Name, symbol and
decimals are read back from the bank module's metadata for the denom.
The first launchpad's coins are plain PairTokens, with the same promises and balances kept in the
contract itself.
External contracts it uses
Every one of these was read off chain 1776 on 22 September 2026 before it was written down — Choice's
Infinity contracts by their own views and code size, the tokens by symbol and decimals, API3's
proxies by latestRoundData.
| Infinity Vault (Choice Exchange v2) — holds every pool's tokens | 0xB67dd13b30ed21310be170968301eF83827B1Cad |
| Infinity CLPoolManager (launch venue — every launch's pool lives inside it) | 0x6A4085Bb379e5213Df84Dc2dD52562559602b029 |
| Infinity CLQuoter (prices the trade panel; simulated, never sent) | 0x13241d5d4FED3ee7eD8E4f1aB74c14544A789d65 |
| wINJ | 0x0000000088827d2d103ee2d9A6b781773AE03FfB |
| USDT (6 decimals) | 0x88f7F2b685F9692caf8c478f5BADF09eE9B1Cc13 |
| USDC (6 decimals) | 0xa00C59fF5a080D2b954d0c75e46E22a0c371235a |
| wETH (18 decimals) | 0x83A15000b753AC0EeE06D2Cb41a69e76D0D5c7F7 |
| API3 INJ/USD reader proxy (18 decimals) | 0xF1d44fc716666EB3abafa67C32adA9EF0ABf9bDb |
| API3 ETH/USD reader proxy (18 decimals) | 0x3fA4257F42A8578D318783A7A6fa119979A39727 |
LI.FI diamond (the only address PairZap sends route calldata to) | 0xeCeC3970Ca674278DA8D9B1c484ACaF6B20181F5 |
| Multicall3 | 0xcA11bde05977b3631167028862bE2a173976CA11 |
wINJ, USDT, USDC and wETH are bank-module tokens: their balances live in Injective's bank module and the ERC-20 contract reaches them through a precompile. On chain they behave as ordinary ERC-20s. The one consequence worth knowing is that no local test chain can run them, which is why the test suite uses mocks for the tokens while running the real Infinity contracts.
Calls worth knowing
Before launching
// Non-reverting. Returns whether it would be allowed, and why not if not.
registry.status(address quote)
returns (bool eligible, Decision decision, Report report)
// The bar this particular asset has to clear — $2,000 if listed, $5,000 if not.
registry.requiredDepthUsdE8(address quote) returns (uint256)
// Make a pool count as evidence for the coin on its non-anchor side. Anyone can call.
clGate.registerPool(PoolKey key)
clGate.registerLaunch(address token) // the pool a launch here opened
clGate.probe(PoolKey key) returns (uint256 usdE8, address anchor) // one live reading, no state
Launching
launchpad.launch(LaunchConfig cfg) payable returns (address token, bytes32 poolId)
launchpad.predictToken(address creator, bytes32 salt) returns (address)
launchpad.launchFee() returns (uint256)
LaunchConfig carries, beyond the obvious:
| field | what it does |
|---|---|
lpFee / tickSpacing | the pool's fee, in hundredths of a bip, and its tick spacing. Infinity has no fee tiers: any fee inside minLpFee..maxLpFee (never above 10%) with any spacing from 1 to 1000, and both ticks multiples of it |
creatorBps | share of supply kept back for you, capped at 20% |
feeRoute | 0 keeps your fees, 1 buys the coin back and burns it, 2 pays your holders |
feeRecipient | zero means the launching wallet |
devBuyQuote | pair-asset amount spent buying your own coin as the pool's first trade; needs an approval to the launchpad first |
devBuyMinOut | least you will accept from that buy — nobody can front-run it, so this guards against you and the pool disagreeing on the opening price |
The pool's key is Infinity's: (currency0, currency1, hooks, poolManager, fee, parameters), with the
hook at zero, the pool manager Choice's, and the tick spacing packed into parameters. Its id is the
keccak256 of that key, ABI-encoded.
After launching
// Anyone can call. Proceeds only ever reach the recorded recipient, the sink and the treasury.
feeVault.collect(address token)
// Creator only. Both take effect from the next collect.
feeVault.setFeeRoute(address token, FeeRoute route)
feeVault.setFeeRecipient(address token, address recipient)
// Reads
launchpad.launchOf(address token) // a public mapping: an unnamed tuple
feeVault.launchOf(address token) returns (Launch) // includes the pool's full PoolKey
feeVault.positionOf(address token) returns (uint128 liquidity) // an Infinity position keeps no tokensOwed
feeVault.feeRouteOf(address token) returns (FeeRoute)
feeVault.feeRecipientOf(address token) returns (address)
feeVault.owed(address token, address who) returns (uint256) // a payout that could not be pushed
feeVault.claim(address token) // collect one
Where the liquidity lock actually lives
There is no lock contract and no locked LP token, because Infinity has no LP tokens at all. A position
only becomes an NFT when the CLPositionManager wraps it; underneath it is a slot in the
CLPoolManager keyed by (owner, tickLower, tickUpper, salt), and the fee vault seeded that slot
directly. The usual "liquidity locked" detectors look for LP tokens or position NFTs sent to a burn
address or a locker, and here there is nothing of the sort for them to find.
What holds instead is a property of FeeVault, and with its source published you can check it
rather than believe it: no code path in the vault ever passes a negative liquidityDelta.
Collecting fees calls modifyLiquidity with a delta of exactly zero, which credits the fees earned
so far and touches nothing else. There is no withdraw, no emergency exit, and no owner function that
adds one. Anyone can read the position with feeVault.positionOf(token), or straight off the pool
manager with CLPoolManager.getLiquidity(poolId, feeVault, tickLower, tickUpper, 0). The float
cannot come back out — not by the creator, not by us.
Owner powers
The owner can retune the depth bars, the fee bounds, the launch fee, the treasury, the buyback sink, the curated list, the gate, its sampling and the hooks it accepts. It cannot touch a launch's liquidity, change an existing launch's creator share, or redirect a creator's fees.
Ownership transfer is two-step everywhere: a handover that is never accepted leaves the current owner in place rather than sending the protocol to a wrong address.
Choice Exchange owns the Infinity contracts themselves, behind its own timelock. It cannot move a position the fee vault holds, but it sets its pool manager's protocol fee, which is zero for hookless pools today.
The owner should be a multisig behind a timelock, and the contracts do not enforce that themselves.
None of this has been audited.

