// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
interface ICurveTokenAuthority {
/// @notice Routers governance trusts to custody pre-graduation tokens.
function allowedRouter(address router) external view returns (bool);
/// @notice Current creator (max-wallet exempt); follows transferCreatorship.
function creatorOf(address token) external view returns (address);
/// @notice Live pre-graduation per-holder cap in tokens (governable; 0 after
/// graduation the cap is skipped entirely by this token).
function maxWallet() external view returns (uint256);
}
/// @title FlowPadCurveToken (v4 single-sided model)
/// @notice LOCAL-ONLY, EXPERIMENTAL. Fixed 1B-supply ERC-20 for the
/// single-sided-liquidity model: the ENTIRE curve supply is seeded as a real
/// Uniswap v4 concentrated-liquidity position at launch (see FlowPadCurveHook),
/// so the token is a genuine on-chain market — routable by any v4 aggregator
/// (GMGN, Axiom, Universal Router) from block one.
///
/// Because there is REAL liquidity from tx 1, the pre-graduation transfer gate
/// of the old (synthetic-curve) model — which whitelisted only the launcher,
/// hook and PoolManager as movers — would break external routing (an aggregator
/// that custodies the token for a hop is neither). This token therefore keeps
/// ONLY the anti-whale MAX-WALLET cap during the curve and lets every transfer
/// leg through, so it trades everywhere. The cap is enforced on the pool-exit
/// leg (`from == poolManager`); the creator, the venue and governance-approved
/// routers are exempt (mirrors production Weg 2 / setRouterAllowed). The cap is
/// read LIVE from the launcher, so governance can adjust it without a redeploy.
/// After graduation the cap is lifted and the token trades with no restrictions.
contract FlowPadCurveToken is ERC20 {
error MaxWalletExceeded();
error NotAuthorized();
uint256 public constant TOTAL_SUPPLY = 1_000_000_000 ether;
address public immutable launcher; // curve launcher + token authority
address public immutable hook; // curve venue (seeds/holds LP + fees)
address public immutable poolManager; // v4 PoolManager (the AMM venue)
bool public graduated;
constructor(string memory name_, string memory symbol_, address hook_, address poolManager_)
ERC20(name_, symbol_)
{
launcher = msg.sender;
hook = hook_;
poolManager = poolManager_;
_mint(msg.sender, TOTAL_SUPPLY);
}
/// @notice Lift the pre-graduation cap. Callable once, only by the launcher
/// or the hook (which runs graduation).
function setGraduated() external {
if (msg.sender != launcher && msg.sender != hook) revert NotAuthorized();
graduated = true;
}
function _isVenue(address a) internal view returns (bool) {
return a == launcher || a == hook || a == poolManager;
}
function _update(address from, address to, uint256 value) internal override {
// Cap ONLY the pool-exit leg (a buy out of the PoolManager) pre-grad, so
// ordinary wallet↔wallet transfers and custody-router sweeps (from a
// router back to the user) are never blocked — the token stays routable
// by any aggregator. The venue, the creator and governance-approved
// routers are exempt (matches production Weg 2 / setRouterAllowed).
if (!graduated && from == poolManager && to != address(0) && !_isVenue(to)) {
address creator = ICurveTokenAuthority(launcher).creatorOf(address(this));
bool exempt = to == creator || ICurveTokenAuthority(launcher).allowedRouter(to);
if (!exempt && balanceOf(to) + value > ICurveTokenAuthority(launcher).maxWallet()) {
revert MaxWalletExceeded();
}
}
super._update(from, to, value);
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "name_",
"type": "string",
"internalType": "string"
},
{
"name": "symbol_",
"type": "string",
"internalType": "string"
},
{
"name": "hook_",
"type": "address",
"internalType": "address"
},
{
"name": "poolManager_",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "nonpayable"
},
{
"name": "ERC20InsufficientAllowance",
"type": "error",
"inputs": [
{
"name": "spender",
"type": "address",
"internalType": "address"
},
{
"name": "allowance",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "needed",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "ERC20InsufficientBalance",
"type": "error",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "balance",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "needed",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "ERC20InvalidApprover",
"type": "error",
"inputs": [
{
"name": "approver",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ERC20InvalidReceiver",
"type": "error",
"inputs": [
{
"name": "receiver",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ERC20InvalidSender",
"type": "error",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ERC20InvalidSpender",
"type": "error",
"inputs": [
{
"name": "spender",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "MaxWalletExceeded",
"type": "error",
"inputs": []
},
{
"name": "NotAuthorized",
"type": "error",
"inputs": []
},
{
"name": "Approval",
"type": "event",
"inputs": [
{
"name": "owner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "spender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "Transfer",
"type": "event",
"inputs": [
{
"name": "from",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "TOTAL_SUPPLY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "allowance",
"type": "function",
"inputs": [
{
"name": "owner",
"type": "address",
"internalType": "address"
},
{
"name": "spender",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "approve",
"type": "function",
"inputs": [
{
"name": "spender",
"type": "address",
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "nonpayable"
},
{
"name": "balanceOf",
"type": "function",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "decimals",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "graduated",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "hook",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "launcher",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "name",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"name": "poolManager",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "setGraduated",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "symbol",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"name": "totalSupply",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "transfer",
"type": "function",
"inputs": [
{
"name": "to",
"type": "address",
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "nonpayable"
},
{
"name": "transferFrom",
"type": "function",
"inputs": [
{
"name": "from",
"type": "address",
"internalType": "address"
},
{
"name": "to",
"type": "address",
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "nonpayable"
}
]0x6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde03146105c657508063095ea7b31461054457806316eebd1e1461050057806318160ddd146104e357806323b872dd146104045780632ac1a8da1461036c578063313ce5671461035157806370a082311461031a5780637f5a7c7b146102d6578063902d55a5146102b057806395d89b41146101ac578063a9059cbb1461017b578063dc4c90d314610137578063dd62ed3e146100e75763e7c2b772146100c1575f80fd5b346100e3575f3660031901126100e357602060ff600554166040519015158152f35b5f80fd5b346100e35760403660031901126100e3576101006106a8565b6101086106be565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b346100e3575f3660031901126100e3576040517f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03168152602090f35b346100e35760403660031901126100e3576101a16101976106a8565b602435903361070a565b602060405160018152f35b346100e3575f3660031901126100e3576040515f6004548060011c906001811680156102a6575b6020831081146102925782855290811561026e5750600114610210575b61020c83610200818503826106d4565b6040519182918261067e565b0390f35b91905060045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b915f905b808210610254575090915081016020016102006101f0565b91926001816020925483858801015201910190929161023c565b60ff191660208086019190915291151560051b8401909101915061020090506101f0565b634e487b7160e01b5f52602260045260245ffd5b91607f16916101d3565b346100e3575f3660031901126100e35760206040516b033b2e3c9fd0803ce80000008152f35b346100e3575f3660031901126100e3576040517f0000000000000000000000004f4571054f590b275ccc48ac436e17e87e82e8cc6001600160a01b03168152602090f35b346100e35760203660031901126100e3576001600160a01b0361033b6106a8565b165f525f602052602060405f2054604051908152f35b346100e3575f3660031901126100e357602060405160128152f35b346100e3575f3660031901126100e357337f000000000000000000000000f875403666f14f8206537b4d028462a7263670346001600160a01b03161415806103d1575b6103c2576005805460ff19166001179055005b63ea8e4eb560e01b5f5260045ffd5b50337f0000000000000000000000004f4571054f590b275ccc48ac436e17e87e82e8cc6001600160a01b031614156103af565b346100e35760603660031901126100e35761041d6106a8565b6104256106be565b6001600160a01b0382165f818152600160209081526040808320338452909152902054909260443592915f198110610463575b506101a1935061070a565b8381106104c85784156104b55733156104a2576101a1945f52600160205260405f2060018060a01b0333165f526020528360405f209103905584610458565b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b8390637dc7a0d960e11b5f523360045260245260445260645ffd5b346100e3575f3660031901126100e3576020600254604051908152f35b346100e3575f3660031901126100e3576040517f000000000000000000000000f875403666f14f8206537b4d028462a7263670346001600160a01b03168152602090f35b346100e35760403660031901126100e35761055d6106a8565b6024359033156104b5576001600160a01b03169081156104a257335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346100e3575f3660031901126100e3575f6003548060011c90600181168015610674575b6020831081146102925782855290811561026e57506001146106165761020c83610200818503826106d4565b91905060035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b915f905b80821061065a575090915081016020016102006101f0565b919260018160209254838588010152019101909291610642565b91607f16916105ea565b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b03821682036100e357565b602435906001600160a01b03821682036100e357565b90601f8019910116810190811067ffffffffffffffff8211176106f657604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160a01b0316908115610a7e576001600160a01b0316918215610a6b5760ff600554161580610a39575b80610a31575b8061098c575b6107bf575b815f525f60205260405f20548181106107a657817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b6040516306f52e1760e51b81523060048201527f000000000000000000000000f875403666f14f8206537b4d028462a7263670346001600160a01b031690602081602481855afa9081156108be575f9161094a575b506001600160a01b0316841480156108dd575b159081610844575b501561074857632ce93b5960e01b5f5260045ffd5b9050835f525f60205260405f20548281018091116108c95760206004926040519384809263f8b45b0560e01b82525afa9182156108be575f9261088a575b50115f61082f565b9091506020813d6020116108b6575b816108a6602093836106d4565b810103126100e35751905f610882565b3d9150610899565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b506040516330ca07d560e01b815260048101859052602081602481855afa9081156108be575f9161090f575b50610827565b90506020813d602011610942575b8161092a602093836106d4565b810103126100e3575180151581036100e3575f610909565b3d915061091d565b90506020813d602011610984575b81610965602093836106d4565b810103126100e357516001600160a01b03811681036100e3575f610814565b3d9150610958565b507f000000000000000000000000f875403666f14f8206537b4d028462a7263670346001600160a01b0316831480156109ff575b80156109cd575b15610743565b507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b031683146109c7565b507f0000000000000000000000004f4571054f590b275ccc48ac436e17e87e82e8cc6001600160a01b031683146109c0565b50600161073d565b507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03168214610737565b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffdfea264697066735822122056dc2b994ea51e641cce3a9e30b204582901d29131b4582bd797a5177d554b2864736f6c634300081a0033
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| no token holdings | ||||
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| no token transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x91e230…46cb58 | 24 days agoFri, 24 Jul 2026 20:29:25 UTC | Approval | [0] 0x000000000000…5ce0f502 [1] 0x000000000000…c0d9fbe5 data: 0x000000000000000000…b2400000 |
| 0x15033f…460c09 | 33 days agoWed, 15 Jul 2026 17:12:21 UTC | Transfer | [0] 0x000000000000…26367034 [1] 0x000000000000…5ce0f502 data: 0x000000000000000000…4f897c96 |
| 0x15033f…460c09 | 33 days agoWed, 15 Jul 2026 17:12:21 UTC | Transfer | [0] 0x000000000000…43e40951 [1] 0x000000000000…26367034 data: 0x000000000000000000…4f897c96 |
| 0x15033f…460c09 | 33 days agoWed, 15 Jul 2026 17:12:21 UTC | Transfer | [0] 0x000000000000…7e82e8cc [1] 0x000000000000…43e40951 data: 0x000000000000000000…e7ffcda0 |
| 0x15033f…460c09 | 33 days agoWed, 15 Jul 2026 17:12:21 UTC | Transfer | [0] 0x000000000000…26367034 [1] 0x000000000000…7e82e8cc data: 0x000000000000000000…e8000000 |
| 0x15033f…460c09 | 33 days agoWed, 15 Jul 2026 17:12:21 UTC | Transfer | [0] 0x000000000000…00000000 [1] 0x000000000000…26367034 data: 0x000000000000000000…e8000000 |
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x91e230…46cb58 | Approve | 18,436,854 | 24 days agoFri, 24 Jul 2026 20:29:25 UTC | 0xbfd1…f502 | IN | Do Not Buy v4 | $0.000 ETH | 0.00000502 |
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 10,563,966 | 33 days agoWed, 15 Jul 2026 17:12:21 UTC | 0x15033f…460c09 | CREATE | launch | 0xf875…7034 | IN | 0xd654…603a | 0 ETH |