LemonCurveFactory
0x4924d006edd8c142eb3f78c4e8437bf718764485
Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
12,449 bytes
ABI entries
12
9 read · 1 write
License
none
Contract information
- Address
- 0x4924d006edd8c142eb3f78c4e8437bf718764485
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.26+commit.8a97fa7a
- Optimization
- Enabled
- Creator
- 0x5988E14444…a8F6665e35
- Creation tx
- 0xfa5dc6bb18…730017533e
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (9)
ANTI_SNIPE_MAX_WALLET() → uint256
ANTI_SNIPE_WINDOW_SECS() → uint256
POOL_FEE() → uint24
TOKEN_SUPPLY() → uint256
curveDeployer() → address
getTokenInfo(address) → tuple
launches(address) → address, address, address, uint256, uint16, uint8
platformFeeReceiver() → address
weth() → address
Events (1)
CurveLaunched
ABI
[
{
"inputs": [
{
"internalType": "contract IWETH",
"name": "_weth",
"type": "address"
},
{
"internalType": "address",
"name": "_platformFeeReceiver",
"type": "address"
},
{
"internalType": "contract CurveDeployer",
"name": "_curveDeployer",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "curve",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "deployer",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "dexFactory",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "positionManager",
"type": "address"
},
{
"indexed": false,
"internalType": "uint8",
"name": "dexKind",
"type": "uint8"
},
{
"indexed": false,
"internalType": "uint256",
"name": "graduationThreshold",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint16",
"name": "creatorFeeBps",
"type": "uint16"
},
{
"indexed": false,
"internalType": "string",
"name": "name",
"type": "string"
},
{
"indexed": false,
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"indexed": false,
"internalType": "string",
"name": "tokenURI",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256",
"name": "timestamp",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "virtualTokenReserve",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "virtualEthReserve",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "totalSupply",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "initialTokenReserve",
"type": "uint256"
}
],
"name": "CurveLaunched",
"type": "event"
},
{
"inputs": [],
"name": "ANTI_SNIPE_MAX_WALLET",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "ANTI_SNIPE_WINDOW_SECS",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "POOL_FEE",
"outputs": [
{
"internalType": "uint24",
"name": "",
"type": "uint24"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TOKEN_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "curveDeployer",
"outputs": [
{
"internalType": "contract CurveDeployer",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "getTokenInfo",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "curve",
"type": "address"
},
{
"internalType": "address",
"name": "deployer",
"type": "address"
},
{
"internalType": "uint256",
"name": "graduationThreshold",
"type": "uint256"
},
{
"internalType": "uint16",
"name": "creatorFeeBps",
"type": "uint16"
},
{
"internalType": "uint8",
"name": "dexKind",
"type": "uint8"
},
{
"internalType": "bool",
"name": "graduated",
"type": "bool"
},
{
"internalType": "address",
"name": "poolAfterGraduation",
"type": "address"
},
{
"internalType": "address",
"name": "lpLocker",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "ethReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "virtualTokenReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "virtualEthReserve",
"type": "uint256"
}
],
"internalType": "struct LemonCurveFactory.TokenInfo",
"name": "info",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "string",
"name": "tokenURI",
"type": "string"
},
{
"internalType": "address",
"name": "dexFactory",
"type": "address"
},
{
"internalType": "address",
"name": "positionManager",
"type": "address"
},
{
"internalType": "uint8",
"name": "dexKind",
"type": "uint8"
},
{
"internalType": "uint256",
"name": "graduationThreshold",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "virtualTokenReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "virtualEthReserve",
"type": "uint256"
},
{
"internalType": "uint16",
"name": "creatorFeeBps",
"type": "uint16"
},
{
"internalType": "address",
"name": "creatorFeeReceiver",
"type": "address"
},
{
"internalType": "string",
"name": "logoURI",
"type": "string"
},
{
"internalType": "string",
"name": "description",
"type": "string"
},
{
"internalType": "string",
"name": "twitter",
"type": "string"
},
{
"internalType": "string",
"name": "telegram",
"type": "string"
},
{
"internalType": "string",
"name": "website",
"type": "string"
}
],
"internalType": "struct LemonCurveFactory.LaunchParams",
"name": "p",
"type": "tuple"
}
],
"name": "launch",
"outputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "curve",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "launches",
"outputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "curve",
"type": "address"
},
{
"internalType": "address",
"name": "deployer",
"type": "address"
},
{
"internalType": "uint256",
"name": "graduationThreshold",
"type": "uint256"
},
{
"internalType": "uint16",
"name": "creatorFeeBps",
"type": "uint16"
},
{
"internalType": "uint8",
"name": "dexKind",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "platformFeeReceiver",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "weth",
"outputs": [
{
"internalType": "contract IWETH",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import {LemonToken} from "./LemonToken.sol";
import {BondingCurve} from "./BondingCurve.sol";
import {IUniswapV3Factory, IUniswapV3Pool, INonfungiblePositionManager, IWETH} from "./interfaces/IUniswap.sol";
import {CurveDeployer} from "./deployers/CurveDeployer.sol";
/// @notice Factory that deploys LemonToken + BondingCurve pairs.
///
/// LemonToken is deployed directly by this factory so explorers/scanners see
/// the same one-hop internal contract-creation trace as the reference launchpad.
/// The large BondingCurve bytecode remains behind CurveDeployer to keep the
/// factory under EIP-170 without hiding the token deployment from indexers.
contract LemonCurveFactory {
uint256 public constant TOKEN_SUPPLY = 1_000_000_000e18;
uint24 public constant POOL_FEE = 10_000;
uint256 public constant ANTI_SNIPE_MAX_WALLET = 10_000_000e18; // 1% of supply, scanner parity
uint256 public constant ANTI_SNIPE_WINDOW_SECS = 900;
IWETH public immutable weth;
address public immutable platformFeeReceiver;
CurveDeployer public immutable curveDeployer;
struct Launched {
address token;
address curve;
address deployer;
uint256 graduationThreshold;
uint16 creatorFeeBps;
uint8 dexKind; // 0 = Uniswap, 1 = Sushi
}
mapping(address token => Launched) public launches;
event CurveLaunched(
address indexed token,
address indexed curve,
address indexed deployer,
address dexFactory,
address positionManager,
uint8 dexKind,
uint256 graduationThreshold,
uint16 creatorFeeBps,
string name,
string symbol,
string tokenURI,
uint256 timestamp,
uint256 virtualTokenReserve,
uint256 virtualEthReserve,
uint256 totalSupply,
uint256 initialTokenReserve
);
constructor(
IWETH _weth,
address _platformFeeReceiver,
CurveDeployer _curveDeployer
) {
weth = _weth;
platformFeeReceiver = _platformFeeReceiver;
curveDeployer = _curveDeployer;
}
struct LaunchParams {
string name;
string symbol;
string tokenURI;
address dexFactory;
address positionManager;
uint8 dexKind;
uint256 graduationThreshold;
uint256 virtualTokenReserve;
uint256 virtualEthReserve;
uint16 creatorFeeBps;
address creatorFeeReceiver;
// On-chain metadata
string logoURI;
string description;
string twitter;
string telegram;
string website;
}
function launch(LaunchParams calldata p) external returns (address token, address curve) {
require(bytes(p.name).length > 0 && bytes(p.symbol).length > 0, "meta");
require(p.dexFactory != address(0) && p.positionManager != address(0), "dex");
require(p.graduationThreshold > 0, "threshold=0");
require(p.virtualEthReserve > 0 && p.virtualTokenReserve > 0, "vreserves");
require(p.creatorFeeBps <= 1000, "creatorFee>10%");
require(p.dexKind <= 1, "dexKind");
token = address(new LemonToken(
p.name,
p.symbol,
TOKEN_SUPPLY,
address(this),
p.logoURI,
p.description,
p.twitter,
p.telegram,
p.website
));
curve = curveDeployer.deployCurve(CurveDeployer.Args({
token: LemonToken(token),
weth: weth,
dexFactory: p.dexFactory,
positionManager: p.positionManager,
deployer: msg.sender,
creatorFeeReceiver: p.creatorFeeReceiver == address(0) ? msg.sender : p.creatorFeeReceiver,
platformFeeReceiver: platformFeeReceiver,
creatorFeeBps: p.creatorFeeBps,
graduationThreshold: p.graduationThreshold,
virtualTokenReserve: p.virtualTokenReserve,
virtualEthReserve: p.virtualEthReserve,
stocksVault: address(0),
vaultBps: uint16(0)
}));
_finalizeLaunch(token, curve);
launches[token] = Launched({
token: token,
curve: curve,
deployer: msg.sender,
graduationThreshold: p.graduationThreshold,
creatorFeeBps: p.creatorFeeBps,
dexKind: p.dexKind
});
_emitCurveLaunched(token, curve, p);
}
/// @dev Seeds the curve with the full supply and locks in the launch
/// protections. Pool wiring happens later, inside BondingCurve._graduate().
function _finalizeLaunch(address token, address curve) internal {
LemonToken tok = LemonToken(token);
require(tok.transfer(curve, tok.totalSupply()), "seed");
tok.configureLaunch(ANTI_SNIPE_MAX_WALLET, 0, ANTI_SNIPE_WINDOW_SECS);
tok.initPoolSetter(curve);
}
function _emitCurveLaunched(address token, address curve, LaunchParams calldata p) internal {
uint256 supply = LemonToken(token).totalSupply();
emit CurveLaunched(
token, curve, msg.sender,
p.dexFactory, p.positionManager, p.dexKind,
p.graduationThreshold, p.creatorFeeBps,
p.name, p.symbol, p.tokenURI,
block.timestamp,
p.virtualTokenReserve, p.virtualEthReserve,
supply, supply
);
}
// --- Views ---
struct TokenInfo {
address token;
address curve;
address deployer;
uint256 graduationThreshold;
uint16 creatorFeeBps;
uint8 dexKind;
bool graduated;
address poolAfterGraduation;
address lpLocker;
uint256 tokenReserve;
uint256 ethReserve;
uint256 virtualTokenReserve;
uint256 virtualEthReserve;
}
function getTokenInfo(address token) external view returns (TokenInfo memory info) {
Launched memory L = launches[token];
info.token = L.token;
info.curve = L.curve;
info.deployer = L.deployer;
info.graduationThreshold = L.graduationThreshold;
info.creatorFeeBps = L.creatorFeeBps;
info.dexKind = L.dexKind;
if (L.curve == address(0)) return info;
BondingCurve c = BondingCurve(payable(L.curve));
info.graduated = c.graduated();
info.poolAfterGraduation = c.poolAfterGraduation();
info.lpLocker = c.lpLockerAddress();
info.tokenReserve = c.tokenReserve();
info.ethReserve = c.ethReserve();
info.virtualTokenReserve = c.virtualTokenReserve();
info.virtualEthReserve = c.virtualEthReserve();
}
}
Chain explorer6113msChain node957ms