FlowrToken
0x31ef2f4e678b3640a380c5882ae1a73763d138e9
Verification
Verified
v0.8.20+commit.a1b79de6
Type
Contract
3,254 bytes
ABI entries
40
12 read · 10 write
License
none
Contract information
- Address
- 0x31ef2f4e678b3640a380c5882ae1a73763d138e9
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.20+commit.a1b79de6
- Optimization
- Enabled
- Creator
- 0x04B0aA623A…7fD97AbD14
- Creation tx
- 0xfb33826e0c…be8c88cb37
Token
- Name
- flowr
- Symbol
- FLOWR
- Decimals
- 18
- Holders
- 335
- Market
- View token page →
Read contract (12)
GARDEN_TIMELOCK() → uint256
MAX_SUPPLY() → uint256
allowance(address, address) → uint256
balanceOf(address) → uint256
decimals() → uint8
garden() → address
name() → string
owner() → address
pendingGarden() → address
pendingGardenTimestamp() → uint256
symbol() → string
totalSupply() → uint256
Events (6)
ApprovalGardenChangeQueuedGardenChangedGardenSetOwnershipTransferredTransfer
ABI
[
{
"inputs": [
{
"internalType": "uint256",
"name": "_initialMint",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"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": "MaxSupplyExceeded",
"type": "error"
},
{
"inputs": [],
"name": "OnlyGarden",
"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": "ZeroAddress",
"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": [
{
"indexed": true,
"internalType": "address",
"name": "newGarden",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "executeAfter",
"type": "uint256"
}
],
"name": "GardenChangeQueued",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "oldGarden",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newGarden",
"type": "address"
}
],
"name": "GardenChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "garden",
"type": "address"
}
],
"name": "GardenSet",
"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": "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"
},
{
"inputs": [],
"name": "GARDEN_TIMELOCK",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"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": "_amount",
"type": "uint256"
}
],
"name": "burn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "executeSetGarden",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "garden",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pendingGarden",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pendingGardenTimestamp",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_garden",
"type": "address"
}
],
"name": "queueSetGarden",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_garden",
"type": "address"
}
],
"name": "setGarden",
"outputs": [],
"stateMutability": "nonpayable",
"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"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/// @title FlowrToken
/// @notice ERC-20 token for flowr ($FLOWR). Only the designated garden contract can mint,
/// up to MAX_SUPPLY (owner 2026-07-08: 5,250,000 total — 262,500 initial mint (5%,
/// source-ratio) + 4,987,500 mineable through the garden).
contract FlowrToken is ERC20, Ownable {
uint256 public constant MAX_SUPPLY = 5_250_000 ether;
uint256 public constant GARDEN_TIMELOCK = 48 hours;
address public garden;
address public pendingGarden;
uint256 public pendingGardenTimestamp;
event GardenSet(address indexed garden);
event GardenChangeQueued(address indexed newGarden, uint256 executeAfter);
event GardenChanged(address indexed oldGarden, address indexed newGarden);
error OnlyGarden();
error MaxSupplyExceeded();
error ZeroAddress();
constructor(uint256 _initialMint) ERC20("flowr", "FLOWR") Ownable(msg.sender) {
if (_initialMint > MAX_SUPPLY) revert MaxSupplyExceeded();
_mint(msg.sender, _initialMint);
}
/// @notice Initial garden setup — only works when the garden is not yet set
function setGarden(address _garden) external onlyOwner {
require(garden == address(0), "Use queueSetGarden");
if (_garden == address(0)) revert ZeroAddress();
garden = _garden;
emit GardenSet(_garden);
}
/// @notice Queue a garden change (48h timelock)
function queueSetGarden(address _garden) external onlyOwner {
if (_garden == address(0)) revert ZeroAddress();
pendingGarden = _garden;
pendingGardenTimestamp = block.timestamp + GARDEN_TIMELOCK;
emit GardenChangeQueued(_garden, pendingGardenTimestamp);
}
/// @notice Execute queued garden change after timelock
function executeSetGarden() external onlyOwner {
require(pendingGarden != address(0), "No pending garden");
require(block.timestamp >= pendingGardenTimestamp, "Timelock not expired");
address old = garden;
garden = pendingGarden;
pendingGarden = address(0);
emit GardenChanged(old, garden);
}
function mint(address _to, uint256 _amount) external {
if (msg.sender != garden) revert OnlyGarden();
if (totalSupply() + _amount > MAX_SUPPLY) revert MaxSupplyExceeded();
_mint(_to, _amount);
}
function burn(uint256 _amount) external {
_burn(msg.sender, _amount);
}
}
Chain explorer3605msChain node70ms