Architecture
Current contract stack (v4, deployed)
┌──────────────────────┐
│ User wallet (SEI) │
└─────────┬────────────┘
│
│ buy() / sell()
▼
┌────────────────────────────┐
│ JellyPadToken │ ← curve phase
│ (one per launched memecoin)│
└─┬────────────┬────────────┬─┘
│ │ │
1% protocol │ 99% SEI │ │ ERC-20 mint
fee │ │ │
▼ ▼ ▼
┌─────────────┐ ┌──────────────┐ ┌────────────┐
│ Factory │ │ JellyPadStaker│ │ User wallet│
│ (splits │ │ (mints jpSEI, │ │ (gets MEME)│
│ 50/50) │ │ delegates, │ └────────────┘
└─┬───────────┘ │ buffers) │
│ └───────────────┘
50% to operator, 50% donateToBuffer
(via factory.receive())
At graduation (mcap × seiUsdPrice ≥ graduationMcapUsd):
┌──────────────────────────────────────────────┐
│ JellyPadToken._migrateToDex(): │
│ 1. take 1% graduation fee in jpSEI │
│ → factory │
│ 2. approve Saphyre router for the rest │
│ 3. addLiquidity → creates (jpSEI, TOKEN) │
│ 4. LP shares minted directly to 0xdEaD │
│ (mathematically unrecoverable) │
└──────────────────────────────────────────────┘
│
▼
┌────────────────────┐
│ Saphyre/DragonSwap │
│ (jpSEI, MEME) pool │ ← post-grad trading
│ permanent liquidity│
│ LP burned at 0xdEaD│
└────────────────────┘Phase 1: The bonding curve
Each token is its own contract (JellyPadToken). On buy():
- Take 1% protocol fee. Forward to factory's
receive(). - Stake the remaining 99% via
JellyPadStaker.stake(false). The staker routes to its buffer if below target, otherwise delegates to the active validator. Either way, the contract receives jpSEI back. - Compute tokens out from a Uniswap V2-style constant-product curve.
- Mint tokens to the buyer.
- Check graduation: if
realSeiReserves × seiUsdPrice ≥ graduationMcapUsd, fire_migrateToDex()in the same tx.
On sell(tokenAmount):
- Compute the curve's gross SEI output from the constant-product formula.
- Call
staker.instantUnstake(jpSeiAmount)for enough jpSEI to cover the gross. The redemption math sizes against the worst-case 4% tier so sells succeed even when the buffer is stressed; any positive dust stays in the contract as bonus reserves. - Take 1% protocol fee off the gross. Forward to factory
receive(). - Pay seller the remaining 99% in native SEI.
- Burn the tokens back into the curve (returned to the contract for resale).
The curve formula:
k = virtualSeiReserves × virtualTokenReserves (constant)
tokensOut = virtualTokenReserves - (k / (virtualSeiReserves + seiIn))Initial reserves: 30 SEI virtual, 800M tokens. The virtual depth makes the curve start at a fair price even with zero real liquidity.
Phase 2: Graduation
When realSeiReserves × seiUsdPrice crosses the per-token graduationMcapUsd threshold, _migrateToDex() runs in the same transaction as the buy that triggered it.
- Take 1% graduation fee in jpSEI off the contract's balance. Send to the factory address. (Fee is in jpSEI not native SEI to avoid paying the staker's instant-unstake fee at the migration step. Factory accumulates yield-bearing principal as protocol revenue, then converts to SEI via the 21-day slow-unstake path.)
- Approve the Saphyre router for the remaining 99% jpSEI plus all curve-side TOKEN.
- Call
router.addLiquidity(TOKEN, jpSEI, ..., to: 0xdEaD). Pair created if it doesn't already exist. The LP receipt is minted directly to0xdEaD. - Set
graduated = true. Subsequentbuy()/sell()on the curve revert. Trading happens on the Saphyre pair.
Phase 3: Post-graduation trading
The token is a clean ERC-20. The Saphyre pair (jpSEI, MEME) is its only liquidity. Users have three swap paths:
- JellyPadRouter (
buy(token,...)/sell(token,...)). The frontend default. Auto-stakes SEI to jpSEI on the buy side, auto-instantUnstakes on the sell side, applies the 1% protocol fee at each end. Most users go through this. - Saphyre directly. The pair contract is public. Anyone can swap against it via the standard V2 router.
- Aggregators. 1inch, Squid, etc. route into the Saphyre pair like any other V2 pool. The protocol fee is bypassed on these paths since they don't call our router.
┌──────────────────────┐
│ JellyPad frontend │
└─────────┬────────────┘
│ buy(token, minOut) payable
▼
┌──────────────────────┐
│ JellyPadRouter │
│ - 1% protocol fee │
│ - stakes SEI → jpSEI │
│ - swaps on Saphyre │
└─┬─────────────┬──────┘
│ │
▼ ▼
┌────────────┐ ┌─────────────┐
│ JellyPad- │ │ Saphyre pair│
│ Staker │ │ (jpSEI,MEME)│
└────────────┘ └─────────────┘Buys via the router auto-stake fresh SEI into jpSEI. Buys via Saphyre directly do not. A Uniswap V2 pool is a passive math contract; it doesn't call our token.
Fee routing
USER ACTION FEE ROUTING
────────────────────────────────────────────────────────────
factory.createToken() 0.01 SEI 100% → staker buffer
token.buy() 1% of msg.value factory.receive() →
50% operator / 50% buffer
token.sell() 1% of grossOut factory.receive() →
50% operator / 50% buffer
token._migrateToDex() 1% of jpSEI → factory address (held as
jpSEI; converted to native SEI
via 21-day slow-unstake to
treasury — buffer untouched)
router.buy() 1% of msg.value factory.receive() (same split)
router.sell() 1% of grossOut factory.receive() (same split)
staker.instantUnstake() 0.5–4% tiered 100% stays in buffer (lifts rate)The MAX_OPERATOR_FEE_BPS = 7000 constant in the factory caps the operator share at 70%. Owner cannot raise it above that even by mistake.
Why the token isn't fee-on-transfer
A common alternative is a transfer hook on the token itself: tax every transfer 1% and route to the factory. JellyPad deliberately doesn't do this because:
- Aggregators (1inch, Squid, etc.) blacklist fee-on-transfer ERC-20s
- DEXes show "honeypot" warnings on the pair, deterring buyers
- The token loses portability. Every wallet, lending app, and bridge has to special-case it
The router-only approach keeps the token a clean ERC-20.
Files at a glance
| File | Purpose |
|---|---|
contracts/src/JellyPadStaker.sol | In-house liquid staker (jpSEI). Validator delegation, dynamic buffer, tiered fees |
contracts/src/JellyPadToken.sol | The launched token (curve + graduation) |
contracts/src/JellyPadFactory.sol | Deploys tokens, collects creation fees, splits protocol fees 50/50 |
contracts/src/JellyPadRouter.sol | Post-graduation routing layer (one-tx user buys/sells) |
contracts/src/interfaces/IStaking.sol | Sei staking precompile ABI |
contracts/src/interfaces/IDistribution.sol | Sei distribution precompile ABI |
contracts/src/interfaces/IDragonSwapRouter.sol | Saphyre/DragonSwap V2 ABI |
contracts/test/JellyPadStaker.t.sol | 37 unit tests for staker logic |
contracts/test/StakerIntegration.t.sol | 6 end-to-end tests with the real staker |
contracts/test/JellyPadToken.t.sol | 19 tests covering token curve + graduation + LP burn |
contracts/script/sei | Bash CLI wrapper for deploy + interaction |