TokenDeployerV3

0x0189676b98c45abe9fbe7fcb9ec316686238efd6

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
14,353 bytes
ABI entries
6
3 read · 2 write
License
none

Contract information

Address
0x0189676b98c45abe9fbe7fcb9ec316686238efd6
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0x82e0dda701…1105fd6e1f

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (3)

deployer()address
factory()address
usdg()address

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "usdg_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "internalType": "address",
        "name": "treasury",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "supplyWhole",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "poolManager",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "positionManager",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "universalRouter",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "saltSeed",
        "type": "uint256"
      }
    ],
    "name": "deploy",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "deployer",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "factory",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "f",
        "type": "address"
      }
    ],
    "name": "setFactory",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "usdg",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

Source code

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

/*  Deploys a FlowTokenV3 whose address is MINED to sort ABOVE USDG (via CREATE2) so USDG is currency0
    in the V4 pool — the slot native ETH held for free in v2. Keeps the factory under the 24KB limit by
    carrying the token creation bytecode here. Launchpad tokens are always `restricted` (locked setters).  */
import {FlowTokenV3} from "./FlowTokenV3.sol";

contract TokenDeployerV3 {
    address public immutable deployer; // the EOA/bundle that deployed this — only it wires the factory
    address public immutable usdg;     // the quote currency the token must sort above
    address public factory;            // only the factory may deploy (set once)

    constructor(address usdg_) {
        require(usdg_ != address(0), "zero");
        deployer = msg.sender;
        usdg = usdg_;
    }

    function setFactory(address f) external {
        require(msg.sender == deployer, "not deployer");
        require(factory == address(0) && f != address(0), "set");
        factory = f;
    }

    function deploy(
        string calldata name, string calldata symbol, address treasury, uint256 supplyWhole,
        address poolManager, address positionManager, address universalRouter, address to, uint256 saltSeed
    ) external returns (address) {
        require(msg.sender == factory, "only factory");

        bytes memory args = abi.encode(name, symbol, treasury, supplyWhole, usdg, true, poolManager, positionManager, universalRouter);
        bytes32 initHash = keccak256(abi.encodePacked(type(FlowTokenV3).creationCode, args));

        // Mine a salt whose CREATE2 address sorts above USDG so USDG is currency0 (~1–2 tries; USDG ~0x5f…).
        // The salt is keyed by `saltSeed` (the factory's global launch counter) so re-using an identical
        // (name,symbol,creator) mines a DIFFERENT address instead of colliding with the prior token.
        bytes32 salt;
        address predicted;
        unchecked {
            for (uint256 i = 0; ; ++i) {
                salt = keccak256(abi.encodePacked(saltSeed, i));
                predicted = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, initHash)))));
                if (uint160(predicted) > uint160(usdg)) break;
            }
        }

        FlowTokenV3 t = new FlowTokenV3{salt: salt}(
            name, symbol, treasury, supplyWhole, usdg, true, poolManager, positionManager, universalRouter
        );
        require(address(t) == predicted, "create2"); // creationCode must match the mined preimage

        // the deployer is fee-exempt on the fresh token → move the full supply + ownership to the factory
        t.transfer(to, t.balanceOf(address(this)));
        t.transferOwnership(to);
        return address(t);
    }
}
Chain explorer5750msChain node85ms