PonsV2LaunchFactory
0x07090eded353736f4403dec96f7163b00e559005
Verification
Verified
v0.8.35+commit.47b9dedd
Type
Contract
15,601 bytes
ABI entries
18
12 read · 2 write
License
mit
Contract information
- Address
- 0x07090eded353736f4403dec96f7163b00e559005
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.35+commit.47b9dedd
- Optimization
- Enabled
- Creator
- 0x65E982d22C…408cc7bF0e
- Creation tx
- 0x9f0804a92d…12c0e007d4
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (12)
FEE_TIER() → uint24
MAX_LAUNCH_ETH() → uint256
TOTAL_SUPPLY() → uint256
allTokenIds(uint256) → uint256
locker() → address
nextRegistrationId() → uint256
positionManager() → address
positions(uint256) → address, address, address
registrationData(uint256) → string, string, string, string, tuple, address, address, bool
totalLaunched() → uint256
treasury() → address
weth() → address
Events (2)
LaunchedRegistered
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "positionManager_",
"type": "address"
},
{
"internalType": "address",
"name": "weth_",
"type": "address"
},
{
"internalType": "address",
"name": "locker_",
"type": "address"
},
{
"internalType": "address",
"name": "treasury_",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "ReentrancyGuardReentrantCall",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "registrationId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "pool",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"indexed": false,
"internalType": "string",
"name": "name",
"type": "string"
},
{
"indexed": false,
"internalType": "string",
"name": "symbol",
"type": "string"
}
],
"name": "Launched",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "registrationId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "launchWallet",
"type": "address"
},
{
"indexed": false,
"internalType": "string",
"name": "name",
"type": "string"
},
{
"indexed": false,
"internalType": "string",
"name": "symbol",
"type": "string"
}
],
"name": "Registered",
"type": "event"
},
{
"inputs": [],
"name": "FEE_TIER",
"outputs": [
{
"internalType": "uint24",
"name": "",
"type": "uint24"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_LAUNCH_ETH",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TOTAL_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "allTokenIds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "registrationId",
"type": "uint256"
},
{
"internalType": "address",
"name": "token0",
"type": "address"
},
{
"internalType": "address",
"name": "token1",
"type": "address"
},
{
"internalType": "uint160",
"name": "sqrtPriceX96",
"type": "uint160"
},
{
"internalType": "int24",
"name": "tickLower",
"type": "int24"
},
{
"internalType": "int24",
"name": "tickUpper",
"type": "int24"
}
],
"name": "launch",
"outputs": [
{
"internalType": "address",
"name": "tokenAddress",
"type": "address"
},
{
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "locker",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "nextRegistrationId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "positionManager",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "positions",
"outputs": [
{
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "name_",
"type": "string"
},
{
"internalType": "string",
"name": "symbol_",
"type": "string"
},
{
"internalType": "string",
"name": "description_",
"type": "string"
},
{
"internalType": "string",
"name": "logo_",
"type": "string"
},
{
"components": [
{
"internalType": "string",
"name": "telegram",
"type": "string"
},
{
"internalType": "string",
"name": "twitter",
"type": "string"
},
{
"internalType": "string",
"name": "discord",
"type": "string"
},
{
"internalType": "string",
"name": "website",
"type": "string"
},
{
"internalType": "string",
"name": "farcaster",
"type": "string"
}
],
"internalType": "struct SocialLinks",
"name": "socials_",
"type": "tuple"
},
{
"internalType": "address",
"name": "creator_",
"type": "address"
},
{
"internalType": "address",
"name": "launchWallet_",
"type": "address"
}
],
"name": "register",
"outputs": [
{
"internalType": "uint256",
"name": "registrationId",
"type": "uint256"
}
],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "registrationData",
"outputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "string",
"name": "description",
"type": "string"
},
{
"internalType": "string",
"name": "logo",
"type": "string"
},
{
"components": [
{
"internalType": "string",
"name": "telegram",
"type": "string"
},
{
"internalType": "string",
"name": "twitter",
"type": "string"
},
{
"internalType": "string",
"name": "discord",
"type": "string"
},
{
"internalType": "string",
"name": "website",
"type": "string"
},
{
"internalType": "string",
"name": "farcaster",
"type": "string"
}
],
"internalType": "struct SocialLinks",
"name": "socials",
"type": "tuple"
},
{
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"internalType": "address",
"name": "launchWallet",
"type": "address"
},
{
"internalType": "bool",
"name": "launched",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalLaunched",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "treasury",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "weth",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./PonsV2Token.sol";
interface IPositionManagerFactory {
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
function createAndInitializePoolIfNecessary(
address token0,
address token1,
uint24 fee,
uint160 sqrtPriceX96
) external payable returns (address pool);
function mint(MintParams calldata params)
external
payable
returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
}
interface IPonsV2LaunchLocker {
function registerPosition(uint256 tokenId, address creator, address token) external;
}
contract PonsV2LaunchFactory is ReentrancyGuard {
uint256 public constant TOTAL_SUPPLY = 1_000_000_000 * 10 ** 18;
uint24 public constant FEE_TIER = 10000;
uint256 public constant MAX_LAUNCH_ETH = 0.001 ether;
address public immutable positionManager;
address public immutable weth;
address public immutable locker;
address public immutable treasury;
struct Registration {
string name;
string symbol;
string description;
string logo;
SocialLinks socials;
address creator;
address launchWallet;
bool launched;
}
uint256 public nextRegistrationId;
mapping(uint256 => Registration) public registrationData;
struct Position {
address creator;
address token;
address pool;
}
mapping(uint256 => Position) public positions;
uint256[] public allTokenIds;
event Registered(
uint256 indexed registrationId,
address indexed creator,
address indexed launchWallet,
string name,
string symbol
);
event Launched(
uint256 indexed registrationId,
address indexed token,
address indexed pool,
uint256 tokenId,
address creator,
string name,
string symbol
);
constructor(
address positionManager_,
address weth_,
address locker_,
address treasury_
) {
require(positionManager_ != address(0), "Zero positionManager");
require(weth_ != address(0), "Zero weth");
require(locker_ != address(0), "Zero locker");
require(treasury_ != address(0), "Zero treasury");
positionManager = positionManager_;
weth = weth_;
locker = locker_;
treasury = treasury_;
}
function register(
string memory name_,
string memory symbol_,
string memory description_,
string memory logo_,
SocialLinks memory socials_,
address creator_,
address launchWallet_
) external payable returns (uint256 registrationId) {
address creator = (creator_ == address(0)) ? msg.sender : creator_;
registrationId = nextRegistrationId++;
registrationData[registrationId] = Registration({
name: name_,
symbol: symbol_,
description: description_,
logo: logo_,
socials: socials_,
creator: creator,
launchWallet: launchWallet_,
launched: false
});
if (msg.value > 0) {
require(launchWallet_ != address(0), "launchWallet required to forward ETH");
uint256 toForward = msg.value > MAX_LAUNCH_ETH ? MAX_LAUNCH_ETH : msg.value;
uint256 excess = msg.value - toForward;
(bool ok,) = launchWallet_.call{value: toForward}("");
require(ok, "ETH forward failed");
if (excess > 0) {
(bool ok2,) = msg.sender.call{value: excess}("");
require(ok2, "ETH refund failed");
}
}
emit Registered(registrationId, creator, launchWallet_, name_, symbol_);
}
function launch(
uint256 registrationId,
address token0,
address token1,
uint160 sqrtPriceX96,
int24 tickLower,
int24 tickUpper
) external nonReentrant returns (address tokenAddress, address pool) {
Registration storage reg = registrationData[registrationId];
require(reg.creator != address(0), "Unknown registration");
require(!reg.launched, "Already launched");
require(token0 < token1, "token0 must be < token1");
if (reg.launchWallet != address(0)) {
require(msg.sender == reg.launchWallet, "Only launchWallet");
}
reg.launched = true;
PonsV2Token token = new PonsV2Token(
reg.name,
reg.symbol,
TOTAL_SUPPLY,
reg.description,
reg.logo,
reg.socials,
reg.creator,
address(this)
);
tokenAddress = address(token);
require(
tokenAddress == token0 || tokenAddress == token1,
"Token address mismatch"
);
require(
IERC20(tokenAddress).transferFrom(reg.creator, address(this), TOTAL_SUPPLY),
"Token pull failed"
);
require(
IERC20(tokenAddress).approve(positionManager, TOTAL_SUPPLY),
"Approve failed"
);
pool = IPositionManagerFactory(positionManager).createAndInitializePoolIfNecessary(
token0, token1, FEE_TIER, sqrtPriceX96
);
uint256 amount0Desired = (tokenAddress == token0) ? TOTAL_SUPPLY : 0;
uint256 amount1Desired = (tokenAddress == token1) ? TOTAL_SUPPLY : 0;
(uint256 tokenId,,,) = IPositionManagerFactory(positionManager).mint(
IPositionManagerFactory.MintParams({
token0: token0,
token1: token1,
fee: FEE_TIER,
tickLower: tickLower,
tickUpper: tickUpper,
amount0Desired: amount0Desired,
amount1Desired: amount1Desired,
amount0Min: 0,
amount1Min: 0,
recipient: locker,
deadline: block.timestamp + 1800
})
);
IPonsV2LaunchLocker(locker).registerPosition(tokenId, reg.creator, tokenAddress);
positions[tokenId] = Position({
creator: reg.creator,
token: tokenAddress,
pool: pool
});
allTokenIds.push(tokenId);
emit Launched(
registrationId,
tokenAddress,
pool,
tokenId,
reg.creator,
reg.name,
reg.symbol
);
}
function totalLaunched() external view returns (uint256) {
return allTokenIds.length;
}
}
Chain explorer3846msChain node83ms