Skip to content

Commit 72638a1

Browse files
frontier-fun: v1.2 factory, locked seed liquidity, staking (#20744)
Co-authored-by: godcomplex44 <314077567+godcomplex44@users.noreply.github.com> Co-authored-by: RohanNero <100052099+RohanNero@users.noreply.github.com>
1 parent cd1604c commit 72638a1

1 file changed

Lines changed: 79 additions & 12 deletions

File tree

projects/frontier-fun/index.js

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,92 @@
11
const ADDRESSES = require('../helper/coreAssets.json')
22
const { getLogs2 } = require('../helper/cache/getLogs')
3+
const { sumTokens2 } = require('../helper/unwrapLPs')
34

4-
// Frontier (frontier.fun) — bonding-curve token launchpad on Robinhood Chain (4663).
5-
// Each launched token custodies the native ETH its own curve raises, so TVL is the
6-
// ETH sitting in un-graduated token contracts. When a curve fills, the token pays
7-
// the creator fee and seeds a Uniswap V4 pool in the same transaction, leaving its
8-
// own balance at zero — graduated markets therefore drop out on their own, and
9-
// their liquidity is already counted by the uniswap-v4 adapter on this chain.
10-
const FACTORY = '0x3cbC9395046607C083B383DC3588A3e8308dFf54'
11-
const FROM_BLOCK = 23650298 // block of the first CoinDeployed event
5+
// Frontier (frontier.fun) — token launchpad on Robinhood Chain (4663), two deployments.
6+
//
7+
// tvl:
8+
// - Curve ETH. Each un-graduated token custodies the native ETH its own curve raises
9+
// (verified: reserveBalance - VIRTUAL_BALANCE equals the token's ETH balance to the
10+
// wei). When the curve fills, the token pays the creator fee and seeds a Uniswap V4
11+
// pool in the same transaction, leaving its balance at zero. v1.2 direct-seed
12+
// launches skip the curve and never hold ETH.
13+
// - Locked seed liquidity (v1.2). Every pool's seed position NFT is minted straight to
14+
// the Harvester, which can only collect fees from it — the liquidity is locked for
15+
// good. Counted as the ETH leg of those positions; the coin leg is the launched
16+
// token's own unsold supply and is not counted. This liquidity is also in the
17+
// uniswap-v4 adapter's TVL on this chain, hence `doublecounted`.
18+
//
19+
// Frontier's ERC-4626 StakingVaults are excluded as the staked assets are launched tokens
20+
const V1_FACTORY = '0x3cbC9395046607C083B383DC3588A3e8308dFf54'
21+
const V1_FROM_BLOCK = 23650298 // first v1 CoinDeployed
22+
const V12_FACTORY = '0xe3A826C056e578c240D362BF4C2fa53E5c0c17a5'
23+
const V12_FROM_BLOCK = 36671438 // v1.2 deploy block
24+
const HARVESTER = '0x2F33cb57fAa8bF1EB52ea18D90B0dc2f8cc2Db1f'
25+
const POSITION_MANAGER = '0x58daec3116aae6d93017baaea7749052e8a04fa7' // Uniswap V4 posm
1226

13-
const COIN_DEPLOYED_EVENT = 'event CoinDeployed(address indexed creator, address indexed token, address factory, address lp, string name, string symbol, string description, string image, uint256 initialSupply, uint256 maxSupply, uint256 initialETHReserves, uint256 initialPrice, uint256 initialMarketCap, uint256 targetETH)'
27+
const V1_COIN_DEPLOYED_EVENT = 'event CoinDeployed(address indexed creator, address indexed token, address factory, address lp, string name, string symbol, string description, string image, uint256 initialSupply, uint256 maxSupply, uint256 initialETHReserves, uint256 initialPrice, uint256 initialMarketCap, uint256 targetETH)'
28+
const V12_COIN_DEPLOYED_EVENT = 'event CoinDeployed(address indexed creator, address indexed token, address factory, address lp, string name, string symbol, string description, string image, uint256 initialSupply, uint256 maxSupply, uint256 initialETHReserves, uint256 initialPrice, uint256 initialMarketCap, uint256 targetETH, bool indexed directSeed)'
29+
const NFT_TRANSFER_EVENT = 'event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)'
30+
const NFT_TRANSFER_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
31+
const asTopic = (address) => '0x' + address.slice(2).toLowerCase().padStart(64, '0')
1432

33+
/**
34+
* Native ETH custodied by un-graduated bonding-curve tokens (v1 + v1.2
35+
* factories, enumerated from CoinDeployed; direct-seed launches never hold
36+
* ETH), plus the ETH leg of the permanently locked Uniswap V4 seed positions
37+
* held by the Harvester. The coin leg of those positions is the launched
38+
* token's own unsold supply and is not counted.
39+
* @param {object} api - DefiLlama chain api for the block being measured
40+
*/
1541
async function tvl(api) {
16-
const logs = await getLogs2({ api, factory: FACTORY, eventAbi: COIN_DEPLOYED_EVENT, fromBlock: FROM_BLOCK })
17-
return api.sumTokens({ tokensAndOwners: logs.map(log => [ADDRESSES.null, log.token]) })
42+
const [v1Launches, v12Launches, positionTransfers] = await Promise.all([
43+
getLogs2({ api, factory: V1_FACTORY, eventAbi: V1_COIN_DEPLOYED_EVENT, fromBlock: V1_FROM_BLOCK }),
44+
getLogs2({ api, factory: V12_FACTORY, eventAbi: V12_COIN_DEPLOYED_EVENT, fromBlock: V12_FROM_BLOCK }),
45+
// Seed positions are minted to the Harvester and never leave it, so every
46+
// position NFT ever sent there is one it still holds; ownerOf below is only
47+
// a guard against that assumption breaking.
48+
getLogs2({
49+
api,
50+
target: POSITION_MANAGER,
51+
eventAbi: NFT_TRANSFER_EVENT,
52+
topics: [NFT_TRANSFER_TOPIC, null, asTopic(HARVESTER)],
53+
fromBlock: V12_FROM_BLOCK,
54+
extraKey: 'harvester-positions',
55+
}),
56+
])
57+
58+
const curveTokens = [
59+
...v1Launches.map((log) => log.token),
60+
...v12Launches.filter((log) => !log.directSeed).map((log) => log.token),
61+
]
62+
await api.sumTokens({ tokensAndOwners: curveTokens.map((token) => [ADDRESSES.null, token]) })
63+
64+
const positionIds = [...new Set(positionTransfers.map((log) => log.tokenId.toString()))]
65+
if (!positionIds.length) return
66+
const owners = await api.multiCall({
67+
target: POSITION_MANAGER,
68+
abi: 'function ownerOf(uint256 tokenId) view returns (address)',
69+
calls: positionIds,
70+
permitFailure: true,
71+
})
72+
const lockedPositionIds = positionIds.filter((_, i) => owners[i]?.toLowerCase() === HARVESTER.toLowerCase())
73+
if (!lockedPositionIds.length) return
74+
75+
return sumTokens2({
76+
api,
77+
resolveUniV4: true,
78+
uniV4ExtraConfig: {
79+
positionIds: lockedPositionIds,
80+
whitelistedTokens: [ADDRESSES.null],
81+
},
82+
})
1883
}
1984

2085
module.exports = {
2186
methodology:
22-
'Counts the native ETH held by Frontier bonding-curve token contracts on Robinhood Chain, enumerated from the factory\'s CoinDeployed events. Each token custodies the ETH its own curve raises until the curve fills, at which point the token pays out the creator fee and seeds a Uniswap V4 pool in the same transaction and its balance goes to zero — so graduated markets are excluded here and their liquidity is counted by the Uniswap V4 adapter instead. The launched tokens themselves are not counted.',
87+
'TVL is the native ETH held by un-graduated Frontier bonding-curve tokens on Robinhood Chain (v1 and v1.2 factories, enumerated from CoinDeployed; each token custodies what its curve raises until it fills and seeds its Uniswap V4 pool), plus the ETH leg of the permanently locked Uniswap V4 seed positions held by the Harvester (v1.2; the coin leg is the launched token itself and is not counted). Launched tokens are not counted anywhere, including the coins staked in Frontier\'s vaults, since their ETH backing is already counted here.',
2388
start: '2026-07-30',
89+
// The locked seed positions are Uniswap V4 liquidity, already in uniswap-v4's TVL on this chain.
90+
doublecounted: true,
2491
robinhood: { tvl },
2592
}

0 commit comments

Comments
 (0)