Integrating with DollarPad

For third parties — trading bots, aggregators, DEX screeners, Telegram/Discord bots — adding support for tokens launched on DollarPad. This is a bonding-curve launchpad on Stable mainnet (chain id 988), not a standard AMM/DEX. Generic DEX-integration code will not work here without the specifics below.

Contract addresses

DollarPad (production)0x94F7A88d8650A727b2a6667E631E3C37a827d383
Uniswap V2 Router (Stable canonical)0xa571dc7c4f2369F1cA24D3a7E8a35c07Ff52bfC0
Uniswap V2 Factory (Stable canonical)0x25D2d657F539F2bB16eC82773cBE5ee49ddD3c69
USDT0 (ERC-20 interface of native gas)0x779Ded0c9e1022225f8E0630b35a9b54bE713736
Multicall30xcA11bde05977b3631167028862bE2a173976CA11

RPC: https://rpc.stable.xyz · Explorer: https://stablescan.xyz · Full ABI in web/lib/abi.ts of the repo, or read directly from the verified contract on StableScan.

⚠️ The one thing that will break your integration if you skip it

Stable’s native gas token is USDT0, with 18 decimals — not ETH. Every price, every buy/sell value, and every quoted amount in DollarPad is denominated in native currency (18 decimals), sent as msg.value — exactly like ETH on any other EVM chain, just worth $1 per unit. There is a separate ERC-20 interface to the same balance at 6 decimals (0x779Ded0c9e1022225f8E0630b35a9b54bE713736), used only internally at graduation. Don’t confuse the two.

Also: the router’s registered WETH() address is a revert-all placeholder on this chain. Never call swapExactETHForTokens or similar *ETH router functions expecting WETH-like behavior — it will revert.

Core mechanics

  • Every token is fixed-supply (1,000,000,000), no mint, no tax, no blacklist.
  • Pre-graduation: the token contract reverts on any transfer that isn’t to/from DollarPad. A token is not tradeable anywhere else until it graduates — check getTokenState(token).graduated before attempting any swap-based trade.
  • Post-graduation: transfers are unrestricted and the token trades on the Uniswap V2 pair created automatically at graduation (LP burned to 0x…dEaD). Standard Uniswap V2 integration works fine from this point on.
  • Pricing follows a constant-product curve over virtual reserves — always use quoteBuy/quoteSell, don’t compute prices from balanceOf yourself.

Current production launch parameters

Each token freezes the params version live when it was created — call curves(token).paramsId paramsHistory(paramsId) for the exact params a specific token launched with.

Creation fee1 USDT
Graduation fee200 USDT (deducted from the raise)
Starting virtual USDT reserve3,500 USDT
Starting virtual token reserve1,080,000,000
Curve supply (sellable)800,000,000
LP supply (reserved for graduation)200,000,000
Trade fee1% (0.5% creator / 0.5% protocol)
Anti-snipe cap2% of supply per wallet
Anti-snipe window100 blocks (~70s at 0.7s/block)

Approximate full-curve raise: ~$10,000 net before graduation.

⚠️ Anti-snipe window — read before building a sniper bot

For the first 100 blocks after a token’s creation, buy() enforces a per-wallet cap of 2% of supply. Any buy pushing a wallet over that cap reverts — including from a bot. This is intentional anti-rug protection. Either size buys to respect the cap during the window (check snipeWindowBought(token, wallet) and createdBlock), or only target tokens where block.number > createdBlock + 100.

Key read functions

function getTokenState(address token) external view returns (TokenState memory);
function getTokenStates(uint256 offset, uint256 limit) external view returns (TokenState[] memory);

Returns graduated, vUsdt/vToken (virtual reserves), priceUsdt18, marketCapUsdt, raisedUsdt, progressBps, plus name/symbol/metadataURI — everything in one call.

function quoteBuy(address token, uint256 usdtIn)
    external view returns (uint256 tokensOut, uint256 usdtUsed, bool wouldGraduate);

usdtIn is gross native USDT (18 decimals). If the buy would exhaust the curve, usdtUsed will be less than usdtIn (the rest refunds on-chain) and wouldGraduate is true — size msg.value off usdtUsed, not your original amount.

function quoteSell(address token, uint256 tokenAmount) external view returns (uint256 usdtOut);

Net payout in native USDT (18 decimals) after the 1% fee.

Key write functions

function create(string name, string symbol, string metadataURI, uint256 minTokensOut)
    external payable returns (address token);

msg.value must be ≥ the current creation fee; any excess is spent as an immediate dev-buy in the same transaction.

function buy(address token, uint256 minTokensOut, uint256 deadline, address referrer) external payable;
function sell(address token, uint256 tokenAmount, uint256 minUsdtOut, uint256 deadline, address referrer) external;

Standard slippage and deadline (unix seconds) protection. referrer is optional (pass address(0) for none) — referrers earn 10% of the protocol fee slice, pulled via claimReferralFees(). sell requires a prior approve(STABLEPAD_ADDRESS, tokenAmount).

Events to watch

event TokenCreated(address indexed token, address indexed creator, string name, string symbol, string metadataURI, uint32 paramsId);
event Trade(address indexed token, address indexed trader, bool isBuy, uint256 usdtAmount, uint256 tokenAmount, uint128 vUsdt, uint128 vToken);
event Graduated(address indexed token, address indexed pair, uint256 usdt6ToLp, uint256 tokensToLp);

Trade includes the post-trade virtual reserves directly — a full price chart can be built purely from these logs, no indexer or extra state reads needed (exactly what DollarPad’s own frontend does).

Graduated fires in the same transaction as the completing Trade — watch for it to know the moment a token switches from buy/sell to normal Uniswap V2 swaps (which will revert with AlreadyGraduated afterward).

Minimal integration flow for a bot

  1. Watch TokenCreated (or poll getTokenStates) to discover new tokens.
  2. Before a “snipe,” check graduated == false and whether the anti-snipe window is still active for that token.
  3. Call quoteBuy(token, intendedUsdtIn) for expected tokensOut; apply your slippage tolerance for minTokensOut.
  4. Send buy(token, minTokensOut, deadline, referrer) with value: usdtUsed (native, 18 decimals).
  5. Watch for Graduated — once fired, switch to normal Uniswap V2 swap logic against the pair from the event (or factory.getPair(token, USDT0)).

Questions about this integration guide can be directed to the DollarPad team.