LaunchFeeSplitter
0x2b3d54c04362a8c1e2c63c5a2d3d6217a7694544
Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
4,472 bytes
ABI entries
27
9 read · 5 write
License
none
Contract information
- Address
- 0x2b3d54c04362a8c1e2c63c5a2d3d6217a7694544
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.26+commit.8a97fa7a
- Optimization
- Enabled
- Creator
- 0x31098c0E25…659D3783Fe
- Creation tx
- 0x6c3adc1ca9…3e0f05c52f
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (9)
creatorRewards(address) → uint256
creatorShareBps() → uint256
deployer() → address
hdxPoolKey() → address, address, uint24, int24, address
hdxPoolSet() → bool
launchHook() → address
poolManager() → address
totalCreatorRewardsAccrued() → uint256
treasury() → address
Events (2)
CreatorRewardsClaimedLaunchFeeAttributed
ABI
[
{
"inputs": [
{
"internalType": "contract IPoolManager",
"name": "_poolManager",
"type": "address"
},
{
"internalType": "address",
"name": "_treasury",
"type": "address"
},
{
"internalType": "uint256",
"name": "_creatorShareBps",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "AlreadySet",
"type": "error"
},
{
"inputs": [],
"name": "ForwardFailed",
"type": "error"
},
{
"inputs": [],
"name": "NotPoolManager",
"type": "error"
},
{
"inputs": [],
"name": "NothingToClaim",
"type": "error"
},
{
"inputs": [],
"name": "OnlyCreator",
"type": "error"
},
{
"inputs": [],
"name": "OnlyDeployer",
"type": "error"
},
{
"inputs": [],
"name": "OnlyLaunchHook",
"type": "error"
},
{
"inputs": [],
"name": "ReentrancyGuardReentrantCall",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "received",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minOut",
"type": "uint256"
}
],
"name": "SlippageExceeded",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "coin",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "ethIn",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "hdxOut",
"type": "uint256"
}
],
"name": "CreatorRewardsClaimed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "coin",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "fee",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "creatorCut",
"type": "uint256"
}
],
"name": "LaunchFeeAttributed",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "coin",
"type": "address"
},
{
"internalType": "uint256",
"name": "minHdxOut",
"type": "uint256"
}
],
"name": "claimCreatorRewards",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "coin",
"type": "address"
}
],
"name": "creatorRewards",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "creatorShareBps",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "deployer",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "hdxPoolKey",
"outputs": [
{
"internalType": "Currency",
"name": "currency0",
"type": "address"
},
{
"internalType": "Currency",
"name": "currency1",
"type": "address"
},
{
"internalType": "uint24",
"name": "fee",
"type": "uint24"
},
{
"internalType": "int24",
"name": "tickSpacing",
"type": "int24"
},
{
"internalType": "contract IHooks",
"name": "hooks",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "hdxPoolSet",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "launchHook",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "coin",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "onLaunchFee",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "poolManager",
"outputs": [
{
"internalType": "contract IPoolManager",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "Currency",
"name": "currency0",
"type": "address"
},
{
"internalType": "Currency",
"name": "currency1",
"type": "address"
},
{
"internalType": "uint24",
"name": "fee",
"type": "uint24"
},
{
"internalType": "int24",
"name": "tickSpacing",
"type": "int24"
},
{
"internalType": "contract IHooks",
"name": "hooks",
"type": "address"
}
],
"internalType": "struct PoolKey",
"name": "key",
"type": "tuple"
}
],
"name": "setHdxPool",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "hook",
"type": "address"
}
],
"name": "setLaunchHook",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "totalCreatorRewardsAccrued",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "treasury",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "unlockCallback",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol";
import {IUnlockCallback} from "v4-core/src/interfaces/callback/IUnlockCallback.sol";
import {PoolKey} from "v4-core/src/types/PoolKey.sol";
import {Currency} from "v4-core/src/types/Currency.sol";
import {BalanceDelta} from "v4-core/src/types/BalanceDelta.sol";
import {SwapParams} from "v4-core/src/types/PoolOperation.sol";
import {TickMath} from "v4-core/src/libraries/TickMath.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {LaunchCoin} from "./LaunchCoin.sol";
/// @title LaunchFeeSplitter — CREATOR REWARDS for launchpad-coins
/// @notice Fee-mottaker for alle launchpad-pools. Av launchpadens 4 %-fee:
/// - 1 %-poeng (25 % av feen) oeremerkes COINENS CREATOR
/// - resten (3 %-poeng) videresendes HDX-treasury umiddelbart
/// Creator claimer naar som helst — utbetalingen MARKEDSKJOEPER HDX
/// i HDX-poolen og sender tokens til creator. Hver claim er altsaa
/// kjoepepress paa HDX. "Launch hos oss, tjen HDX."
///
/// @dev Attribusjon: LaunchFeeHook kaller onLaunchFee(coin, amount) rett
/// etter at ETH-feen er tatt hit via poolManager.take.
/// @dev Foer HDX-poolen er satt (setHdxPool, én gang) utbetales claims i
/// ETH som fallback — relevant kun for testnet.
contract LaunchFeeSplitter is IUnlockCallback, ReentrancyGuard {
address public immutable treasury;
IPoolManager public immutable poolManager;
address public immutable deployer;
/// @notice Andel av feen som gaar til creator. 2500 bps av 4 %-feen
/// = 1 %-poeng av traden.
uint256 public immutable creatorShareBps;
uint256 internal constant BPS = 10_000;
address public launchHook; // settes én gang etter hook-deploy
PoolKey public hdxPoolKey; // settes én gang naar HDX-poolen finnes
bool public hdxPoolSet;
/// @notice Claimbar creator-pott per coin, i ETH (veksles til HDX ved claim).
mapping(address coin => uint256) public creatorRewards;
uint256 public totalCreatorRewardsAccrued; // livstid, for statistikk
event LaunchFeeAttributed(address indexed coin, uint256 fee, uint256 creatorCut);
event CreatorRewardsClaimed(address indexed coin, address indexed creator, uint256 ethIn, uint256 hdxOut);
error OnlyDeployer();
error OnlyLaunchHook();
error OnlyCreator();
error AlreadySet();
error NothingToClaim();
error ForwardFailed();
error NotPoolManager();
error SlippageExceeded(uint256 received, uint256 minOut);
constructor(IPoolManager _poolManager, address _treasury, uint256 _creatorShareBps) {
require(_creatorShareBps <= BPS, "share too high");
poolManager = _poolManager;
treasury = _treasury;
creatorShareBps = _creatorShareBps;
deployer = msg.sender;
}
receive() external payable {} // ETH fra poolManager.take (hook-fees)
// ---- Engangs-oppsett (deployer, foer bruk) ----
function setLaunchHook(address hook) external {
if (msg.sender != deployer) revert OnlyDeployer();
if (launchHook != address(0)) revert AlreadySet();
launchHook = hook;
}
function setHdxPool(PoolKey calldata key) external {
if (msg.sender != deployer) revert OnlyDeployer();
if (hdxPoolSet) revert AlreadySet();
hdxPoolKey = key;
hdxPoolSet = true;
}
// ---- Fee-attribusjon (kalles av hooken per swap) ----
function onLaunchFee(address coin, uint256 amount) external {
if (msg.sender != launchHook) revert OnlyLaunchHook();
uint256 creatorCut = (amount * creatorShareBps) / BPS;
creatorRewards[coin] += creatorCut;
totalCreatorRewardsAccrued += creatorCut;
uint256 forward = amount - creatorCut;
if (forward > 0) {
(bool ok,) = treasury.call{value: forward}("");
if (!ok) revert ForwardFailed();
}
emit LaunchFeeAttributed(coin, amount, creatorCut);
}
// ---- Creator claim: ETH-potten markedskjoeper HDX til creator ----
/// @param minHdxOut AUDIT-fix M-3: minste HDX creator godtar for potten —
/// uten dette kunne claim-kjoepet sandwiches uten grense. Settes av
/// frontenden fra gjeldende pris med slippage-toleranse. Ignoreres
/// i ETH-fallbacken (ingen swap skjer da).
function claimCreatorRewards(address coin, uint256 minHdxOut) external nonReentrant {
address creator = LaunchCoin(coin).creator();
if (msg.sender != creator) revert OnlyCreator();
uint256 amount = creatorRewards[coin];
if (amount == 0) revert NothingToClaim();
creatorRewards[coin] = 0;
if (hdxPoolSet) {
poolManager.unlock(abi.encode(coin, creator, amount, minHdxOut));
} else {
// Testnet-fallback foer HDX-poolen finnes: utbetal ETH.
(bool ok,) = creator.call{value: amount}("");
if (!ok) revert ForwardFailed();
emit CreatorRewardsClaimed(coin, creator, amount, 0);
}
}
/// @dev Kjoep HDX for creator-potten: exactInput ETH -> HDX i HDX-poolen,
/// HDX tas direkte ut til creator. (Kjøpet betaler selv 4 %-hooken
/// — creator-claims mater altsaa ogsaa treasury.)
function unlockCallback(bytes calldata data) external returns (bytes memory) {
if (msg.sender != address(poolManager)) revert NotPoolManager();
(address coin, address creator, uint256 amount, uint256 minHdxOut) =
abi.decode(data, (address, address, uint256, uint256));
BalanceDelta delta = poolManager.swap(
hdxPoolKey,
SwapParams({
zeroForOne: true, // ETH (currency0) -> HDX (currency1)
amountSpecified: -int256(amount),
sqrtPriceLimitX96: TickMath.MIN_SQRT_PRICE + 1
}),
""
);
// Betal ETH-siden, ta HDX-siden rett til creator.
if (delta.amount0() < 0) {
poolManager.settle{value: uint256(uint128(-delta.amount0()))}();
}
uint256 hdxOut;
if (delta.amount1() > 0) {
hdxOut = uint256(uint128(delta.amount1()));
poolManager.take(hdxPoolKey.currency1, creator, hdxOut);
}
if (hdxOut < minHdxOut) revert SlippageExceeded(hdxOut, minHdxOut);
emit CreatorRewardsClaimed(coin, creator, amount, hdxOut);
return "";
}
}
Chain explorer3903msChain node81ms