TokenFactory

0xb94f65b2a32a5fe9099dd8823f0daf4939b0d0ad

Verification
Verified
v0.8.24+commit.e11b9ed9
Type
Contract
2,804 bytes
ABI entries
20
6 read · 6 write
License
none

Contract information

Address
0xb94f65b2a32a5fe9099dd8823f0daf4939b0d0ad
Chain
Robinhood Chain (4663)
Compiler
v0.8.24+commit.e11b9ed9
Optimization
Enabled
Creation tx
0xd25e4b1af6…c9dececb6f

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (6)

feeTo()address
getTokenCount(address)uint256
getTokensByCreator(address)address[]
owner()address
tierFees(uint256)uint256
tokensByCreator(address, uint256)address

Events (4)

FeeToUpdatedOwnershipTransferredTierFeeUpdatedTokenCreated

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_feeTo",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "OwnableInvalidOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "OwnableUnauthorizedAccount",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "ReentrancyGuardReentrantCall",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "oldFeeTo",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "newFeeTo",
        "type": "address"
      }
    ],
    "name": "FeeToUpdated",
    "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": false,
        "internalType": "uint256",
        "name": "tier",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "oldFee",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newFee",
        "type": "uint256"
      }
    ],
    "name": "TierFeeUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "creator",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tier",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "features",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      }
    ],
    "name": "TokenCreated",
    "type": "event"
  },
  {
    "inputs": [
      {
        "internalType": "bytes",
        "name": "bytecode",
        "type": "bytes"
      },
      {
        "internalType": "uint256",
        "name": "tier",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "features",
        "type": "uint256"
      },
      {
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      }
    ],
    "name": "createToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "feeTo",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "creator",
        "type": "address"
      }
    ],
    "name": "getTokenCount",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "creator",
        "type": "address"
      }
    ],
    "name": "getTokensByCreator",
    "outputs": [
      {
        "internalType": "address[]",
        "name": "",
        "type": "address[]"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newFeeTo",
        "type": "address"
      }
    ],
    "name": "setFeeTo",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tier",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "newFee",
        "type": "uint256"
      }
    ],
    "name": "setTierFee",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "tierFees",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "tokensByCreator",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "withdraw",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

/**
 * @title Tokenry.tools TokenFactory
 * @notice Factory contract for deploying token contracts with tiered pricing
 */
contract TokenFactory is Ownable, ReentrancyGuard {
    /// @notice Mapping from creator to list of token addresses
    mapping(address => address[]) public tokensByCreator;
    
    /// @notice Fee recipient address
    address public feeTo;
    
    /// @notice Mapping of Tier ID => Cost in native currency (wei)
    /// @dev 0 = Basic, 1 = Advanced
    mapping(uint256 => uint256) public tierFees;
    
    /// @notice Event emitted when a token is created
    event TokenCreated(
        address indexed creator,
        address indexed token,
        uint256 tier,
        uint256 features,
        string name,
        string symbol
    );
    
    /// @notice Event emitted when a tier fee is updated
    event TierFeeUpdated(uint256 tier, uint256 oldFee, uint256 newFee);
    
    /// @notice Event emitted when fee recipient is updated
    event FeeToUpdated(address oldFeeTo, address newFeeTo);
    
    /**
     * @param _feeTo Address to receive creation fees
     */
    constructor(address _feeTo) Ownable(msg.sender) {
        require(_feeTo != address(0), "TokenFactory: invalid fee recipient");
        feeTo = _feeTo;
        
        // Initialize Default Prices (in wei)
        tierFees[0] = 1000000000000000; // Basic: 0.001 native currency
        tierFees[1] = 3000000000000000; // Advanced: 0.003 native currency
    }
    
    /**
     * @notice Create a new token contract
     * @param bytecode The bytecode of the token contract to deploy
     * @param tier The pricing tier (0 for Basic, 1 for Advanced)
     * @param features Feature bitmask (for UI/Indexing purposes)
     * @param name Token name
     * @param symbol Token symbol
     * @return token Address of the deployed token contract
     */
    function createToken(
        bytes memory bytecode,
        uint256 tier,
        uint256 features,
        string memory name,
        string memory symbol
    ) external payable nonReentrant returns (address token) {
        uint256 requiredFee = tierFees[tier];
        
        // Ensure the tier exists/has a price set (prevents free deployments on accidental high tiers)
        require(requiredFee > 0, "TokenFactory: invalid or disabled tier");
        require(msg.value >= requiredFee, "TokenFactory: insufficient fee for this tier");
        require(bytecode.length > 0, "TokenFactory: empty bytecode");
        
        assembly {
            token := create(0, add(bytecode, 0x20), mload(bytecode))
        }
        
        require(token != address(0), "TokenFactory: deployment failed");
        
        tokensByCreator[msg.sender].push(token);
        
        if (msg.value > 0) {
            (bool success, ) = feeTo.call{value: msg.value}("");
            require(success, "TokenFactory: fee transfer failed");
        }
        
        // Emit tier so the UI knows which dashboard to load
        emit TokenCreated(msg.sender, token, tier, features, name, symbol);
        
        return token;
    }
    
    /**
     * @notice Get all tokens created by an address
     * @param creator Address of the token creator
     * @return Array of token addresses
     */
    function getTokensByCreator(address creator) external view returns (address[] memory) {
        return tokensByCreator[creator];
    }
    
    /**
     * @notice Get token count for a creator
     * @param creator Address of the token creator
     * @return Number of tokens created
     */
    function getTokenCount(address creator) external view returns (uint256) {
        return tokensByCreator[creator].length;
    }
    
    /**
     * @notice Update the fee for a specific tier (owner only)
     * @param tier The tier ID (0 or 1)
     * @param newFee New creation fee in native currency (wei)
     */
    function setTierFee(uint256 tier, uint256 newFee) external onlyOwner {
        uint256 oldFee = tierFees[tier];
        tierFees[tier] = newFee;
        emit TierFeeUpdated(tier, oldFee, newFee);
    }
    
    /**
     * @notice Update the fee recipient (owner only)
     * @param newFeeTo New fee recipient address
     */
    function setFeeTo(address newFeeTo) external onlyOwner {
        require(newFeeTo != address(0), "TokenFactory: invalid fee recipient");
        address oldFeeTo = feeTo;
        feeTo = newFeeTo;
        emit FeeToUpdated(oldFeeTo, newFeeTo);
    }
    
    /**
     * @notice Withdraw any native currency accidentally sent to this contract (owner only)
     */
    function withdraw() external onlyOwner {
        (bool success, ) = owner().call{value: address(this).balance}("");
        require(success, "TokenFactory: withdraw failed");
    }
}

Chain explorer3124msChain node71ms