QuiverV4HookDeployer

0x69a4415006d8cd32273d5bac1d62d2b2e196d854

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
11,033 bytes
ABI entries
2
0 read · 2 write
License
none

Contract information

Address
0x69a4415006d8cd32273d5bac1d62d2b2e196d854
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0xcf781e5a39…98008f1005

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (0)

No read functions

The ABI is unavailable or exposes no view functions.

ABI

[
  {
    "inputs": [
      {
        "internalType": "contract QuiverV4Hook",
        "name": "hook",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "launcher",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "finalOwner",
        "type": "address"
      }
    ],
    "name": "configure",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "salt",
        "type": "bytes32"
      },
      {
        "internalType": "address",
        "name": "poolManager",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "positionManager",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "universalRouter",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "quoter",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "gate",
        "type": "address"
      }
    ],
    "name": "deploy",
    "outputs": [
      {
        "internalType": "contract QuiverV4Hook",
        "name": "hook",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

Source code

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

import { Script, console } from "forge-std/Script.sol";
import { QuiverV4Gate } from "../src/QuiverV4Gate.sol";
import { QuiverV4Hook } from "../src/QuiverV4Hook.sol";
import { QuiverV4PermaLock } from "../src/QuiverV4PermaLock.sol";
import { QuiverV4Launcher } from "../src/QuiverV4Launcher.sol";

contract QuiverV4HookDeployer {
    function deploy(
        bytes32 salt,
        address poolManager,
        address positionManager,
        address universalRouter,
        address quoter,
        address gate
    ) external returns (QuiverV4Hook hook) {
        hook = new QuiverV4Hook{ salt: salt }(poolManager, positionManager, universalRouter, quoter, gate);
    }

    function configure(QuiverV4Hook hook, address launcher, address finalOwner) external {
        hook.setLauncher(launcher);
        if (finalOwner != address(0)) hook.transferOwnership(finalOwner);
    }
}

/// @notice Robinhood mainnet/fork deployment script. It does not broadcast unless explicitly invoked with --broadcast.
contract DeployV2 is Script {
    address internal constant POOL_MANAGER = 0x8366a39CC670B4001A1121B8F6A443A643e40951;
    address internal constant POSITION_MANAGER = 0x58daec3116aae6D93017bAAea7749052E8a04fA7;
    address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
    address internal constant WETH9 = 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73;
    address internal constant V4_QUOTER = 0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94;
    // Latest canonical Robinhood deployment registry address, verified against poolManager() before deployment.
    address internal constant UNIVERSAL_ROUTER = 0x06AfBA43Fd06227fA663b0DAecF536f6EaA6bf99;

    address internal constant TREASURY = 0x5B274D7675A5e7ceac443Fc3169fe901c4a555D4;
    address internal constant OWNER_MAINNET = 0x7De8473b75BD562DDB33DD7d0731987127330304;
    address internal constant OWNER_TESTNET = 0xaB526563d1c43F5E63f431D2eb0ab253E46D79D1;
    uint256 internal constant MAINNET_CHAIN_ID = 4663;
    uint256 internal constant TESTNET_FORK_CHAIN_ID = 44663;
    uint160 internal constant REQUIRED_FLAGS = 0x2880;
    uint160 internal constant ALL_HOOK_MASK = (1 << 14) - 1;

    function run() external {
        require(
            block.chainid == MAINNET_CHAIN_ID || block.chainid == TESTNET_FORK_CHAIN_ID,
            "expected Robinhood mainnet or local fork"
        );
        address gatekeeper = vm.envAddress("GATEKEEPER_ADDRESS");
        uint256 platformFee = vm.envOr("PLATFORM_FEE_BPS", uint256(2_000));
        require(platformFee <= 2_500, "platform fee exceeds 25%");
        address finalOwner = block.chainid == MAINNET_CHAIN_ID ? OWNER_MAINNET : OWNER_TESTNET;

        vm.startBroadcast();
        QuiverV4Gate gate = new QuiverV4Gate(UNIVERSAL_ROUTER, WETH9, gatekeeper);
        QuiverV4PermaLock permaLock = new QuiverV4PermaLock(POSITION_MANAGER, TREASURY, uint16(platformFee));
        QuiverV4HookDeployer hookDeployer = new QuiverV4HookDeployer();
        bytes32 salt = _mineHookSalt(address(hookDeployer), address(gate));
        QuiverV4Hook hook =
            hookDeployer.deploy(salt, POOL_MANAGER, POSITION_MANAGER, UNIVERSAL_ROUTER, V4_QUOTER, address(gate));
        QuiverV4Launcher launcher = new QuiverV4Launcher(
            POOL_MANAGER,
            POSITION_MANAGER,
            PERMIT2,
            address(hook),
            address(gate),
            address(permaLock),
            UNIVERSAL_ROUTER,
            WETH9
        );
        hookDeployer.configure(hook, address(launcher), finalOwner);
        gate.setLauncher(address(launcher));
        gate.setHook(address(hook));

        if (finalOwner != address(0)) {
            gate.transferOwnership(finalOwner);
            permaLock.transferOwnership(finalOwner);
            launcher.transferOwnership(finalOwner);
        }
        vm.stopBroadcast();

        console.log("QuiverV4Hook:", address(hook));
        console.log("QuiverV4Gate:", address(gate));
        console.log("QuiverV4PermaLock:", address(permaLock));
        console.log("QuiverV4Launcher:", address(launcher));
        console.logBytes32(salt);
    }

    function _mineHookSalt(address deployer, address gate) private pure returns (bytes32 salt) {
        bytes32 initCodeHash = keccak256(
            abi.encodePacked(
                type(QuiverV4Hook).creationCode,
                abi.encode(POOL_MANAGER, POSITION_MANAGER, UNIVERSAL_ROUTER, V4_QUOTER, gate)
            )
        );
        for (uint256 i; i < 1_000_000; ++i) {
            salt = bytes32(i);
            address predicted =
                address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initCodeHash)))));
            if ((uint160(predicted) & ALL_HOOK_MASK) == REQUIRED_FLAGS) return salt;
        }
        revert("hook salt not found");
    }
}
Chain explorer4076msChain node89ms