Skip to main content
The preview functions live on the LaunchViewModule at 0xce83E3659251116d114Ec1CA729ffB49B99403c3. They are pure, free to call, and take local launch state as parameters. The pattern is: read launch state from the hook, pass it to the view module. After bonding, use the Uniswap V4 Quoter at 0x3972C00f7ed4885e145823eb7C655375d275A1C5 instead.

previewBuyLocal

function previewBuyLocal(
    uint128 saleSupply,
    uint96 targetRaise,
    uint32 gainBps,
    uint128 sold,
    uint128 remaining,
    uint256 ethIn
) external pure returns (
    uint256 tokensOut,
    uint256 cost,
    uint256 refund,
    uint256 tokensRemaining
);
Return fieldMeaning
tokensOutTokens you would receive at the current curve price
costETH actually consumed by the curve (may be less than ethIn if your buy would push past the bond target)
refundETH that would be refunded (ethIn - cost, or zero if the curve absorbs all of it)
tokensRemainingTokens left on the curve after the hypothetical buy
If refund is non zero, your buy would trigger the bond. Both the curve buy and the bond happen in the same transaction when you execute. The local params come from getLaunchState(launchId):
  • saleSupply = state.saleSupply
  • targetRaise = state.targetRaise
  • gainBps = state.gainBps
  • sold = state.sold
  • remaining = state.saleSupply - state.sold

previewSellLocal

function previewSellLocal(
    uint128 saleSupply,
    uint96 targetRaise,
    uint32 gainBps,
    uint128 sold,
    uint128 tokenAmount,
    uint128 netContributions,
    uint16 creatorFeeSplitBps,
    uint16 protocolFeeBps,
    uint16 variableFeeBps,
    uint16 bpsDenominator
) external pure returns (
    uint256 netPayout,
    uint256 protocolFee,
    uint256 creatorFee,
    uint256 buybackFee
);
Return fieldMeaning
netPayoutETH you would receive after fees
protocolFeeETH taken as the 1 percent protocol fee
creatorFeeETH credited to the creator from the variable fee
buybackFeeETH credited to the buyback module from the variable fee
netPayout + protocolFee + creatorFee + buybackFee equals the gross curve payout for tokenAmount. Local params come from getLaunchState(launchId) plus the protocol constants (PROTOCOL_FEE_BPS = 100, VARIABLE_FEE_BPS = 100, BPS_DENOMINATOR = 10000).

previewSaleSplit

function previewSaleSplit(uint96 targetRaise, uint32 gainBps)
    external view returns (
        uint128 saleSupply,
        uint128 liquiditySupply,
        uint16 salePortionBps,
        uint256 marginalPrice,
        uint256 poolPrice
    );
Use this before launch to see how the supply will be split between the bonding curve and the post bond V4 pool.
Return fieldMeaning
saleSupplyTokens sold through the curve
liquiditySupplyTokens paired with ETH in the V4 pool at bond
salePortionBpssaleSupply as bps of total supply
marginalPricePrice of the last token on the curve
poolPriceOpening price of the V4 pool
marginalPrice and poolPrice are equal by design. The split is chosen so the curve hands off to the pool without a price gap. previewSaleSplit is also callable on the hook (the hook delegates to the view module’s previewSaleSplit selector for this read).

Off chain reading

The simplest way to call these from JavaScript:
import { createPublicClient, http, parseEther } from "viem"
import { INKY_PUMP_HOOK_ABI, LAUNCH_VIEW_MODULE_ABI } from "./abi"

const HOOK = "0x4cC8F6d5B7cE150CCC0A9B7664532B1283b96AC4"
const VIEW = "0xce83E3659251116d114Ec1CA729ffB49B99403c3"

const client = createPublicClient({
  chain: { id: 57073, rpcUrls: { default: { http: ["https://rpc-gel.inkonchain.com"] } } },
  transport: http(),
})

const state = await client.readContract({
  address: HOOK,
  abi: INKY_PUMP_HOOK_ABI,
  functionName: "getLaunchState",
  args: [launchId],
})

const preview = await client.readContract({
  address: VIEW,
  abi: LAUNCH_VIEW_MODULE_ABI,
  functionName: "previewBuyLocal",
  args: [
    state.saleSupply,
    state.targetRaise,
    state.gainBps,
    state.sold,
    state.saleSupply - state.sold,
    parseEther("0.1"),
  ],
})
Using cast from Foundry:
# 1. Read state from the hook
cast call 0x4cC8F6d5B7cE150CCC0A9B7664532B1283b96AC4 \
  "getLaunchState(uint256)" $LAUNCH_ID \
  --rpc-url https://rpc-gel.inkonchain.com

# 2. Pass the unpacked state to the view module's previewBuyLocal
cast call 0xce83E3659251116d114Ec1CA729ffB49B99403c3 \
  "previewBuyLocal(uint128,uint96,uint32,uint128,uint128,uint256)(uint256,uint256,uint256,uint256)" \
  $SALE_SUPPLY $TARGET_RAISE $GAIN_BPS $SOLD $REMAINING $ETH_IN_WEI \
  --rpc-url https://rpc-gel.inkonchain.com

Post bond quotes

After a token bonds, the preview functions on the view module no longer reflect tradable price. Use the Uniswap V4 Quoter instead:
// Uniswap V4 Quoter at 0x3972C00f7ed4885e145823eb7C655375d275A1C5
function quoteExactInputSingle(QuoteExactSingleParams memory params)
    external returns (uint256 amountOut, uint256 gasEstimate);
The V4 Quoter is non view (it uses revert-data for the answer), so it has to be simulated through eth_call rather than called directly. Most viem and ethers clients handle this transparently.