AgentCoin
0xedfab19245990bc8cdb547668cfd0be3d06d3b11
Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
16,508 bytes
ABI entries
123
48 read · 20 write
License
none
Contract information
- Address
- 0xedfab19245990bc8cdb547668cfd0be3d06d3b11
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.26+commit.8a97fa7a
- Optimization
- Enabled
- Creator
- 0xea5AEEC394…C374a7f86E
- Creation tx
- 0xa9d1ecf9a2…904e60b8de
Token
- Name
- AgentCoin
- Symbol
- AGENT
- Decimals
- 8
- Holders
- 39
- Market
- View token page →
Read contract (48)
BPS_DENOMINATOR() → uint256
DEFAULT_ADMIN_ROLE() → bytes32
DEFAULT_MAX_MINTS() → uint256
DEFAULT_PAYMENT_PER_MINT() → uint256
DEFAULT_PAYMENT_SEED() → uint256
DEFAULT_POOL_FEE() → uint24
DEFAULT_POOL_TICK_SPACING() → int24
DEFAULT_TOKENS_PER_MINT() → uint256
HOOK_SETTER_ROLE() → bytes32
LP_LOCK_DURATION() → uint256
LP_MANAGER_ROLE() → bytes32
MAX_MINTS() → uint256
MAX_MINT_FACTOR_BPS() → uint16
MINT_AUTHORIZATION_TYPEHASH() → bytes32
MINT_SIGNER_ROLE() → bytes32
MIN_MINT_FACTOR_BPS() → uint16
PAYMENT_PER_MINT() → uint256
SQRT_PRICE_AGENT_COIN_FIRST_DEFAULT() → uint160
SQRT_PRICE_PAYMENT_TOKEN_FIRST_DEFAULT() → uint160
TOKENS_PER_MINT() → uint256
TRUMP_ACCOUNT_WITHDRAWER_ROLE() → bytes32
allowance(address, address) → uint256
balanceOf(address) → uint256
decimals() → uint8
eip712Domain() → bytes1, string, string, uint256, address, bytes32, uint256[]
getRoleAdmin(bytes32) → bytes32
hasRole(bytes32, address) → bool
liquidityDeployed() → bool
liquidityGuardHook() → address
lpPositionClaimed() → bool
lpTokenId() → uint256
lpUnlockTime() → uint256
mintAuthorizationDigest(uint256, uint16, uint256) → bytes32
mintCount() → uint256
mintDeposits(uint256) → address, address, address, uint8
name() → string
nextMintId() → uint256
owner() → address
paymentSeed() → uint256
paymentToken() → address
permit2() → address
poolManager() → address
poolSeedAmount() → uint256
positionManager() → address
supportsInterface(bytes4) → bool
symbol() → string
totalSupply() → uint256
trumpAccountTokenReserve() → uint256
Events (15)
ApprovalEIP712DomainChangedLiquidityDeployedLiquidityGuardHookSetLpFeesCollectedLpPositionClaimedMintCompletedMintFundedMintWithdrawnOwnershipTransferredRoleAdminChangedRoleGrantedRoleRevokedTransferTrumpAccountTokensWithdrawn
ABI
[
{
"inputs": [
{
"internalType": "contract IPoolManager",
"name": "poolManager_",
"type": "address"
},
{
"internalType": "contract IPositionManager",
"name": "positionManager_",
"type": "address"
},
{
"internalType": "contract IAllowanceTransfer",
"name": "permit2_",
"type": "address"
},
{
"internalType": "uint256",
"name": "paymentSeed_",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "poolSeedAmount_",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "tokensPerMint_",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "maxMints_",
"type": "uint256"
},
{
"components": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "defaultAdmin",
"type": "address"
},
{
"internalType": "address",
"name": "mintSigner",
"type": "address"
},
{
"internalType": "address",
"name": "lpManager",
"type": "address"
},
{
"internalType": "address",
"name": "trumpAccountWithdrawer",
"type": "address"
}
],
"internalType": "struct AgentCoin.InitialRoles",
"name": "initialRoles_",
"type": "tuple"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "AccessControlBadConfirmation",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "bytes32",
"name": "neededRole",
"type": "bytes32"
}
],
"name": "AccessControlUnauthorizedAccount",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "target",
"type": "address"
}
],
"name": "AddressEmptyCode",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "AddressInsufficientBalance",
"type": "error"
},
{
"inputs": [],
"name": "ContractFeeClaimWindowClosed",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "allowance",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "needed",
"type": "uint256"
}
],
"name": "ERC20InsufficientAllowance",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "uint256",
"name": "balance",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "needed",
"type": "uint256"
}
],
"name": "ERC20InsufficientBalance",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "approver",
"type": "address"
}
],
"name": "ERC20InvalidApprover",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
}
],
"name": "ERC20InvalidReceiver",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "ERC20InvalidSender",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "ERC20InvalidSpender",
"type": "error"
},
{
"inputs": [],
"name": "FailedInnerCall",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "available",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "requested",
"type": "uint256"
}
],
"name": "InsufficientTrumpAccountReserve",
"type": "error"
},
{
"inputs": [],
"name": "InvalidAddress",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "signer",
"type": "address"
}
],
"name": "InvalidMintAuthorization",
"type": "error"
},
{
"inputs": [],
"name": "InvalidMintConfig",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint16",
"name": "factorBps",
"type": "uint16"
}
],
"name": "InvalidMintFactor",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "expected",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "received",
"type": "uint256"
}
],
"name": "InvalidPaymentAmount",
"type": "error"
},
{
"inputs": [],
"name": "InvalidPaymentTokenDecimals",
"type": "error"
},
{
"inputs": [],
"name": "InvalidRobinhoodProtocolAddresses",
"type": "error"
},
{
"inputs": [],
"name": "InvalidShortString",
"type": "error"
},
{
"inputs": [],
"name": "LiquidityAlreadyDeployed",
"type": "error"
},
{
"inputs": [],
"name": "LiquidityGuardHookAlreadySet",
"type": "error"
},
{
"inputs": [],
"name": "LpNotInitialized",
"type": "error"
},
{
"inputs": [],
"name": "LpPositionAlreadyClaimed",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "unlockTime",
"type": "uint256"
}
],
"name": "LpPositionLocked",
"type": "error"
},
{
"inputs": [],
"name": "MaxMintsReached",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "deadline",
"type": "uint256"
}
],
"name": "MintAuthorizationExpired",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
}
],
"name": "MintDepositNotFunded",
"type": "error"
},
{
"inputs": [],
"name": "NativeTransferFailed",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "caller",
"type": "address"
},
{
"internalType": "address",
"name": "funder",
"type": "address"
},
{
"internalType": "address",
"name": "negotiator",
"type": "address"
}
],
"name": "NotMintDepositWithdrawer",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "caller",
"type": "address"
},
{
"internalType": "address",
"name": "negotiator",
"type": "address"
}
],
"name": "NotMintNegotiator",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "OwnableInvalidOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "OwnableUnauthorizedAccount",
"type": "error"
},
{
"inputs": [],
"name": "PoolInitializationFailed",
"type": "error"
},
{
"inputs": [],
"name": "ReentrancyGuardReentrantCall",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint8",
"name": "bits",
"type": "uint8"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "SafeCastOverflowedUintDowncast",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "SafeERC20FailedOperation",
"type": "error"
},
{
"inputs": [
{
"internalType": "string",
"name": "str",
"type": "string"
}
],
"name": "StringTooLong",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [],
"name": "EIP712DomainChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint128",
"name": "liquidity",
"type": "uint128"
}
],
"name": "LiquidityDeployed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "hook",
"type": "address"
}
],
"name": "LiquidityGuardHookSet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "LpFeesCollected",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "LpPositionClaimed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "funder",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "negotiator",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "tokenAmount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "trumpAccountAmount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint16",
"name": "factorBps",
"type": "uint16"
},
{
"indexed": false,
"internalType": "address",
"name": "signer",
"type": "address"
}
],
"name": "MintCompleted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "funder",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "negotiator",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "paymentAmount",
"type": "uint256"
}
],
"name": "MintFunded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "funder",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "initiator",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "paymentAmount",
"type": "uint256"
}
],
"name": "MintWithdrawn",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "previousAdminRole",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "newAdminRole",
"type": "bytes32"
}
],
"name": "RoleAdminChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleGranted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleRevoked",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "TrumpAccountTokensWithdrawn",
"type": "event"
},
{
"inputs": [],
"name": "BPS_DENOMINATOR",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_ADMIN_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_MAX_MINTS",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_PAYMENT_PER_MINT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_PAYMENT_SEED",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_POOL_FEE",
"outputs": [
{
"internalType": "uint24",
"name": "",
"type": "uint24"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_POOL_TICK_SPACING",
"outputs": [
{
"internalType": "int24",
"name": "",
"type": "int24"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_TOKENS_PER_MINT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "HOOK_SETTER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "LP_LOCK_DURATION",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "LP_MANAGER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_MINTS",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_MINT_FACTOR_BPS",
"outputs": [
{
"internalType": "uint16",
"name": "",
"type": "uint16"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MINT_AUTHORIZATION_TYPEHASH",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MINT_SIGNER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MIN_MINT_FACTOR_BPS",
"outputs": [
{
"internalType": "uint16",
"name": "",
"type": "uint16"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "PAYMENT_PER_MINT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "SQRT_PRICE_AGENT_COIN_FIRST_DEFAULT",
"outputs": [
{
"internalType": "uint160",
"name": "",
"type": "uint160"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "SQRT_PRICE_PAYMENT_TOKEN_FIRST_DEFAULT",
"outputs": [
{
"internalType": "uint160",
"name": "",
"type": "uint160"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TOKENS_PER_MINT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TRUMP_ACCOUNT_WITHDRAWER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "burn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "burnFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "claimLpPosition",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "collectLpFees",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
},
{
"internalType": "uint16",
"name": "factorBps",
"type": "uint16"
},
{
"internalType": "uint256",
"name": "deadline",
"type": "uint256"
},
{
"internalType": "address",
"name": "signer",
"type": "address"
},
{
"internalType": "bytes",
"name": "signature",
"type": "bytes"
}
],
"name": "completeMint",
"outputs": [
{
"internalType": "uint256",
"name": "tokenAmount",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "eip712Domain",
"outputs": [
{
"internalType": "bytes1",
"name": "fields",
"type": "bytes1"
},
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "version",
"type": "string"
},
{
"internalType": "uint256",
"name": "chainId",
"type": "uint256"
},
{
"internalType": "address",
"name": "verifyingContract",
"type": "address"
},
{
"internalType": "bytes32",
"name": "salt",
"type": "bytes32"
},
{
"internalType": "uint256[]",
"name": "extensions",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "emergencyWithdrawNative",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "emergencyWithdrawToken",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "address",
"name": "negotiator",
"type": "address"
}
],
"name": "fundMint",
"outputs": [
{
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
}
],
"name": "getRoleAdmin",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "grantRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "hasRole",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "liquidityDeployed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "liquidityGuardHook",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "lpPositionClaimed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "lpTokenId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "lpUnlockTime",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
},
{
"internalType": "uint16",
"name": "factorBps",
"type": "uint16"
},
{
"internalType": "uint256",
"name": "deadline",
"type": "uint256"
}
],
"name": "mintAuthorizationDigest",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "mintCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
}
],
"name": "mintDeposits",
"outputs": [
{
"internalType": "address",
"name": "funder",
"type": "address"
},
{
"internalType": "address",
"name": "negotiator",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "enum AgentCoin.MintDepositStatus",
"name": "status",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "nextMintId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "paymentSeed",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "paymentToken",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "permit2",
"outputs": [
{
"internalType": "contract IAllowanceTransfer",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "poolManager",
"outputs": [
{
"internalType": "contract IPoolManager",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "poolSeedAmount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "positionManager",
"outputs": [
{
"internalType": "contract IPositionManager",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "callerConfirmation",
"type": "address"
}
],
"name": "renounceRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "revokeRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "liquidityGuardHook_",
"type": "address"
}
],
"name": "setInitialLiquidityGuardHook",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "liquidityGuardHook_",
"type": "address"
}
],
"name": "setLiquidityGuardHook",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "trumpAccountTokenReserve",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "mintId",
"type": "uint256"
}
],
"name": "withdrawMintDeposit",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "withdrawTrumpAccountTokens",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {IPositionManager, PoolKey as PositionPoolKey} from "v4-periphery/src/interfaces/IPositionManager.sol";
import {Actions} from "v4-periphery/src/libraries/Actions.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {LiquidityAmounts} from "v4-periphery/src/libraries/LiquidityAmounts.sol";
import {RobinhoodAddresses} from "src/RobinhoodAddresses.sol";
contract AgentCoin is ERC20, ERC20Burnable, AccessControl, Ownable, EIP712, ReentrancyGuard {
using SafeERC20 for IERC20;
bytes32 public constant MINT_SIGNER_ROLE = keccak256("MINT_SIGNER_ROLE");
bytes32 public constant LP_MANAGER_ROLE = keccak256("LP_MANAGER_ROLE");
bytes32 public constant TRUMP_ACCOUNT_WITHDRAWER_ROLE = keccak256("TRUMP_ACCOUNT_WITHDRAWER_ROLE");
bytes32 public constant HOOK_SETTER_ROLE = keccak256("HOOK_SETTER_ROLE");
bytes32 public constant MINT_AUTHORIZATION_TYPEHASH = keccak256(
"MintAuthorization(uint256 mintId,address funder,address negotiator,address recipient,uint16 factorBps,uint256 deadline)"
);
// User mint side is 50% of total supply:
// 2,100 AgentCoin/mint * 5,000 mints = 10,500,000 AgentCoin.
uint256 public constant DEFAULT_TOKENS_PER_MINT = 2_100 * 10 ** 8;
uint256 public constant DEFAULT_MAX_MINTS = 5_000;
uint256 public constant DEFAULT_PAYMENT_SEED = 50_000 * 10 ** 6;
uint256 public constant DEFAULT_PAYMENT_PER_MINT = 10 * 10 ** 6;
uint16 public constant MIN_MINT_FACTOR_BPS = 2_000; // 20%
uint16 public constant MAX_MINT_FACTOR_BPS = 10_000; // 100%
uint256 public constant BPS_DENOMINATOR = 10_000;
uint24 public constant DEFAULT_POOL_FEE = 10_000; // 1%
int24 public constant DEFAULT_POOL_TICK_SPACING = 200;
uint256 public constant LP_LOCK_DURATION = 365 days;
// Derived from LP seed ratio 50,000 USDG (6d) : 10,500,000 AgentCoin (8d),
// using sqrtPriceX96 = floor(sqrt((amountToken1Raw << 192) / amountToken0Raw)).
uint160 public constant SQRT_PRICE_PAYMENT_TOKEN_FIRST_DEFAULT = 11481251519025279852052291705240;
uint160 public constant SQRT_PRICE_AGENT_COIN_FIRST_DEFAULT = 546726262810727612002490081;
error NativeTransferFailed();
error InvalidPaymentTokenDecimals();
error InvalidRobinhoodProtocolAddresses();
error LpNotInitialized();
error LpPositionAlreadyClaimed();
error LpPositionLocked(uint256 unlockTime);
error ContractFeeClaimWindowClosed();
error MaxMintsReached();
error InvalidMintConfig();
error InvalidAddress();
error LiquidityAlreadyDeployed();
error LiquidityGuardHookAlreadySet();
error PoolInitializationFailed();
error MintDepositNotFunded(uint256 mintId);
error NotMintDepositWithdrawer(address caller, address funder, address negotiator);
error NotMintNegotiator(address caller, address negotiator);
error InvalidMintFactor(uint16 factorBps);
error MintAuthorizationExpired(uint256 deadline);
error InvalidMintAuthorization(address signer);
error InvalidPaymentAmount(uint256 expected, uint256 received);
error InsufficientTrumpAccountReserve(uint256 available, uint256 requested);
enum MintDepositStatus {
None,
Funded,
Withdrawn,
Completed
}
struct MintDeposit {
address funder;
address negotiator;
address recipient;
MintDepositStatus status;
}
struct InitialRoles {
address owner;
address defaultAdmin;
address mintSigner;
address lpManager;
address trumpAccountWithdrawer;
}
IPoolManager public immutable poolManager;
IPositionManager public immutable positionManager;
IAllowanceTransfer public immutable permit2;
address public constant paymentToken = RobinhoodAddresses.USDG;
uint256 public immutable paymentSeed;
uint256 public immutable poolSeedAmount;
uint256 internal immutable _tokensPerMint;
uint256 internal immutable _maxMints;
uint256 internal immutable _paymentPerMint;
address public liquidityGuardHook;
uint256 public lpTokenId;
uint256 public lpUnlockTime;
bool public liquidityDeployed;
bool public lpPositionClaimed;
uint256 public nextMintId = 1;
uint256 public trumpAccountTokenReserve;
mapping(uint256 mintId => MintDeposit deposit) public mintDeposits;
uint160 internal _sqrtPricePaymentTokenFirst;
uint160 internal _sqrtPriceAgentCoinFirst;
uint256 public mintCount;
event MintFunded(
uint256 indexed mintId,
address indexed funder,
address indexed negotiator,
address recipient,
uint256 paymentAmount
);
event MintWithdrawn(
uint256 indexed mintId, address indexed funder, address indexed initiator, uint256 paymentAmount
);
event MintCompleted(
uint256 indexed mintId,
address indexed funder,
address indexed negotiator,
address recipient,
uint256 tokenAmount,
uint256 trumpAccountAmount,
uint16 factorBps,
address signer
);
event TrumpAccountTokensWithdrawn(address indexed recipient, uint256 amount);
event LiquidityGuardHookSet(address indexed hook);
event LiquidityDeployed(uint256 tokenId, uint128 liquidity);
event LpFeesCollected(address indexed recipient, uint256 indexed tokenId);
event LpPositionClaimed(address indexed recipient, uint256 indexed tokenId);
constructor(
IPoolManager poolManager_,
IPositionManager positionManager_,
IAllowanceTransfer permit2_,
uint256 paymentSeed_,
uint256 poolSeedAmount_,
uint256 tokensPerMint_,
uint256 maxMints_,
InitialRoles memory initialRoles_
) ERC20("AgentCoin", "AGENT") Ownable(initialRoles_.owner) EIP712("AgentCoin", "1") {
if (
address(poolManager_) == address(0) || address(positionManager_) == address(0)
|| address(permit2_) == address(0) || initialRoles_.owner == address(0)
|| initialRoles_.defaultAdmin == address(0) || initialRoles_.mintSigner == address(0)
|| initialRoles_.lpManager == address(0) || initialRoles_.trumpAccountWithdrawer == address(0)
) {
revert InvalidAddress();
}
if (
block.chainid == RobinhoodAddresses.CHAIN_ID
&& (address(poolManager_) != RobinhoodAddresses.UNISWAP_V4_POOL_MANAGER
|| address(positionManager_) != RobinhoodAddresses.UNISWAP_V4_POSITION_MANAGER
|| address(permit2_) != RobinhoodAddresses.PERMIT2)
) {
revert InvalidRobinhoodProtocolAddresses();
}
if (
paymentSeed_ != DEFAULT_PAYMENT_SEED || poolSeedAmount_ != DEFAULT_TOKENS_PER_MINT * DEFAULT_MAX_MINTS
|| tokensPerMint_ != DEFAULT_TOKENS_PER_MINT || maxMints_ != DEFAULT_MAX_MINTS
|| paymentSeed_ / maxMints_ != DEFAULT_PAYMENT_PER_MINT
) {
revert InvalidMintConfig();
}
if (IERC20Metadata(paymentToken).decimals() != 6) revert InvalidPaymentTokenDecimals();
poolManager = poolManager_;
positionManager = positionManager_;
permit2 = permit2_;
paymentSeed = paymentSeed_;
poolSeedAmount = poolSeedAmount_;
_tokensPerMint = tokensPerMint_;
_maxMints = maxMints_;
_paymentPerMint = paymentSeed_ / maxMints_;
_grantRole(DEFAULT_ADMIN_ROLE, initialRoles_.defaultAdmin);
_grantRole(MINT_SIGNER_ROLE, initialRoles_.mintSigner);
_grantRole(LP_MANAGER_ROLE, initialRoles_.lpManager);
_grantRole(TRUMP_ACCOUNT_WITHDRAWER_ROLE, initialRoles_.trumpAccountWithdrawer);
_grantRole(HOOK_SETTER_ROLE, msg.sender);
_sqrtPricePaymentTokenFirst = SQRT_PRICE_PAYMENT_TOKEN_FIRST_DEFAULT;
_sqrtPriceAgentCoinFirst = SQRT_PRICE_AGENT_COIN_FIRST_DEFAULT;
// Pre-mint LP seed allocation (50% of total supply) to this contract.
if (poolSeedAmount_ > 0) {
_mint(address(this), poolSeedAmount_);
}
}
// ===== Metadata =====
function decimals() public pure override returns (uint8) {
return 8;
}
function TOKENS_PER_MINT() public view returns (uint256) {
return _tokensPerMint;
}
function MAX_MINTS() public view returns (uint256) {
return _maxMints;
}
function PAYMENT_PER_MINT() public view returns (uint256) {
return _paymentPerMint;
}
// ===== Mint Escrow =====
function fundMint(address recipient, address negotiator) external nonReentrant returns (uint256 mintId) {
if (mintCount >= _maxMints) revert MaxMintsReached();
address resolvedRecipient = recipient == address(0) ? msg.sender : recipient;
address resolvedNegotiator = negotiator == address(0) ? msg.sender : negotiator;
mintId = nextMintId++;
mintDeposits[mintId] = MintDeposit({
funder: msg.sender,
negotiator: resolvedNegotiator,
recipient: resolvedRecipient,
status: MintDepositStatus.Funded
});
uint256 balanceBefore = IERC20(paymentToken).balanceOf(address(this));
IERC20(paymentToken).safeTransferFrom(msg.sender, address(this), _paymentPerMint);
uint256 received = IERC20(paymentToken).balanceOf(address(this)) - balanceBefore;
if (received != _paymentPerMint) revert InvalidPaymentAmount(_paymentPerMint, received);
emit MintFunded(mintId, msg.sender, resolvedNegotiator, resolvedRecipient, _paymentPerMint);
}
function withdrawMintDeposit(uint256 mintId) external nonReentrant {
MintDeposit storage deposit = mintDeposits[mintId];
if (deposit.status != MintDepositStatus.Funded) revert MintDepositNotFunded(mintId);
if (msg.sender != deposit.funder && msg.sender != deposit.negotiator) {
revert NotMintDepositWithdrawer(msg.sender, deposit.funder, deposit.negotiator);
}
deposit.status = MintDepositStatus.Withdrawn;
IERC20(paymentToken).safeTransfer(deposit.funder, _paymentPerMint);
emit MintWithdrawn(mintId, deposit.funder, msg.sender, _paymentPerMint);
}
function completeMint(uint256 mintId, uint16 factorBps, uint256 deadline, address signer, bytes calldata signature)
external
nonReentrant
returns (uint256 tokenAmount)
{
if (mintCount >= _maxMints) revert MaxMintsReached();
MintDeposit storage deposit = mintDeposits[mintId];
if (deposit.status != MintDepositStatus.Funded) revert MintDepositNotFunded(mintId);
if (msg.sender != deposit.negotiator) revert NotMintNegotiator(msg.sender, deposit.negotiator);
if (factorBps < MIN_MINT_FACTOR_BPS || factorBps > MAX_MINT_FACTOR_BPS) {
revert InvalidMintFactor(factorBps);
}
if (block.timestamp > deadline) revert MintAuthorizationExpired(deadline);
bytes32 digest = _mintAuthorizationDigest(mintId, deposit, factorBps, deadline);
if (!hasRole(MINT_SIGNER_ROLE, signer) || !SignatureChecker.isValidSignatureNow(signer, digest, signature)) {
revert InvalidMintAuthorization(signer);
}
deposit.status = MintDepositStatus.Completed;
mintCount += 1;
tokenAmount = _tokensPerMint * factorBps / BPS_DENOMINATOR;
uint256 trumpAccountAmount = _tokensPerMint - tokenAmount;
_mint(address(this), _tokensPerMint);
_transfer(address(this), deposit.recipient, tokenAmount);
trumpAccountTokenReserve += trumpAccountAmount;
emit MintCompleted(
mintId,
deposit.funder,
deposit.negotiator,
deposit.recipient,
tokenAmount,
trumpAccountAmount,
factorBps,
signer
);
if (mintCount == _maxMints) _initializePoolAndDeployLiquidity(DEFAULT_POOL_FEE, DEFAULT_POOL_TICK_SPACING);
}
function mintAuthorizationDigest(uint256 mintId, uint16 factorBps, uint256 deadline)
external
view
returns (bytes32)
{
MintDeposit storage deposit = mintDeposits[mintId];
if (deposit.status == MintDepositStatus.None) revert MintDepositNotFunded(mintId);
return _mintAuthorizationDigest(mintId, deposit, factorBps, deadline);
}
// ===== AccessControl-Gated Actions =====
function setInitialLiquidityGuardHook(address liquidityGuardHook_) external onlyRole(HOOK_SETTER_ROLE) {
if (liquidityGuardHook != address(0)) revert LiquidityGuardHookAlreadySet();
_setLiquidityGuardHook(liquidityGuardHook_);
_revokeRole(HOOK_SETTER_ROLE, msg.sender);
}
function setLiquidityGuardHook(address liquidityGuardHook_) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (liquidityDeployed) revert LiquidityAlreadyDeployed();
_setLiquidityGuardHook(liquidityGuardHook_);
}
function _setLiquidityGuardHook(address liquidityGuardHook_) internal {
if (liquidityGuardHook_ == address(0)) revert InvalidAddress();
liquidityGuardHook = liquidityGuardHook_;
emit LiquidityGuardHookSet(liquidityGuardHook_);
}
function collectLpFees() external onlyRole(LP_MANAGER_ROLE) nonReentrant {
if (!liquidityDeployed) revert LpNotInitialized();
if (lpPositionClaimed) revert LpPositionAlreadyClaimed();
if (block.timestamp >= lpUnlockTime) revert ContractFeeClaimWindowClosed();
uint256 tokenId = lpTokenId;
(PositionPoolKey memory poolKey,) = positionManager.getPoolAndPositionInfo(tokenId);
bytes[] memory params = new bytes[](2);
params[0] = abi.encode(tokenId, uint256(0), uint128(0), uint128(0), bytes(""));
params[1] = abi.encode(poolKey.currency0, poolKey.currency1, msg.sender);
positionManager.modifyLiquidities(
abi.encode(abi.encodePacked(uint8(Actions.DECREASE_LIQUIDITY), uint8(Actions.TAKE_PAIR)), params),
block.timestamp + 1 hours
);
emit LpFeesCollected(msg.sender, tokenId);
}
function claimLpPosition() external onlyRole(LP_MANAGER_ROLE) nonReentrant {
if (!liquidityDeployed) revert LpNotInitialized();
if (lpPositionClaimed) revert LpPositionAlreadyClaimed();
if (block.timestamp < lpUnlockTime) revert LpPositionLocked(lpUnlockTime);
uint256 tokenId = lpTokenId;
lpPositionClaimed = true;
IERC721(address(positionManager)).safeTransferFrom(address(this), msg.sender, tokenId);
emit LpPositionClaimed(msg.sender, tokenId);
}
function withdrawTrumpAccountTokens(address recipient, uint256 amount)
external
onlyRole(TRUMP_ACCOUNT_WITHDRAWER_ROLE)
nonReentrant
{
if (recipient == address(0)) revert InvalidAddress();
uint256 reserve = trumpAccountTokenReserve;
if (amount > reserve) revert InsufficientTrumpAccountReserve(reserve, amount);
trumpAccountTokenReserve = reserve - amount;
_transfer(address(this), recipient, amount);
emit TrumpAccountTokensWithdrawn(recipient, amount);
}
function emergencyWithdrawToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) nonReentrant {
IERC20(token).safeTransfer(msg.sender, amount);
}
function emergencyWithdrawNative(uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) nonReentrant {
(bool ok,) = payable(msg.sender).call{value: amount}("");
if (!ok) revert NativeTransferFailed();
}
// ===== Internal Logic =====
function _mintAuthorizationDigest(uint256 mintId, MintDeposit storage deposit, uint16 factorBps, uint256 deadline)
internal
view
returns (bytes32)
{
return _hashTypedDataV4(
keccak256(
abi.encode(
MINT_AUTHORIZATION_TYPEHASH,
mintId,
deposit.funder,
deposit.negotiator,
deposit.recipient,
factorBps,
deadline
)
)
);
}
function _initializePoolAndDeployLiquidity(uint24 fee, int24 tickSpacing) internal {
if (liquidityDeployed) revert LiquidityAlreadyDeployed();
if (liquidityGuardHook == address(0)) revert InvalidAddress();
(address token0, address token1, uint160 sqrtPriceX96) = _sortedTokenData();
PoolKey memory poolKey = PoolKey({
currency0: Currency.wrap(token0),
currency1: Currency.wrap(token1),
fee: fee,
tickSpacing: tickSpacing,
hooks: IHooks(liquidityGuardHook)
});
try poolManager.initialize(poolKey, sqrtPriceX96) returns (int24) {}
catch {
revert PoolInitializationFailed();
}
uint256 amountPayment = paymentSeed;
uint256 seedAmount = poolSeedAmount;
(uint128 amount0Max, uint128 amount1Max, uint128 liquidity) =
_calculateMintParams(poolKey, amountPayment, seedAmount);
(int24 tickLower, int24 tickUpper) = _fullRangeTicks(tickSpacing);
IERC20(paymentToken).forceApprove(address(permit2), amountPayment);
IERC20(address(this)).forceApprove(address(permit2), seedAmount);
permit2.approve(paymentToken, address(positionManager), SafeCast.toUint160(amountPayment), type(uint48).max);
permit2.approve(address(this), address(positionManager), SafeCast.toUint160(seedAmount), type(uint48).max);
bytes[] memory params = new bytes[](2);
params[0] =
abi.encode(poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, address(this), bytes(""));
params[1] = abi.encode(poolKey.currency0, poolKey.currency1);
lpTokenId = positionManager.nextTokenId();
positionManager.modifyLiquidities(
abi.encode(abi.encodePacked(uint8(Actions.MINT_POSITION), uint8(Actions.SETTLE_PAIR)), params),
block.timestamp
);
liquidityDeployed = true;
lpUnlockTime = block.timestamp + LP_LOCK_DURATION;
emit LiquidityDeployed(lpTokenId, liquidity);
}
function _calculateMintParams(PoolKey memory poolKey, uint256 amountPaymentToken, uint256 amountAgentCoin)
internal
view
returns (uint128 amount0Max, uint128 amount1Max, uint128 liquidity)
{
uint256 amount0;
uint256 amount1;
if (paymentToken < address(this)) {
amount0 = amountPaymentToken;
amount1 = amountAgentCoin;
} else {
amount0 = amountAgentCoin;
amount1 = amountPaymentToken;
}
amount0Max = SafeCast.toUint128(amount0);
amount1Max = SafeCast.toUint128(amount1);
(int24 tickLower, int24 tickUpper) = _fullRangeTicks(poolKey.tickSpacing);
liquidity = LiquidityAmounts.getLiquidityForAmounts(
SafeCast.toUint160(paymentToken < address(this) ? _sqrtPricePaymentTokenFirst : _sqrtPriceAgentCoinFirst),
TickMath.getSqrtPriceAtTick(tickLower),
TickMath.getSqrtPriceAtTick(tickUpper),
amount0,
amount1
);
}
function _fullRangeTicks(int24 tickSpacing) internal pure returns (int24 tickLower, int24 tickUpper) {
tickLower = (TickMath.MIN_TICK / tickSpacing) * tickSpacing;
if (tickLower < TickMath.MIN_TICK) {
tickLower += tickSpacing;
}
tickUpper = (TickMath.MAX_TICK / tickSpacing) * tickSpacing;
if (tickUpper > TickMath.MAX_TICK) {
tickUpper -= tickSpacing;
}
}
function _sortedTokenData() internal view returns (address token0, address token1, uint160 sqrtPriceX96) {
if (paymentToken < address(this)) {
token0 = paymentToken;
token1 = address(this);
sqrtPriceX96 = _sqrtPricePaymentTokenFirst;
} else {
token0 = address(this);
token1 = paymentToken;
sqrtPriceX96 = _sqrtPriceAgentCoinFirst;
}
}
}
Chain explorer1522msChain node102ms