LaunchFactory
0x56d2a4512b00e792831e74149126994da3c62967
Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
8,371 bytes
ABI entries
20
10 read · 1 write
License
none
Contract information
- Address
- 0x56d2a4512b00e792831e74149126994da3c62967
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.26+commit.8a97fa7a
- Optimization
- Enabled
- Creator
- 0xD8c485F701…0BB29f0146
- Creation tx
- 0x46a3574e15…461956050d
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (10)
controllerImplementation() → address
feeController() → address
guardian() → address
launch(uint256) → tuple
launchCount() → uint256
launchHook() → address
launchRouter() → address
predictController(uint256, address, string, string) → address
tokenScaleDivisor() → uint256
treasury() → address
Events (1)
LaunchCreated
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "controllerImplementation_",
"type": "address"
},
{
"internalType": "contract LaunchHook",
"name": "hook_",
"type": "address"
},
{
"internalType": "contract FeeController",
"name": "feeController_",
"type": "address"
},
{
"internalType": "contract LaunchRouter",
"name": "router_",
"type": "address"
},
{
"internalType": "address",
"name": "guardian_",
"type": "address"
},
{
"internalType": "address",
"name": "treasury_",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "address",
"name": "target",
"type": "address"
}
],
"name": "AddressEmptyCode",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "AddressInsufficientBalance",
"type": "error"
},
{
"inputs": [],
"name": "CreatorMustCall",
"type": "error"
},
{
"inputs": [],
"name": "ERC1167FailedCreateClone",
"type": "error"
},
{
"inputs": [],
"name": "FailedInnerCall",
"type": "error"
},
{
"inputs": [],
"name": "InvalidAddress",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "SafeERC20FailedOperation",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "launchId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "controller",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "team",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "receipt",
"type": "address"
}
],
"name": "LaunchCreated",
"type": "event"
},
{
"inputs": [],
"name": "controllerImplementation",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"internalType": "address",
"name": "team",
"type": "address"
}
],
"name": "createLaunch",
"outputs": [
{
"internalType": "uint256",
"name": "launchId",
"type": "uint256"
},
{
"components": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "controller",
"type": "address"
},
{
"internalType": "address",
"name": "receipt",
"type": "address"
},
{
"internalType": "address",
"name": "creatorEscrow",
"type": "address"
},
{
"internalType": "address",
"name": "teamEscrow",
"type": "address"
},
{
"internalType": "address",
"name": "protocolEscrow",
"type": "address"
},
{
"internalType": "address",
"name": "creatorProceedsEscrow",
"type": "address"
},
{
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"internalType": "address",
"name": "team",
"type": "address"
}
],
"internalType": "struct LaunchFactory.LaunchRecord",
"name": "record",
"type": "tuple"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "feeController",
"outputs": [
{
"internalType": "contract FeeController",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "guardian",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "launchId",
"type": "uint256"
}
],
"name": "launch",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "controller",
"type": "address"
},
{
"internalType": "address",
"name": "receipt",
"type": "address"
},
{
"internalType": "address",
"name": "creatorEscrow",
"type": "address"
},
{
"internalType": "address",
"name": "teamEscrow",
"type": "address"
},
{
"internalType": "address",
"name": "protocolEscrow",
"type": "address"
},
{
"internalType": "address",
"name": "creatorProceedsEscrow",
"type": "address"
},
{
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"internalType": "address",
"name": "team",
"type": "address"
}
],
"internalType": "struct LaunchFactory.LaunchRecord",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "launchCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "launchHook",
"outputs": [
{
"internalType": "contract LaunchHook",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "launchRouter",
"outputs": [
{
"internalType": "contract LaunchRouter",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "launchId",
"type": "uint256"
},
{
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
}
],
"name": "predictController",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "tokenScaleDivisor",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "treasury",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import { Clones } from "openzeppelin-contracts/contracts/proxy/Clones.sol";
import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import { FeeController } from "./FeeController.sol";
import { LaunchController } from "./LaunchController.sol";
import { LaunchHook } from "./LaunchHook.sol";
import { LaunchRouter } from "./LaunchRouter.sol";
import { LaunchToken } from "./LaunchToken.sol";
import { ProtocolTokenFeeVault } from "./ProtocolTokenFeeVault.sol";
import { LaunchConstants } from "./libraries/LaunchConstants.sol";
/// @notice Permissionless launch creation with exact approved allocation custody.
contract LaunchFactory {
using SafeERC20 for IERC20;
struct LaunchRecord {
address token;
address controller;
address receipt;
address creatorEscrow;
address teamEscrow;
address protocolEscrow;
address creatorProceedsEscrow;
address creator;
address team;
}
address public immutable controllerImplementation;
LaunchHook public immutable launchHook;
FeeController public immutable feeController;
LaunchRouter public immutable launchRouter;
address public immutable guardian;
address public immutable treasury;
uint256 public launchCount;
mapping(uint256 launchId => LaunchRecord) private launches;
error InvalidAddress();
error CreatorMustCall();
event LaunchCreated(
uint256 indexed launchId,
address indexed token,
address indexed controller,
address creator,
address team,
address receipt
);
constructor(
address controllerImplementation_,
LaunchHook hook_,
FeeController feeController_,
LaunchRouter router_,
address guardian_,
address treasury_
) {
if (
controllerImplementation_ == address(0) || address(hook_) == address(0)
|| address(feeController_) == address(0) || address(router_) == address(0) || guardian_ == address(0)
|| treasury_ == address(0)
) revert InvalidAddress();
controllerImplementation = controllerImplementation_;
launchHook = hook_;
feeController = feeController_;
launchRouter = router_;
guardian = guardian_;
treasury = treasury_;
}
function launch(uint256 launchId) external view returns (LaunchRecord memory) {
return launches[launchId];
}
/// @notice One on production chains and 1,000 on Robinhood testnet 46630.
function tokenScaleDivisor() external view returns (uint256) {
return LaunchConstants.tokenScaleDivisor();
}
function createLaunch(string calldata name, string calldata symbol, address creator, address team)
external
returns (uint256 launchId, LaunchRecord memory record)
{
if (creator != msg.sender) revert CreatorMustCall();
if (team == address(0)) revert InvalidAddress();
launchId = launchCount++;
bytes32 salt = keccak256(abi.encode(block.chainid, address(this), launchId, creator, name, symbol));
address controllerAddress = Clones.cloneDeterministic(controllerImplementation, salt);
LaunchToken token = new LaunchToken(name, symbol, address(this));
ProtocolTokenFeeVault protocolTokenFeeVault = new ProtocolTokenFeeVault(IERC20(address(token)), treasury);
LaunchController controller = LaunchController(payable(controllerAddress));
controller.initialize(
IERC20(address(token)), creator, guardian, address(launchRouter), address(protocolTokenFeeVault)
);
IERC20 erc20 = IERC20(address(token));
erc20.safeTransfer(controllerAddress, LaunchConstants.controllerTokens());
feeController.registerController(controllerAddress, controller.poolId(), creator);
launchRouter.registerController(controllerAddress);
launchHook.registerPool(controller.getPoolKey(), controllerAddress, controller.bandLowerSqrts());
controller.seed();
record = LaunchRecord({
token: address(token),
controller: controllerAddress,
receipt: address(controller.receipt()),
creatorEscrow: address(0),
teamEscrow: address(0),
protocolEscrow: address(protocolTokenFeeVault),
creatorProceedsEscrow: address(0),
creator: creator,
team: team
});
launches[launchId] = record;
emit LaunchCreated(launchId, address(token), controllerAddress, creator, team, record.receipt);
}
function predictController(uint256 launchId, address creator, string calldata name, string calldata symbol)
external
view
returns (address)
{
bytes32 salt = keccak256(abi.encode(block.chainid, address(this), launchId, creator, name, symbol));
return Clones.predictDeterministicAddress(controllerImplementation, salt, address(this));
}
}
Chain explorer4112msChain node75ms