ETH Price: $1,824.39 (-3.22%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create232670842025-09-01 8:27:23175 days ago1756715243IN
0xDC9718E7...cd14C20AA
0 ETH0.000155080.70208974
Create231863052025-08-21 1:54:35187 days ago1755741275IN
0xDC9718E7...cd14C20AA
0 ETH0.000205490.2335105
Create231735712025-08-19 7:17:35189 days ago1755587855IN
0xDC9718E7...cd14C20AA
0 ETH0.000168490.16035703
Create231458652025-08-15 10:33:59192 days ago1755254039IN
0xDC9718E7...cd14C20AA
0 ETH0.000317521.43744962
Create231387652025-08-14 10:43:11193 days ago1755168191IN
0xDC9718E7...cd14C20AA
0 ETH0.00163761.8608925
Create231134542025-08-10 21:51:11197 days ago1754862671IN
0xDC9718E7...cd14C20AA
0 ETH0.000226220.25060238
Create230894682025-08-07 13:25:47200 days ago1754573147IN
0xDC9718E7...cd14C20AA
0 ETH0.001609811.41656374
Create230883352025-08-07 9:37:35200 days ago1754559455IN
0xDC9718E7...cd14C20AA
0 ETH0.000106690.47736482
Create230879382025-08-07 8:17:59200 days ago1754554679IN
0xDC9718E7...cd14C20AA
0 ETH0.00048190.49287283
Create230869342025-08-07 4:55:59201 days ago1754542559IN
0xDC9718E7...cd14C20AA
0 ETH0.000143340.16299645
Create230865142025-08-07 3:31:47201 days ago1754537507IN
0xDC9718E7...cd14C20AA
0 ETH0.000192870.21932534
Create230864792025-08-07 3:24:47201 days ago1754537087IN
0xDC9718E7...cd14C20AA
0 ETH0.000184890.20730581
Create230734752025-08-05 7:49:35202 days ago1754380175IN
0xDC9718E7...cd14C20AA
0 ETH0.000205960.93238631
Sync Extra Rewar...230463262025-08-01 12:47:23206 days ago1754052443IN
0xDC9718E7...cd14C20AA
0 ETH0.00034531.92165233
Create230012482025-07-26 5:32:23213 days ago1753507943IN
0xDC9718E7...cd14C20AA
0 ETH0.00029540.33568768
Create229978242025-07-25 18:03:59213 days ago1753466639IN
0xDC9718E7...cd14C20AA
0 ETH0.000295640.28325893
Create229651242025-07-21 4:17:35218 days ago1753071455IN
0xDC9718E7...cd14C20AA
0 ETH0.000207520.6709101
Create229510342025-07-19 5:02:11220 days ago1752901331IN
0xDC9718E7...cd14C20AA
0 ETH0.000241151.09170973
Create229381282025-07-17 9:48:59221 days ago1752745739IN
0xDC9718E7...cd14C20AA
0 ETH0.005307936.03572719
Create229171112025-07-14 11:26:47224 days ago1752492407IN
0xDC9718E7...cd14C20AA
0 ETH0.002746533.12103424
Create229025342025-07-12 10:37:11226 days ago1752316631IN
0xDC9718E7...cd14C20AA
0 ETH0.00016280.73701175
Create228962092025-07-11 13:23:35227 days ago1752240215IN
0xDC9718E7...cd14C20AA
0 ETH0.004664045.3
Create228906102025-07-10 18:36:35228 days ago1752172595IN
0xDC9718E7...cd14C20AA
0 ETH0.007468858.48724508
Create228872922025-07-10 7:29:35228 days ago1752132575IN
0xDC9718E7...cd14C20AA
0 ETH0.003968464.51259724
Create228872802025-07-10 7:27:11228 days ago1752132431IN
0xDC9718E7...cd14C20AA
0 ETH0.004059714.61326112
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x6100a03d231863052025-08-21 1:54:35187 days ago1755741275
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81231863052025-08-21 1:54:35187 days ago1755741275
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d231735712025-08-19 7:17:35189 days ago1755587855
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81231735712025-08-19 7:17:35189 days ago1755587855
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d231387652025-08-14 10:43:11193 days ago1755168191
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81231387652025-08-14 10:43:11193 days ago1755168191
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d231134542025-08-10 21:51:11197 days ago1754862671
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81231134542025-08-10 21:51:11197 days ago1754862671
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d230894682025-08-07 13:25:47200 days ago1754573147
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81230894682025-08-07 13:25:47200 days ago1754573147
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d230879382025-08-07 8:17:59200 days ago1754554679
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81230879382025-08-07 8:17:59200 days ago1754554679
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d230869342025-08-07 4:55:59201 days ago1754542559
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81230869342025-08-07 4:55:59201 days ago1754542559
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d230865142025-08-07 3:31:47201 days ago1754537507
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81230865142025-08-07 3:31:47201 days ago1754537507
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d230864792025-08-07 3:24:47201 days ago1754537087
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81230864792025-08-07 3:24:47201 days ago1754537087
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d230012482025-07-26 5:32:23213 days ago1753507943
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81230012482025-07-26 5:32:23213 days ago1753507943
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d229978242025-07-25 18:03:59213 days ago1753466639
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81229978242025-07-25 18:03:59213 days ago1753466639
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d229381282025-07-17 9:48:59221 days ago1752745739
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x602c3d81229381282025-07-17 9:48:59221 days ago1752745739
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
0x6100a03d229171112025-07-14 11:26:47224 days ago1752492407
0xDC9718E7...cd14C20AA
 Contract Creation0 ETH
View All Internal Transactions
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CRVPoolFactory

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;

import "src/base/factory/PoolFactory.sol";

import {IBooster} from "src/base/interfaces/IBooster.sol";
import {IConvexFactory} from "src/base/interfaces/IConvexFactory.sol";
import {IGaugeController} from "src/base/interfaces/IGaugeController.sol";

/// @notice Inherit from PoolFactory to deploy a pool compatible with CRV gauges and check if the token is a valid extra rewards to add.
contract CRVPoolFactory is PoolFactory {
    /// @notice Ve Funder is a special gauge not valid to be deployed as a pool.
    address public constant CVX = 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B;

    /// @notice Convex Booster.
    address public constant BOOSTER = 0xF403C135812408BFbE8713b5A23a04b3D48AAE31;

    /// @notice Ve Funder is a special gauge not valid to be deployed as a pool.
    address public constant VE_FUNDER = 0xbAF05d7aa4129CA14eC45cC9d4103a9aB9A9fF60;

    /// @notice Convex Minimal Proxy Factory for Only Boost.
    address public constant CONVEX_MINIMAL_PROXY_FACTORY = 0x4E795A6f991e305e3f28A3b1b2B4B9789d2CD5A1;

    /// @notice Curve Gauge Controller.
    IGaugeController public constant GAUGE_CONTROLLER = IGaugeController(0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB);

    /// @notice Event emitted when a pool is deployed with Only Boost.
    event PoolDeployed(address vault, address rewardDistributor, address lp, address gauge, address stakingConvex);

    constructor(
        address _strategy,
        address _rewardToken,
        address _vaultImplementation,
        address _liquidityGaugeImplementation,
        address _rewardReceiverImplementation
    )
        PoolFactory(
            _strategy,
            _rewardToken,
            _vaultImplementation,
            _liquidityGaugeImplementation,
            _rewardReceiverImplementation
        )
    {}

    /// @notice Create a new pool for a given pid on the Convex platform.
    /// @param _pid Pool id.
    /// @param _deployPool To deploy the pool.
    /// @param _deployConvex To deploy the convex staking.
    /// @return vault Address of the vault.
    /// @return rewardDistributor Address of the reward distributor.
    /// @return stakingConvex Address of the staking convex.
    function create(uint256 _pid, bool _deployPool, bool _deployConvex)
        external
        returns (address vault, address rewardDistributor, address stakingConvex)
    {
        (address _token,, address _gauge,,,) = IBooster(BOOSTER).poolInfo(_pid);

        if (_deployConvex) {
            stakingConvex = IConvexFactory(CONVEX_MINIMAL_PROXY_FACTORY).create(_token, _pid);
        }

        if (_deployPool) {
            /// Create Stake DAO pool.
            (vault, rewardDistributor) = _create(_gauge);

            emit PoolDeployed(vault, rewardDistributor, _token, _gauge, stakingConvex);
        } else {
            address _rewardDistributor = strategy.rewardDistributors(_gauge);

            /// We go through the execute function because if the pool is already deployed and have extra rewards,
            /// We do not want CVX be distributed by the Reward Receiver.
            /// Approve the reward distributor to spend the reward token.
            if (ERC20(CVX).allowance(address(strategy), _rewardDistributor) == 0) {
                strategy.execute(
                    CVX, 0, abi.encodeWithSignature("approve(address,uint256)", _rewardDistributor, type(uint256).max)
                );
            }

            /// Add CVX in the case where Only Boost is enabled.
            address distributor = ILiquidityGauge(_rewardDistributor).reward_data(CVX).distributor;
            if (distributor == address(0)) {
                strategy.execute(
                    _rewardDistributor,
                    0,
                    abi.encodeWithSignature("add_reward(address,address)", CVX, address(strategy))
                );
            }
        }
    }

    function syncExtraRewards(address _gauge) external {
        address _rewardDistributor = strategy.rewardDistributors(_gauge);
        if (_rewardDistributor == address(0)) return;

        _addExtraRewards(_gauge, _rewardDistributor);
    }

    /// @notice Add the main reward token to the reward distributor.
    /// @param _gauge Address of the _gauge.
    function _addRewardToken(address _gauge) internal override {
        /// The strategy should claim through the locker the reward token,
        /// and distribute it to the reward distributor every harvest.
        strategy.addRewardToken(_gauge, rewardToken);

        /// Add CVX in the case where Only Boost is enabled.
        strategy.addRewardToken(_gauge, CVX);
    }

    /// @inheritdoc PoolFactory
    function _isValidToken(address _token) internal view override returns (bool) {
        /// We can't add the reward token as extra reward.
        /// We can't add special pools like the Ve Funder.
        /// We can't add SDT as extra reward, as it's already added by default.
        /// We can't add CVX as extra reward, as it's already added by default.
        if (_token == rewardToken || _token == VE_FUNDER || _token == SDT || _token == CVX) return false;

        /// If the token is available as an inflation receiver, it's not valid.
        try GAUGE_CONTROLLER.gauge_types(_token) {
            return false;
        } catch {
            return true;
        }
    }

    /// inheritdoc PoolFactory
    function _isValidGauge(address _gauge) internal view override returns (bool) {
        bool isValid;
        /// Check if the gauge is a valid candidate and available as an inflation receiver.
        /// This call always reverts if the gauge is not valid.
        try GAUGE_CONTROLLER.gauge_types(_gauge) {
            isValid = true;
        } catch {
            return false;
        }

        /// Check if the gauge is not killed.
        /// Not all the pools, but most of them, have this function.
        try ILiquidityGauge(_gauge).is_killed() returns (bool isKilled) {
            if (isKilled) return false;
        } catch {}

        /// If the gauge doesn't support the is_killed function, but is unofficially killed, it can be deployed.
        return isValid;
    }
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;

import {ERC20} from "solady/tokens/ERC20.sol";
import {IVault} from "src/base/interfaces/IVault.sol";
import {LibClone} from "solady/utils/LibClone.sol";
import {IBooster} from "src/base/interfaces/IBooster.sol";

import {IStrategy} from "src/base/interfaces/IStrategy.sol";
import {IFallback} from "src/base/interfaces/IFallback.sol";
import {ILiquidityGauge} from "src/base/interfaces/ILiquidityGauge.sol";
import {ISDLiquidityGauge} from "src/base/interfaces/ISDLiquidityGauge.sol";

/// @notice Factory built to be compatible with CRV gauges but can be overidden to support other gauges/protocols.
abstract contract PoolFactory {
    using LibClone for address;

    /// @notice Denominator for fixed point math.
    uint256 public constant DENOMINATOR = 10_000;

    /// @notice Stake DAO strategy contract address.
    IStrategy public immutable strategy;

    /// @notice Reward token address.
    address public immutable rewardToken;

    /// @notice Staking Deposit implementation address.
    address public immutable vaultImplementation;

    /// @notice Reward Receiver implementation address.
    address public immutable rewardReceiverImplementation;

    /// @notice Liquidity Gauge implementation address.
    address public immutable liquidityGaugeImplementation;

    /// @notice Stake DAO token address.
    address public constant SDT = 0x73968b9a57c6E53d41345FD57a6E6ae27d6CDB2F;

    /// @notice Voting Escrow Stake DAO token address.
    address public constant VESDT = 0x0C30476f66034E11782938DF8e4384970B6c9e8a;

    /// @notice SDT VEBoost proxy address.
    address public constant VE_BOOST_PROXY = 0xD67bdBefF01Fc492f1864E61756E5FBB3f173506;

    /// @notice Claim helper contract address for LiquidityGauges.
    address public constant CLAIM_HELPER = 0x539e65190a371cE73244A98DEc42BA635cCa512c;

    /// @notice Stake DAO token distributor address.
    address public constant SDT_DISTRIBUTOR = 0x9C99dffC1De1AfF7E7C1F36fCdD49063A281e18C;

    /// @notice Throwed if the gauge is not valid candidate.
    error INVALID_GAUGE();

    /// @notice Throwed if the token is not valid.
    error INVALID_TOKEN();

    /// @notice Throwed if the gauge has been already used.
    error GAUGE_ALREADY_USED();

    /// @notice Emitted when a new pool is deployed.
    event PoolDeployed(address vault, address rewardDistributor, address token, address gauge);

    /// @notice Constructor.
    /// @param _strategy Address of the strategy contract. This contract should have the ability to add new reward tokens.
    /// @param _rewardToken Address of the main reward token.
    /// @param _vaultImplementation Address of the staking deposit implementation. Main entry point.
    /// @param _liquidityGaugeImplementation Address of the liquidity gauge implementation.
    constructor(
        address _strategy,
        address _rewardToken,
        address _vaultImplementation,
        address _liquidityGaugeImplementation,
        address _rewardReceiverImplementation
    ) {
        rewardToken = _rewardToken;
        strategy = IStrategy(_strategy);
        vaultImplementation = _vaultImplementation;
        liquidityGaugeImplementation = _liquidityGaugeImplementation;
        rewardReceiverImplementation = _rewardReceiverImplementation;
    }

    /// @notice Add new staking gauge to Stake DAO Locker.
    /// @param _gauge Address of the liquidity gauge.
    /// @return vault Address of the staking deposit.
    /// @return rewardDistributor Address of the reward distributor to claim rewards.
    function create(address _gauge) public virtual returns (address vault, address rewardDistributor) {
        return _create(_gauge);
    }

    /// @notice Add new staking gauge to Stake DAO Locker.
    function _create(address _gauge) internal returns (address vault, address rewardDistributor) {
        /// Perform checks on the gauge to make sure it's valid and can be used.
        if (!_isValidGauge(_gauge)) revert INVALID_GAUGE();

        /// Perform checks on the strategy to make sure it's not already used.
        if (strategy.rewardDistributors(_gauge) != address(0)) revert GAUGE_ALREADY_USED();

        /// Retrieve the staking token.
        address lp = _getGaugeStakingToken(_gauge);

        /// Clone the Reward Distributor.
        rewardDistributor = LibClone.clone(liquidityGaugeImplementation);

        /// We use the LP token and the gauge address as salt to generate the vault address.
        bytes32 salt = keccak256(abi.encodePacked(lp, _gauge));

        /// We use CWIA setup. We encode the LP token, the strategy address and the reward distributor address as data
        /// to be passed as immutable args to the vault.
        bytes memory vaultData = abi.encodePacked(lp, address(strategy), rewardDistributor);

        /// Clone the Vault.
        vault = vaultImplementation.cloneDeterministic(vaultData, salt);

        /// Retrieve the symbol to be used on the reward distributor.
        (, string memory _symbol) = _getNameAndSymbol(lp);

        /// Initialize the Reward Distributor.
        ISDLiquidityGauge(rewardDistributor).initialize(
            vault, address(this), SDT, VESDT, VE_BOOST_PROXY, SDT_DISTRIBUTOR, vault, _symbol
        );

        /// Initialize Vault.
        IVault(vault).initialize();

        /// Allow the vault to stake the LP token in the locker trough the strategy.
        strategy.toggleVault(vault);

        /// Map in the strategy the staking token to it's corresponding gauge.
        strategy.setGauge(lp, _gauge);

        /// Map the gauge to the reward distributor that should receive the rewards.
        strategy.setRewardDistributor(_gauge, rewardDistributor);

        /// Set ClaimHelper as claimer.
        ISDLiquidityGauge(rewardDistributor).set_claimer(CLAIM_HELPER);

        /// Transfer ownership of the reward distributor to the strategy.
        ISDLiquidityGauge(rewardDistributor).commit_transfer_ownership(address(strategy));

        /// Accept ownership of the reward distributor.
        strategy.acceptRewardDistributorOwnership(rewardDistributor);

        /// Add the reward token to the reward distributor.
        _addRewardToken(_gauge);

        /// Add extra rewards if any.
        _addExtraRewards(_gauge, rewardDistributor);

        emit PoolDeployed(vault, rewardDistributor, lp, _gauge);
    }

    /// @notice Add the main reward token to the reward distributor.
    /// @param _gauge Address of the gauge.
    function _addRewardToken(address _gauge) internal virtual {
        /// The strategy should claim through the locker the reward token,
        /// and distribute it to the reward distributor every harvest.
        strategy.addRewardToken(_gauge, rewardToken);
    }

    /// @notice Add extra reward tokens to the reward distributor.
    /// @param _gauge Address of the liquidity gauge.
    function _addExtraRewards(address _gauge, address _rewardDistributor) internal virtual {
        /// Check if the gauge supports extra rewards.
        /// This function is not supported on all gauges, depending on when they were deployed.
        bytes memory data = abi.encodeWithSignature("reward_tokens(uint256)", 0);

        /// Hence the call to the function is wrapped in a try catch.
        (bool success,) = _gauge.call(data);
        if (!success) {
            /// If it fails, we set the LGtype to 1 to indicate that the gauge doesn't support extra rewards.
            /// So the harvest would skip the extra rewards.
            strategy.setLGtype(_gauge, 1);

            return;
        }

        /// Loop through the extra reward tokens.
        /// 8 is the maximum number of extra reward tokens supported by the gauges.
        for (uint8 i = 0; i < 8;) {
            /// Get the extra reward token address.
            address _extraRewardToken = ISDLiquidityGauge(_gauge).reward_tokens(i);

            /// If the address is 0, it means there are no more extra reward tokens.
            if (_extraRewardToken == address(0)) break;

            /// Performs checks on the extra reward token.
            /// Checks like if the token is also an lp token that can be staked in the locker, these tokens are not supported.
            address distributor = ILiquidityGauge(_rewardDistributor).reward_data(_extraRewardToken).distributor;

            if (_isValidToken(_extraRewardToken) && distributor == address(0)) {
                /// Then we add the extra reward token to the reward distributor through the strategy.
                strategy.addRewardToken(_gauge, _extraRewardToken);
            }

            unchecked {
                ++i;
            }
        }
    }

    /// @notice Perform checks on the gauge to make sure it's valid and can be used.
    function _isValidGauge(address _gauge) internal view virtual returns (bool) {}

    /// @notice Perform checks on the token to make sure it's valid and can be used.
    function _isValidToken(address _token) internal view virtual returns (bool) {}

    /// @notice Retrieve the staking token from the gauge.
    /// @param _gauge Address of the liquidity gauge.
    function _getGaugeStakingToken(address _gauge) internal view virtual returns (address lp) {
        lp = ILiquidityGauge(_gauge).lp_token();
    }

    /// @notice Retrieve the name and symbol of the staking token.
    /// @param _lp Address of the staking token.
    function _getNameAndSymbol(address _lp) internal view virtual returns (string memory name, string memory symbol) {
        name = ERC20(_lp).name();
        symbol = ERC20(_lp).symbol();
    }
}

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.19;

interface IBooster {
    function poolLength() external view returns (uint256);

    function poolInfo(uint256 pid)
        external
        view
        returns (address lpToken, address token, address gauge, address crvRewards, address stash, bool shutdown);

    function deposit(uint256 _pid, uint256 _amount, bool _stake) external returns (bool);

    function earmarkRewards(uint256 _pid) external returns (bool);

    function depositAll(uint256 _pid, bool _stake) external returns (bool);

    function withdraw(uint256 _pid, uint256 _amount) external returns (bool);

    function claimRewards(uint256 _pid, address gauge) external returns (bool);
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;

interface IConvexFactory {
    function protocolFeesPercent() external view returns (uint256);
    function fallbacks(address gauge) external view returns (address);
    function create(address token, uint256 pid) external returns (address);
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;

interface IGaugeController {
    struct VotedSlope {
        uint256 slope;
        uint256 power;
        uint256 end;
    }

    function admin() external view returns (address);

    function gauges(uint256) external view returns (address);

    //solhint-disable-next-line
    function gauge_types(address addr) external view returns (int128);

    //solhint-disable-next-line
    function gauge_relative_weight_write(address addr, uint256 timestamp) external returns (uint256);

    //solhint-disable-next-line
    function gauge_relative_weight(address addr) external view returns (uint256);

    //solhint-disable-next-line
    function gauge_relative_weight(address addr, uint256 timestamp) external view returns (uint256);

    //solhint-disable-next-line
    function get_total_weight() external view returns (uint256);

    //solhint-disable-next-line
    function get_gauge_weight(address addr) external view returns (uint256);

    function get_type_weight(int128) external view returns (uint256);

    function vote_for_gauge_weights(address, uint256) external;

    function vote_user_slopes(address, address) external returns (VotedSlope memory);

    function last_user_vote(address _user, address _gauge) external view returns (uint256);

    function checkpoint_gauge(address _gauge) external;

    function add_gauge(address, int128, uint256) external;

    function add_type(string memory, uint256) external;

    function commit_transfer_ownership(address) external;

    function accept_transfer_ownership() external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple ERC20 + EIP-2612 implementation.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
///
/// @dev Note:
/// - The ERC20 standard allows minting and transferring to and from the zero address,
///   minting and transferring zero tokens, as well as self-approvals.
///   For performance, this implementation WILL NOT revert for such actions.
///   Please add any checks with overrides if desired.
/// - The `permit` function uses the ecrecover precompile (0x1).
///
/// If you are overriding:
/// - NEVER violate the ERC20 invariant:
///   the total sum of all balances must be equal to `totalSupply()`.
/// - Check that the overridden function is actually used in the function you want to
///   change the behavior of. Much of the code has been manually inlined for performance.
abstract contract ERC20 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The total supply has overflowed.
    error TotalSupplyOverflow();

    /// @dev The allowance has overflowed.
    error AllowanceOverflow();

    /// @dev The allowance has underflowed.
    error AllowanceUnderflow();

    /// @dev Insufficient balance.
    error InsufficientBalance();

    /// @dev Insufficient allowance.
    error InsufficientAllowance();

    /// @dev The permit is invalid.
    error InvalidPermit();

    /// @dev The permit has expired.
    error PermitExpired();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when `amount` tokens is transferred from `from` to `to`.
    event Transfer(address indexed from, address indexed to, uint256 amount);

    /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`.
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The storage slot for the total supply.
    uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c;

    /// @dev The balance slot of `owner` is given by:
    /// ```
    ///     mstore(0x0c, _BALANCE_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let balanceSlot := keccak256(0x0c, 0x20)
    /// ```
    uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2;

    /// @dev The allowance slot of (`owner`, `spender`) is given by:
    /// ```
    ///     mstore(0x20, spender)
    ///     mstore(0x0c, _ALLOWANCE_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let allowanceSlot := keccak256(0x0c, 0x34)
    /// ```
    uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20;

    /// @dev The nonce slot of `owner` is given by:
    /// ```
    ///     mstore(0x0c, _NONCES_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let nonceSlot := keccak256(0x0c, 0x20)
    /// ```
    uint256 private constant _NONCES_SLOT_SEED = 0x38377508;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`.
    uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901;

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 private constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    /// @dev `keccak256("1")`.
    bytes32 private constant _VERSION_HASH =
        0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;

    /// @dev `keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")`.
    bytes32 private constant _PERMIT_TYPEHASH =
        0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ERC20 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the name of the token.
    function name() public view virtual returns (string memory);

    /// @dev Returns the symbol of the token.
    function symbol() public view virtual returns (string memory);

    /// @dev Returns the decimals places of the token.
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERC20                            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the amount of tokens in existence.
    function totalSupply() public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_TOTAL_SUPPLY_SLOT)
        }
    }

    /// @dev Returns the amount of tokens owned by `owner`.
    function balanceOf(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`.
    function allowance(address owner, address spender)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x34))
        }
    }

    /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
    ///
    /// Emits a {Approval} event.
    function approve(address spender, uint256 amount) public virtual returns (bool) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the allowance slot and store the amount.
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x34), amount)
            // Emit the {Approval} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c)))
        }
        return true;
    }

    /// @dev Transfer `amount` tokens from the caller to `to`.
    ///
    /// Requirements:
    /// - `from` must at least have `amount`.
    ///
    /// Emits a {Transfer} event.
    function transfer(address to, uint256 amount) public virtual returns (bool) {
        _beforeTokenTransfer(msg.sender, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, caller())
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(msg.sender, to, amount);
        return true;
    }

    /// @dev Transfers `amount` tokens from `from` to `to`.
    ///
    /// Note: Does not update the allowance if it is the maximum uint256 value.
    ///
    /// Requirements:
    /// - `from` must at least have `amount`.
    /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
        _beforeTokenTransfer(from, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let from_ := shl(96, from)
            // Compute the allowance slot and load its value.
            mstore(0x20, caller())
            mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))
            let allowanceSlot := keccak256(0x0c, 0x34)
            let allowance_ := sload(allowanceSlot)
            // If the allowance is not the maximum uint256 value.
            if add(allowance_, 1) {
                // Revert if the amount to be transferred exceeds the allowance.
                if gt(amount, allowance_) {
                    mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated allowance.
                sstore(allowanceSlot, sub(allowance_, amount))
            }
            // Compute the balance slot and load its value.
            mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(from, to, amount);
        return true;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          EIP-2612                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev For more performance, override to return the constant value
    /// of `keccak256(bytes(name()))` if `name()` will never change.
    function _constantNameHash() internal view virtual returns (bytes32 result) {}

    /// @dev Returns the current nonce for `owner`.
    /// This value is used to compute the signature for EIP-2612 permit.
    function nonces(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the nonce slot and load its value.
            mstore(0x0c, _NONCES_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`,
    /// authorized by a signed approval by `owner`.
    ///
    /// Emits a {Approval} event.
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        /// @solidity memory-safe-assembly
        assembly {
            // Revert if the block timestamp is greater than `deadline`.
            if gt(timestamp(), deadline) {
                mstore(0x00, 0x1a15a3cc) // `PermitExpired()`.
                revert(0x1c, 0x04)
            }
            let m := mload(0x40) // Grab the free memory pointer.
            // Clean the upper 96 bits.
            owner := shr(96, shl(96, owner))
            spender := shr(96, shl(96, spender))
            // Compute the nonce slot and load its value.
            mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX)
            mstore(0x00, owner)
            let nonceSlot := keccak256(0x0c, 0x20)
            let nonceValue := sload(nonceSlot)
            // Prepare the domain separator.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), _VERSION_HASH)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            mstore(0x2e, keccak256(m, 0xa0))
            // Prepare the struct hash.
            mstore(m, _PERMIT_TYPEHASH)
            mstore(add(m, 0x20), owner)
            mstore(add(m, 0x40), spender)
            mstore(add(m, 0x60), value)
            mstore(add(m, 0x80), nonceValue)
            mstore(add(m, 0xa0), deadline)
            mstore(0x4e, keccak256(m, 0xc0))
            // Prepare the ecrecover calldata.
            mstore(0x00, keccak256(0x2c, 0x42))
            mstore(0x20, and(0xff, v))
            mstore(0x40, r)
            mstore(0x60, s)
            let t := staticcall(gas(), 1, 0, 0x80, 0x20, 0x20)
            // If the ecrecover fails, the returndatasize will be 0x00,
            // `owner` will be checked if it equals the hash at 0x00,
            // which evaluates to false (i.e. 0), and we will revert.
            // If the ecrecover succeeds, the returndatasize will be 0x20,
            // `owner` will be compared against the returned address at 0x20.
            if iszero(eq(mload(returndatasize()), owner)) {
                mstore(0x00, 0xddafbaef) // `InvalidPermit()`.
                revert(0x1c, 0x04)
            }
            // Increment and store the updated nonce.
            sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds.
            // Compute the allowance slot and store the value.
            // The `owner` is already at slot 0x20.
            mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender))
            sstore(keccak256(0x2c, 0x34), value)
            // Emit the {Approval} event.
            log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
        }
    }

    /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit.
    function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) {
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Grab the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), _VERSION_HASH)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            result := keccak256(m, 0xa0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL MINT FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Mints `amount` tokens to `to`, increasing the total supply.
    ///
    /// Emits a {Transfer} event.
    function _mint(address to, uint256 amount) internal virtual {
        _beforeTokenTransfer(address(0), to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT)
            let totalSupplyAfter := add(totalSupplyBefore, amount)
            // Revert if the total supply overflows.
            if lt(totalSupplyAfter, totalSupplyBefore) {
                mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`.
                revert(0x1c, 0x04)
            }
            // Store the updated total supply.
            sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter)
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(address(0), to, amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL BURN FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Burns `amount` tokens from `from`, reducing the total supply.
    ///
    /// Emits a {Transfer} event.
    function _burn(address from, uint256 amount) internal virtual {
        _beforeTokenTransfer(from, address(0), amount);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, from)
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Subtract and store the updated total supply.
            sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount))
            // Emit the {Transfer} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0)
        }
        _afterTokenTransfer(from, address(0), amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL TRANSFER FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Moves `amount` of tokens from `from` to `to`.
    function _transfer(address from, address to, uint256 amount) internal virtual {
        _beforeTokenTransfer(from, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let from_ := shl(96, from)
            // Compute the balance slot and load its value.
            mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(from, to, amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL ALLOWANCE FUNCTIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`.
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the allowance slot and load its value.
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, owner)
            let allowanceSlot := keccak256(0x0c, 0x34)
            let allowance_ := sload(allowanceSlot)
            // If the allowance is not the maximum uint256 value.
            if add(allowance_, 1) {
                // Revert if the amount to be transferred exceeds the allowance.
                if gt(amount, allowance_) {
                    mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated allowance.
                sstore(allowanceSlot, sub(allowance_, amount))
            }
        }
    }

    /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`.
    ///
    /// Emits a {Approval} event.
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            let owner_ := shl(96, owner)
            // Compute the allowance slot and store the amount.
            mstore(0x20, spender)
            mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED))
            sstore(keccak256(0x0c, 0x34), amount)
            // Emit the {Approval} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c)))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HOOKS TO OVERRIDE                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Hook that is called before any transfer of tokens.
    /// This includes minting and burning.
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}

    /// @dev Hook that is called after any transfer of tokens.
    /// This includes minting and burning.
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.19;

interface IVault {
    function deposit(address _recipient, uint256 _amount, bool _earn) external;
    function withdraw(uint256 _shares) external;
    function initialize() external;
}

File 8 of 12 : LibClone.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Minimal proxy library.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)
/// @author Minimal proxy by 0age (https://github.com/0age)
/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie
/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)
/// @author Minimal ERC1967 proxy by jtriley-eth (https://github.com/jtriley-eth/minimum-viable-proxy)
///
/// @dev Minimal proxy:
/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,
/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,
/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.
///
/// @dev Minimal proxy (PUSH0 variant):
/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.
/// It is optimized first for minimal runtime gas, then for minimal bytecode.
/// The PUSH0 clone functions are intentionally postfixed with a jarring "_PUSH0" as
/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.
/// Please use with caution.
///
/// @dev Clones with immutable args (CWIA):
/// The implementation of CWIA here implements a `receive()` method that emits the
/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,
/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards
/// composability. The minimal proxy implementation does not offer this feature.
///
/// @dev Minimal ERC1967 proxy:
/// An minimal ERC1967 proxy, intended to be upgraded with UUPS.
/// This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.
///
/// @dev ERC1967I proxy:
/// An variant of the minimal ERC1967 proxy, with a special code path that activates
/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
/// `implementation` address. The returned implementation is guaranteed to be valid if the
/// keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`.
library LibClone {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The keccak256 of the deployed code for the ERC1967 proxy.
    bytes32 internal constant ERC1967_CODE_HASH =
        0xaaa52c8cc8a0e3fd27ce756cc6b4e70c51423e9b597b11f32d3e49f8b1fc890d;

    /// @dev The keccak256 of the deployed code for the ERC1967I proxy.
    bytes32 internal constant ERC1967I_CODE_HASH =
        0xce700223c0d4cea4583409accfc45adac4a093b3519998a9cbbe1504dadba6f7;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unable to deploy the clone.
    error DeploymentFailed();

    /// @dev The salt must start with either the zero address or `by`.
    error SaltDoesNotStartWith();

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  MINIMAL PROXY OPERATIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Deploys a clone of `implementation`.
    function clone(address implementation) internal returns (address instance) {
        instance = clone(0, implementation);
    }

    /// @dev Deploys a clone of `implementation`.
    /// Deposits `value` ETH during deployment.
    function clone(uint256 value, address implementation) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            /**
             * --------------------------------------------------------------------------+
             * CREATION (9 bytes)                                                        |
             * --------------------------------------------------------------------------|
             * Opcode     | Mnemonic          | Stack     | Memory                       |
             * --------------------------------------------------------------------------|
             * 60 runSize | PUSH1 runSize     | r         |                              |
             * 3d         | RETURNDATASIZE    | 0 r       |                              |
             * 81         | DUP2              | r 0 r     |                              |
             * 60 offset  | PUSH1 offset      | o r 0 r   |                              |
             * 3d         | RETURNDATASIZE    | 0 o r 0 r |                              |
             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code   |
             * f3         | RETURN            |           | [0..runSize): runtime code   |
             * --------------------------------------------------------------------------|
             * RUNTIME (44 bytes)                                                        |
             * --------------------------------------------------------------------------|
             * Opcode  | Mnemonic       | Stack                  | Memory                |
             * --------------------------------------------------------------------------|
             *                                                                           |
             * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
             * 3d      | RETURNDATASIZE | 0                      |                       |
             * 3d      | RETURNDATASIZE | 0 0                    |                       |
             * 3d      | RETURNDATASIZE | 0 0 0                  |                       |
             * 3d      | RETURNDATASIZE | 0 0 0 0                |                       |
             *                                                                           |
             * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
             * 36      | CALLDATASIZE   | cds 0 0 0 0            |                       |
             * 3d      | RETURNDATASIZE | 0 cds 0 0 0 0          |                       |
             * 3d      | RETURNDATASIZE | 0 0 cds 0 0 0 0        |                       |
             * 37      | CALLDATACOPY   | 0 0 0 0                | [0..cds): calldata    |
             *                                                                           |
             * ::: delegate call to the implementation contract :::::::::::::::::::::::: |
             * 36      | CALLDATASIZE   | cds 0 0 0 0            | [0..cds): calldata    |
             * 3d      | RETURNDATASIZE | 0 cds 0 0 0 0          | [0..cds): calldata    |
             * 73 addr | PUSH20 addr    | addr 0 cds 0 0 0 0     | [0..cds): calldata    |
             * 5a      | GAS            | gas addr 0 cds 0 0 0 0 | [0..cds): calldata    |
             * f4      | DELEGATECALL   | success 0 0            | [0..cds): calldata    |
             *                                                                           |
             * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
             * 3d      | RETURNDATASIZE | rds success 0 0        | [0..cds): calldata    |
             * 3d      | RETURNDATASIZE | rds rds success 0 0    | [0..cds): calldata    |
             * 93      | SWAP4          | 0 rds success 0 rds    | [0..cds): calldata    |
             * 80      | DUP1           | 0 0 rds success 0 rds  | [0..cds): calldata    |
             * 3e      | RETURNDATACOPY | success 0 rds          | [0..rds): returndata  |
             *                                                                           |
             * 60 0x2a | PUSH1 0x2a     | 0x2a success 0 rds     | [0..rds): returndata  |
             * 57      | JUMPI          | 0 rds                  | [0..rds): returndata  |
             *                                                                           |
             * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * fd      | REVERT         |                        | [0..rds): returndata  |
             *                                                                           |
             * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b      | JUMPDEST       | 0 rds                  | [0..rds): returndata  |
             * f3      | RETURN         |                        | [0..rds): returndata  |
             * --------------------------------------------------------------------------+
             */
            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
            mstore(0x14, implementation)
            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
            instance := create(value, 0x0c, 0x35)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Deploys a deterministic clone of `implementation` with `salt`.
    function cloneDeterministic(address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = cloneDeterministic(0, implementation, salt);
    }

    /// @dev Deploys a deterministic clone of `implementation` with `salt`.
    /// Deposits `value` ETH during deployment.
    function cloneDeterministic(uint256 value, address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
            mstore(0x14, implementation)
            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
            instance := create2(value, 0x0c, 0x35, salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the initialization code of the clone of `implementation`.
    function initCode(address implementation) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(add(result, 0x40), 0x5af43d3d93803e602a57fd5bf30000000000000000000000)
            mstore(add(result, 0x28), implementation)
            mstore(add(result, 0x14), 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
            mstore(result, 0x35) // Store the length.
            mstore(0x40, add(result, 0x60)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the clone of `implementation`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHash(address implementation) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
            mstore(0x14, implementation)
            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
            hash := keccak256(0x0c, 0x35)
            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the address of the deterministic clone of `implementation`,
    /// with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)
        internal
        pure
        returns (address predicted)
    {
        bytes32 hash = initCodeHash(implementation);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*          MINIMAL PROXY OPERATIONS (PUSH0 VARIANT)          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Deploys a PUSH0 clone of `implementation`.
    function clone_PUSH0(address implementation) internal returns (address instance) {
        instance = clone_PUSH0(0, implementation);
    }

    /// @dev Deploys a PUSH0 clone of `implementation`.
    /// Deposits `value` ETH during deployment.
    function clone_PUSH0(uint256 value, address implementation)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            /**
             * --------------------------------------------------------------------------+
             * CREATION (9 bytes)                                                        |
             * --------------------------------------------------------------------------|
             * Opcode     | Mnemonic          | Stack     | Memory                       |
             * --------------------------------------------------------------------------|
             * 60 runSize | PUSH1 runSize     | r         |                              |
             * 5f         | PUSH0             | 0 r       |                              |
             * 81         | DUP2              | r 0 r     |                              |
             * 60 offset  | PUSH1 offset      | o r 0 r   |                              |
             * 5f         | PUSH0             | 0 o r 0 r |                              |
             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code   |
             * f3         | RETURN            |           | [0..runSize): runtime code   |
             * --------------------------------------------------------------------------|
             * RUNTIME (45 bytes)                                                        |
             * --------------------------------------------------------------------------|
             * Opcode  | Mnemonic       | Stack                  | Memory                |
             * --------------------------------------------------------------------------|
             *                                                                           |
             * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
             * 5f      | PUSH0          | 0                      |                       |
             * 5f      | PUSH0          | 0 0                    |                       |
             *                                                                           |
             * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
             * 36      | CALLDATASIZE   | cds 0 0                |                       |
             * 5f      | PUSH0          | 0 cds 0 0              |                       |
             * 5f      | PUSH0          | 0 0 cds 0 0            |                       |
             * 37      | CALLDATACOPY   | 0 0                    | [0..cds): calldata    |
             *                                                                           |
             * ::: delegate call to the implementation contract :::::::::::::::::::::::: |
             * 36      | CALLDATASIZE   | cds 0 0                | [0..cds): calldata    |
             * 5f      | PUSH0          | 0 cds 0 0              | [0..cds): calldata    |
             * 73 addr | PUSH20 addr    | addr 0 cds 0 0         | [0..cds): calldata    |
             * 5a      | GAS            | gas addr 0 cds 0 0     | [0..cds): calldata    |
             * f4      | DELEGATECALL   | success                | [0..cds): calldata    |
             *                                                                           |
             * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
             * 3d      | RETURNDATASIZE | rds success            | [0..cds): calldata    |
             * 5f      | PUSH0          | 0 rds success          | [0..cds): calldata    |
             * 5f      | PUSH0          | 0 0 rds success        | [0..cds): calldata    |
             * 3e      | RETURNDATACOPY | success                | [0..rds): returndata  |
             *                                                                           |
             * 60 0x29 | PUSH1 0x29     | 0x29 success           | [0..rds): returndata  |
             * 57      | JUMPI          |                        | [0..rds): returndata  |
             *                                                                           |
             * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d      | RETURNDATASIZE | rds                    | [0..rds): returndata  |
             * 5f      | PUSH0          | 0 rds                  | [0..rds): returndata  |
             * fd      | REVERT         |                        | [0..rds): returndata  |
             *                                                                           |
             * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b      | JUMPDEST       |                        | [0..rds): returndata  |
             * 3d      | RETURNDATASIZE | rds                    | [0..rds): returndata  |
             * 5f      | PUSH0          | 0 rds                  | [0..rds): returndata  |
             * f3      | RETURN         |                        | [0..rds): returndata  |
             * --------------------------------------------------------------------------+
             */
            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
            mstore(0x14, implementation) // 20
            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
            instance := create(value, 0x0e, 0x36)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
    function cloneDeterministic_PUSH0(address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = cloneDeterministic_PUSH0(0, implementation, salt);
    }

    /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
    /// Deposits `value` ETH during deployment.
    function cloneDeterministic_PUSH0(uint256 value, address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
            mstore(0x14, implementation) // 20
            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
            instance := create2(value, 0x0e, 0x36, salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the initialization code of the PUSH0 clone of `implementation`.
    function initCode_PUSH0(address implementation) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(add(result, 0x40), 0x5af43d5f5f3e6029573d5ffd5b3d5ff300000000000000000000) // 16
            mstore(add(result, 0x26), implementation) // 20
            mstore(add(result, 0x12), 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
            mstore(result, 0x36) // Store the length.
            mstore(0x40, add(result, 0x60)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
            mstore(0x14, implementation) // 20
            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
            hash := keccak256(0x0e, 0x36)
            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,
    /// with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress_PUSH0(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes32 hash = initCodeHash_PUSH0(implementation);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*           CLONES WITH IMMUTABLE ARGS OPERATIONS            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: This implementation of CWIA differs from the original implementation.
    // If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.

    /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `data`.
    function clone(address implementation, bytes memory data) internal returns (address instance) {
        instance = clone(0, implementation, data);
    }

    /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `data`.
    /// Deposits `value` ETH during deployment.
    function clone(uint256 value, address implementation, bytes memory data)
        internal
        returns (address instance)
    {
        assembly {
            // Compute the boundaries of the data and cache the memory slots around it.
            let mBefore3 := mload(sub(data, 0x60))
            let mBefore2 := mload(sub(data, 0x40))
            let mBefore1 := mload(sub(data, 0x20))
            let dataLength := mload(data)
            let dataEnd := add(add(data, 0x20), dataLength)
            let mAfter1 := mload(dataEnd)

            // +2 bytes for telling how much data there is appended to the call.
            let extraLength := add(dataLength, 2)
            // The `creationSize` is `extraLength + 108`
            // The `runSize` is `creationSize - 10`.

            /**
             * ---------------------------------------------------------------------------------------------------+
             * CREATION (10 bytes)                                                                                |
             * ---------------------------------------------------------------------------------------------------|
             * Opcode     | Mnemonic          | Stack     | Memory                                                |
             * ---------------------------------------------------------------------------------------------------|
             * 61 runSize | PUSH2 runSize     | r         |                                                       |
             * 3d         | RETURNDATASIZE    | 0 r       |                                                       |
             * 81         | DUP2              | r 0 r     |                                                       |
             * 60 offset  | PUSH1 offset      | o r 0 r   |                                                       |
             * 3d         | RETURNDATASIZE    | 0 o r 0 r |                                                       |
             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code                            |
             * f3         | RETURN            |           | [0..runSize): runtime code                            |
             * ---------------------------------------------------------------------------------------------------|
             * RUNTIME (98 bytes + extraLength)                                                                   |
             * ---------------------------------------------------------------------------------------------------|
             * Opcode   | Mnemonic       | Stack                    | Memory                                      |
             * ---------------------------------------------------------------------------------------------------|
             *                                                                                                    |
             * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |
             * 36       | CALLDATASIZE   | cds                      |                                             |
             * 60 0x2c  | PUSH1 0x2c     | 0x2c cds                 |                                             |
             * 57       | JUMPI          |                          |                                             |
             * 34       | CALLVALUE      | cv                       |                                             |
             * 3d       | RETURNDATASIZE | 0 cv                     |                                             |
             * 52       | MSTORE         |                          | [0..0x20): callvalue                        |
             * 7f sig   | PUSH32 0x9e..  | sig                      | [0..0x20): callvalue                        |
             * 59       | MSIZE          | 0x20 sig                 | [0..0x20): callvalue                        |
             * 3d       | RETURNDATASIZE | 0 0x20 sig               | [0..0x20): callvalue                        |
             * a1       | LOG1           |                          | [0..0x20): callvalue                        |
             * 00       | STOP           |                          | [0..0x20): callvalue                        |
             * 5b       | JUMPDEST       |                          |                                             |
             *                                                                                                    |
             * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36       | CALLDATASIZE   | cds                      |                                             |
             * 3d       | RETURNDATASIZE | 0 cds                    |                                             |
             * 3d       | RETURNDATASIZE | 0 0 cds                  |                                             |
             * 37       | CALLDATACOPY   |                          | [0..cds): calldata                          |
             *                                                                                                    |
             * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d       | RETURNDATASIZE | 0                        | [0..cds): calldata                          |
             * 3d       | RETURNDATASIZE | 0 0                      | [0..cds): calldata                          |
             * 3d       | RETURNDATASIZE | 0 0 0                    | [0..cds): calldata                          |
             * 3d       | RETURNDATASIZE | 0 0 0 0                  | [0..cds): calldata                          |
             * 61 extra | PUSH2 extra    | e 0 0 0 0                | [0..cds): calldata                          |
             *                                                                                                    |
             * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 80       | DUP1           | e e 0 0 0 0              | [0..cds): calldata                          |
             * 60 0x62  | PUSH1 0x62     | 0x62 e e 0 0 0 0         | [0..cds): calldata                          |
             * 36       | CALLDATASIZE   | cds 0x62 e e 0 0 0 0     | [0..cds): calldata                          |
             * 39       | CODECOPY       | e 0 0 0 0                | [0..cds): calldata, [cds..cds+e): extraData |
             *                                                                                                    |
             * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36       | CALLDATASIZE   | cds e 0 0 0 0            | [0..cds): calldata, [cds..cds+e): extraData |
             * 01       | ADD            | cds+e 0 0 0 0            | [0..cds): calldata, [cds..cds+e): extraData |
             * 3d       | RETURNDATASIZE | 0 cds+e 0 0 0 0          | [0..cds): calldata, [cds..cds+e): extraData |
             * 73 addr  | PUSH20 addr    | addr 0 cds+e 0 0 0 0     | [0..cds): calldata, [cds..cds+e): extraData |
             * 5a       | GAS            | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
             * f4       | DELEGATECALL   | success 0 0              | [0..cds): calldata, [cds..cds+e): extraData |
             *                                                                                                    |
             * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d       | RETURNDATASIZE | rds success 0 0          | [0..cds): calldata, [cds..cds+e): extraData |
             * 3d       | RETURNDATASIZE | rds rds success 0 0      | [0..cds): calldata, [cds..cds+e): extraData |
             * 93       | SWAP4          | 0 rds success 0 rds      | [0..cds): calldata, [cds..cds+e): extraData |
             * 80       | DUP1           | 0 0 rds success 0 rds    | [0..cds): calldata, [cds..cds+e): extraData |
             * 3e       | RETURNDATACOPY | success 0 rds            | [0..rds): returndata                        |
             *                                                                                                    |
             * 60 0x60  | PUSH1 0x60     | 0x60 success 0 rds       | [0..rds): returndata                        |
             * 57       | JUMPI          | 0 rds                    | [0..rds): returndata                        |
             *                                                                                                    |
             * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * fd       | REVERT         |                          | [0..rds): returndata                        |
             *                                                                                                    |
             * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b       | JUMPDEST       | 0 rds                    | [0..rds): returndata                        |
             * f3       | RETURN         |                          | [0..rds): returndata                        |
             * ---------------------------------------------------------------------------------------------------+
             */
            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.
            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.
            // Write the rest of the bytecode.
            mstore(
                sub(data, 0x21),
                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
            )
            // `keccak256("ReceiveETH(uint256)")`
            mstore(
                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
            )
            mstore(
                // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.
                // The actual EVM limit may be smaller and may change over time.
                sub(data, add(0x59, lt(extraLength, 0xff9e))),
                or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)
            )
            mstore(dataEnd, shl(0xf0, extraLength))

            instance := create(value, sub(data, 0x4c), add(extraLength, 0x6c))
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }

            // Restore the overwritten memory surrounding `data`.
            mstore(dataEnd, mAfter1)
            mstore(data, dataLength)
            mstore(sub(data, 0x20), mBefore1)
            mstore(sub(data, 0x40), mBefore2)
            mstore(sub(data, 0x60), mBefore3)
        }
    }

    /// @dev Deploys a deterministic clone of `implementation`
    /// with immutable arguments encoded in `data` and `salt`.
    function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = cloneDeterministic(0, implementation, data, salt);
    }

    /// @dev Deploys a deterministic clone of `implementation`
    /// with immutable arguments encoded in `data` and `salt`.
    function cloneDeterministic(
        uint256 value,
        address implementation,
        bytes memory data,
        bytes32 salt
    ) internal returns (address instance) {
        assembly {
            // Compute the boundaries of the data and cache the memory slots around it.
            let mBefore3 := mload(sub(data, 0x60))
            let mBefore2 := mload(sub(data, 0x40))
            let mBefore1 := mload(sub(data, 0x20))
            let dataLength := mload(data)
            let dataEnd := add(add(data, 0x20), dataLength)
            let mAfter1 := mload(dataEnd)

            // +2 bytes for telling how much data there is appended to the call.
            let extraLength := add(dataLength, 2)

            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.
            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.
            // Write the rest of the bytecode.
            mstore(
                sub(data, 0x21),
                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
            )
            // `keccak256("ReceiveETH(uint256)")`
            mstore(
                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
            )
            mstore(
                // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.
                // The actual EVM limit may be smaller and may change over time.
                sub(data, add(0x59, lt(extraLength, 0xff9e))),
                or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)
            )
            mstore(dataEnd, shl(0xf0, extraLength))

            instance := create2(value, sub(data, 0x4c), add(extraLength, 0x6c), salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }

            // Restore the overwritten memory surrounding `data`.
            mstore(dataEnd, mAfter1)
            mstore(data, dataLength)
            mstore(sub(data, 0x20), mBefore1)
            mstore(sub(data, 0x40), mBefore2)
            mstore(sub(data, 0x60), mBefore3)
        }
    }

    /// @dev Returns the initialization code hash of the clone of `implementation`
    /// using immutable arguments encoded in `data`.
    function initCode(address implementation, bytes memory data)
        internal
        pure
        returns (bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let dataLength := mload(data)

            // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.
            // The actual EVM limit may be smaller and may change over time.
            returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))

            let o := add(result, 0x8c)
            let end := add(o, dataLength)

            // Copy the `data` into `result`.
            for { let d := sub(add(data, 0x20), o) } 1 {} {
                mstore(o, mload(add(o, d)))
                o := add(o, 0x20)
                if iszero(lt(o, end)) { break }
            }

            // +2 bytes for telling how much data there is appended to the call.
            let extraLength := add(dataLength, 2)

            mstore(add(result, 0x6c), 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.
            mstore(add(result, 0x5f), implementation) // Write the address of the implementation.
            // Write the rest of the bytecode.
            mstore(
                add(result, 0x4b),
                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
            )
            // `keccak256("ReceiveETH(uint256)")`
            mstore(
                add(result, 0x32),
                0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
            )
            mstore(
                add(result, 0x12),
                or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)
            )
            mstore(end, shl(0xf0, extraLength))
            mstore(add(end, 0x02), 0) // Zeroize the slot after the result.
            mstore(result, add(extraLength, 0x6c)) // Store the length.
            mstore(0x40, add(0x22, end)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the clone of `implementation`
    /// using immutable arguments encoded in `data`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHash(address implementation, bytes memory data)
        internal
        pure
        returns (bytes32 hash)
    {
        assembly {
            // Compute the boundaries of the data and cache the memory slots around it.
            let mBefore3 := mload(sub(data, 0x60))
            let mBefore2 := mload(sub(data, 0x40))
            let mBefore1 := mload(sub(data, 0x20))
            let dataLength := mload(data)
            let dataEnd := add(add(data, 0x20), dataLength)
            let mAfter1 := mload(dataEnd)

            // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.
            // The actual EVM limit may be smaller and may change over time.
            returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))

            // +2 bytes for telling how much data there is appended to the call.
            let extraLength := add(dataLength, 2)

            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.
            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.
            // Write the rest of the bytecode.
            mstore(
                sub(data, 0x21),
                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
            )
            // `keccak256("ReceiveETH(uint256)")`
            mstore(
                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
            )
            mstore(
                sub(data, 0x5a),
                or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)
            )
            mstore(dataEnd, shl(0xf0, extraLength))

            hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))

            // Restore the overwritten memory surrounding `data`.
            mstore(dataEnd, mAfter1)
            mstore(data, dataLength)
            mstore(sub(data, 0x20), mBefore1)
            mstore(sub(data, 0x40), mBefore2)
            mstore(sub(data, 0x60), mBefore3)
        }
    }

    /// @dev Returns the address of the deterministic clone of
    /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress(
        address implementation,
        bytes memory data,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes32 hash = initCodeHash(implementation, data);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              MINIMAL ERC1967 PROXY OPERATIONS              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: The ERC1967 proxy here is intended to be upgraded with UUPS.
    // This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.

    /// @dev Deploys a minimal ERC1967 proxy with `implementation`.
    function deployERC1967(address implementation) internal returns (address instance) {
        instance = deployERC1967(0, implementation);
    }

    /// @dev Deploys a minimal ERC1967 proxy with `implementation`.
    /// Deposits `value` ETH during deployment.
    function deployERC1967(uint256 value, address implementation)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            /**
             * ---------------------------------------------------------------------------------+
             * CREATION (34 bytes)                                                              |
             * ---------------------------------------------------------------------------------|
             * Opcode     | Mnemonic       | Stack            | Memory                          |
             * ---------------------------------------------------------------------------------|
             * 60 runSize | PUSH1 runSize  | r                |                                 |
             * 3d         | RETURNDATASIZE | 0 r              |                                 |
             * 81         | DUP2           | r 0 r            |                                 |
             * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |
             * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |
             * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |
             * 73 impl    | PUSH20 impl    | impl 0 r         | [0..runSize): runtime code      |
             * 60 slotPos | PUSH1 slotPos  | slotPos impl 0 r | [0..runSize): runtime code      |
             * 51         | MLOAD          | slot impl 0 r    | [0..runSize): runtime code      |
             * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |
             * f3         | RETURN         |                  | [0..runSize): runtime code      |
             * ---------------------------------------------------------------------------------|
             * RUNTIME (61 bytes)                                                               |
             * ---------------------------------------------------------------------------------|
             * Opcode     | Mnemonic       | Stack            | Memory                          |
             * ---------------------------------------------------------------------------------|
             *                                                                                  |
             * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36         | CALLDATASIZE   | cds              |                                 |
             * 3d         | RETURNDATASIZE | 0 cds            |                                 |
             * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |
             * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |
             *                                                                                  |
             * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | 0                |                                 |
             * 3d         | RETURNDATASIZE | 0 0              |                                 |
             * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |
             * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |
             * 7f slot    | PUSH32 slot    | s 0 cds 0 0      | [0..calldatasize): calldata     |
             * 54         | SLOAD          | i 0 cds 0 0      | [0..calldatasize): calldata     |
             * 5a         | GAS            | g i 0 cds 0 0    | [0..calldatasize): calldata     |
             * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |
             *                                                                                  |
             * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |
             * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |
             * 80         | DUP1           | 0 0 rds succ     | [0..calldatasize): calldata     |
             * 3e         | RETURNDATACOPY | succ             | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
             * 60 0x38    | PUSH1 0x38     | dest succ        | [0..returndatasize): returndata |
             * 57         | JUMPI          |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
             * fd         | REVERT         |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b         | JUMPDEST       |                  | [0..returndatasize): returndata |
             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
             * f3         | RETURN         |                  | [0..returndatasize): returndata |
             * ---------------------------------------------------------------------------------+
             */
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
            mstore(0x20, 0x6009)
            mstore(0x1e, implementation)
            mstore(0x0a, 0x603d3d8160223d3973)
            instance := create(value, 0x21, 0x5f)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
    function deployDeterministicERC1967(address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = deployDeterministicERC1967(0, implementation, salt);
    }

    /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
    /// Deposits `value` ETH during deployment.
    function deployDeterministicERC1967(uint256 value, address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
            mstore(0x20, 0x6009)
            mstore(0x1e, implementation)
            mstore(0x0a, 0x603d3d8160223d3973)
            instance := create2(value, 0x21, 0x5f, salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
    /// Note: This method is intended for use in ERC4337 factories,
    /// which are expected to NOT revert if the proxy is already deployed.
    function createDeterministicERC1967(address implementation, bytes32 salt)
        internal
        returns (bool alreadyDeployed, address instance)
    {
        return createDeterministicERC1967(0, implementation, salt);
    }

    /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
    /// Deposits `value` ETH during deployment.
    /// Note: This method is intended for use in ERC4337 factories,
    /// which are expected to NOT revert if the proxy is already deployed.
    function createDeterministicERC1967(uint256 value, address implementation, bytes32 salt)
        internal
        returns (bool alreadyDeployed, address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
            mstore(0x20, 0x6009)
            mstore(0x1e, implementation)
            mstore(0x0a, 0x603d3d8160223d3973)
            // Compute and store the bytecode hash.
            mstore(add(m, 0x35), keccak256(0x21, 0x5f))
            mstore(m, shl(88, address()))
            mstore8(m, 0xff) // Write the prefix.
            mstore(add(m, 0x15), salt)
            instance := keccak256(m, 0x55)
            for {} 1 {} {
                if iszero(extcodesize(instance)) {
                    instance := create2(value, 0x21, 0x5f, salt)
                    if iszero(instance) {
                        mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                        revert(0x1c, 0x04)
                    }
                    break
                }
                alreadyDeployed := 1
                if iszero(value) { break }
                if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                    mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                    revert(0x1c, 0x04)
                }
                break
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation`.
    function initCodeERC1967(address implementation) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(
                add(result, 0x60),
                0x3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f300
            )
            mstore(
                add(result, 0x40),
                0x55f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc
            )
            mstore(add(result, 0x20), or(shl(24, implementation), 0x600951))
            mstore(add(result, 0x09), 0x603d3d8160223d3973)
            mstore(result, 0x5f) // Store the length.
            mstore(0x40, add(result, 0x80)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHashERC1967(address implementation) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
            mstore(0x20, 0x6009)
            mstore(0x1e, implementation)
            mstore(0x0a, 0x603d3d8160223d3973)
            hash := keccak256(0x21, 0x5f)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Returns the address of the deterministic ERC1967 proxy of `implementation`,
    /// with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddressERC1967(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes32 hash = initCodeHashERC1967(implementation);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                 ERC1967I PROXY OPERATIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: This proxy has a special code path that activates if `calldatasize() == 1`.
    // This code path skips the delegatecall and directly returns the `implementation` address.
    // The returned implementation is guaranteed to be valid if the keccak256 of the
    // proxy's code is equal to `ERC1967I_CODE_HASH`.

    /// @dev Deploys a minimal ERC1967I proxy with `implementation`.
    function deployERC1967I(address implementation) internal returns (address instance) {
        instance = deployERC1967I(0, implementation);
    }

    /// @dev Deploys a ERC1967I proxy with `implementation`.
    /// Deposits `value` ETH during deployment.
    function deployERC1967I(uint256 value, address implementation)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            /**
             * ---------------------------------------------------------------------------------+
             * CREATION (34 bytes)                                                              |
             * ---------------------------------------------------------------------------------|
             * Opcode     | Mnemonic       | Stack            | Memory                          |
             * ---------------------------------------------------------------------------------|
             * 60 runSize | PUSH1 runSize  | r                |                                 |
             * 3d         | RETURNDATASIZE | 0 r              |                                 |
             * 81         | DUP2           | r 0 r            |                                 |
             * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |
             * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |
             * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |
             * 73 impl    | PUSH20 impl    | impl 0 r         | [0..runSize): runtime code      |
             * 60 slotPos | PUSH1 slotPos  | slotPos impl 0 r | [0..runSize): runtime code      |
             * 51         | MLOAD          | slot impl 0 r    | [0..runSize): runtime code      |
             * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |
             * f3         | RETURN         |                  | [0..runSize): runtime code      |
             * ---------------------------------------------------------------------------------|
             * RUNTIME (82 bytes)                                                               |
             * ---------------------------------------------------------------------------------|
             * Opcode     | Mnemonic       | Stack            | Memory                          |
             * ---------------------------------------------------------------------------------|
             *                                                                                  |
             * ::: check calldatasize ::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36         | CALLDATASIZE   | cds              |                                 |
             * 58         | PC             | 1 cds            |                                 |
             * 14         | EQ             | eqs              |                                 |
             * 60 0x43    | PUSH1 0x43     | dest eqs         |                                 |
             * 57         | JUMPI          |                  |                                 |
             *                                                                                  |
             * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36         | CALLDATASIZE   | cds              |                                 |
             * 3d         | RETURNDATASIZE | 0 cds            |                                 |
             * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |
             * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |
             *                                                                                  |
             * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | 0                |                                 |
             * 3d         | RETURNDATASIZE | 0 0              |                                 |
             * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |
             * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |
             * 7f slot    | PUSH32 slot    | s 0 cds 0 0      | [0..calldatasize): calldata     |
             * 54         | SLOAD          | i 0 cds 0 0      | [0..calldatasize): calldata     |
             * 5a         | GAS            | g i 0 cds 0 0    | [0..calldatasize): calldata     |
             * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |
             *                                                                                  |
             * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |
             * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |
             * 80         | DUP1           | 0 0 rds succ     | [0..calldatasize): calldata     |
             * 3e         | RETURNDATACOPY | succ             | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
             * 60 0x3E    | PUSH1 0x3E     | dest succ        | [0..returndatasize): returndata |
             * 57         | JUMPI          |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
             * fd         | REVERT         |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b         | JUMPDEST       |                  | [0..returndatasize): returndata |
             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
             * f3         | RETURN         |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: implementation , return :::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b         | JUMPDEST       |                  |                                 |
             * 60 0x20    | PUSH1 0x20     | 32               |                                 |
             * 60 0x0F    | PUSH1 0x0F     | o 32             |                                 |
             * 3d         | RETURNDATASIZE | 0 o 32           |                                 |
             * 39         | CODECOPY       |                  | [0..32): implementation slot    |
             * 3d         | RETURNDATASIZE | 0                | [0..32): implementation slot    |
             * 51         | MLOAD          | slot             | [0..32): implementation slot    |
             * 54         | SLOAD          | impl             | [0..32): implementation slot    |
             * 3d         | RETURNDATASIZE | 0 impl           | [0..32): implementation slot    |
             * 52         | MSTORE         |                  | [0..32): implementation address |
             * 59         | MSIZE          | 32               | [0..32): implementation address |
             * 3d         | RETURNDATASIZE | 0 32             | [0..32): implementation address |
             * f3         | RETURN         |                  | [0..32): implementation address |
             *                                                                                  |
             * ---------------------------------------------------------------------------------+
             */
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
            mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
            mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
            instance := create(value, 0x0c, 0x74)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.
    function deployDeterministicERC1967I(address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = deployDeterministicERC1967I(0, implementation, salt);
    }

    /// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.
    /// Deposits `value` ETH during deployment.
    function deployDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
            mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
            mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
            instance := create2(value, 0x0c, 0x74, salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.
    /// Note: This method is intended for use in ERC4337 factories,
    /// which are expected to NOT revert if the proxy is already deployed.
    function createDeterministicERC1967I(address implementation, bytes32 salt)
        internal
        returns (bool alreadyDeployed, address instance)
    {
        return createDeterministicERC1967I(0, implementation, salt);
    }

    /// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.
    /// Deposits `value` ETH during deployment.
    /// Note: This method is intended for use in ERC4337 factories,
    /// which are expected to NOT revert if the proxy is already deployed.
    function createDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)
        internal
        returns (bool alreadyDeployed, address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
            mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
            mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
            // Compute and store the bytecode hash.
            mstore(add(m, 0x35), keccak256(0x0c, 0x74))
            mstore(m, shl(88, address()))
            mstore8(m, 0xff) // Write the prefix.
            mstore(add(m, 0x15), salt)
            instance := keccak256(m, 0x55)
            for {} 1 {} {
                if iszero(extcodesize(instance)) {
                    instance := create2(value, 0x0c, 0x74, salt)
                    if iszero(instance) {
                        mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                        revert(0x1c, 0x04)
                    }
                    break
                }
                alreadyDeployed := 1
                if iszero(value) { break }
                if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                    mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                    revert(0x1c, 0x04)
                }
                break
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation`.
    function initCodeERC1967I(address implementation) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(
                add(result, 0x74),
                0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3
            )
            mstore(
                add(result, 0x54),
                0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4
            )
            mstore(add(result, 0x34), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(add(result, 0x1d), implementation)
            mstore(add(result, 0x09), 0x60523d8160223d3973)
            mstore(add(result, 0x94), 0)
            mstore(result, 0x74) // Store the length.
            mstore(0x40, add(result, 0xa0)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHashERC1967I(address implementation) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
            mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
            mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
            hash := keccak256(0x0c, 0x74)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Returns the address of the deterministic ERC1967I proxy of `implementation`,
    /// with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddressERC1967I(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes32 hash = initCodeHashERC1967I(implementation);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      OTHER OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the address when a contract with initialization code hash,
    /// `hash`, is deployed with `salt`, by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)
        internal
        pure
        returns (address predicted)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and store the bytecode hash.
            mstore8(0x00, 0xff) // Write the prefix.
            mstore(0x35, hash)
            mstore(0x01, shl(96, deployer))
            mstore(0x15, salt)
            predicted := keccak256(0x00, 0x55)
            mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Requires that `salt` starts with either the zero address or `by`.
    function checkStartsWith(bytes32 salt, address by) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            // If the salt does not start with the zero address or `by`.
            if iszero(or(iszero(shr(96, salt)), eq(shr(96, shl(96, by)), shr(96, salt)))) {
                mstore(0x00, 0x0c4549ef) // `SaltDoesNotStartWith()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;

interface IStrategy {
    function locker() external view returns (address);

    function deposit(address _token, uint256 amount) external;
    function withdraw(address _token, uint256 amount) external;

    function claimProtocolFees() external;
    function claimNativeRewards() external;
    function harvest(address _asset, bool _distributeSDT, bool _claimExtra) external;

    function rewardReceivers(address _gauge) external view returns (address);
    function rewardDistributors(address _gauge) external view returns (address);

    /// Factory functions
    function toggleVault(address vault) external;
    function setGauge(address token, address gauge) external;
    function setLGtype(address gauge, uint256 gaugeType) external;
    function addRewardToken(address _token, address _rewardDistributor) external;
    function acceptRewardDistributorOwnership(address rewardDistributor) external;
    function setRewardDistributor(address gauge, address rewardDistributor) external;
    function addRewardReceiver(address gauge, address rewardReceiver) external;

    function execute(address _to, uint256 _value, bytes calldata _data) external returns (bool, bytes memory);
}

/// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.19;

interface IFallback {
    function initialize() external;
    function claim(bool _claimExtraRewards)
        external
        returns (uint256 rewardTokenAmount, uint256 fallbackRewardTokenAmount, uint256 protocolFees);
    function balanceOf(address _asset) external view returns (uint256);
    function deposit(address _asset, uint256 _amount) external;
    function withdraw(address _asset, uint256 _amount) external;
    function fallbackRewardToken() external view returns (address);
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;

interface ILiquidityGauge {
    struct Reward {
        address token;
        address distributor;
        uint256 period_finish;
        uint256 rate;
        uint256 last_update;
        uint256 integral;
    }

    function deposit_reward_token(address _rewardToken, uint256 _amount) external;

    function claim_rewards_for(address _user, address _recipient) external;

    function working_balances(address _address) external view returns (uint256);

    function deposit(uint256 _value, address _addr) external;

    function reward_tokens(uint256 _i) external view returns (address);

    function reward_data(address _tokenReward) external view returns (Reward memory);

    function balanceOf(address) external view returns (uint256);

    function totalSupply() external view returns (uint256);

    function claimable_reward(address _user, address _reward_token) external view returns (uint256);

    function claimable_tokens(address _user) external returns (uint256);

    function user_checkpoint(address _user) external returns (bool);

    function commit_transfer_ownership(address) external;

    function apply_transfer_ownership() external;

    function claim_rewards(address) external;

    function add_reward(address, address) external;

    function set_claimer(address) external;

    function admin() external view returns (address);

    function set_reward_distributor(address _rewardToken, address _newDistrib) external;

    function lp_token() external view returns (address);

    function is_killed() external view returns (bool);

    function staking_token() external view returns (address);
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;

/// Modified version of the liquidity for Stake DAO needs.
interface ISDLiquidityGauge {
    struct Reward {
        address token;
        address distributor;
        uint256 period_finish;
        uint256 rate;
        uint256 last_update;
        uint256 integral;
    }

    // solhint-disable-next-line
    function deposit_reward_token(address _rewardToken, uint256 _amount) external;

    // solhint-disable-next-line
    function claim_rewards_for(address _user, address _recipient) external;

    function claim_rewards() external;

    function claim_rewards(address _user) external;

    function claim_rewards(address _user, address _receiver) external;

    // // solhint-disable-next-line
    // function claim_rewards_for(address _user) external;

    // solhint-disable-next-line
    function deposit(uint256 _value, address _addr) external;

    // solhint-disable-next-line
    function reward_tokens(uint256 _i) external view returns (address);

    function withdraw(uint256 _value, address _addr, bool _claim_rewards) external;

    function withdraw(uint256 _value, address _addr) external;

    function staking_token() external view returns (address);

    function vault() external view returns (address);

    // solhint-disable-next-line
    function reward_data(address _tokenReward) external view returns (Reward memory);

    function reward_count() external view returns (uint256);

    function totalSupply() external view returns (uint256);

    function balanceOf(address) external returns (uint256);

    function claimable_reward(address _user, address _reward_token) external view returns (uint256);

    function user_checkpoint(address _user) external returns (bool);

    function commit_transfer_ownership(address) external;

    function initialize(
        address _staking_token,
        address _admin,
        address _SDT,
        address _voting_escrow,
        address _veBoost_proxy,
        address _distributor,
        address _vault,
        string memory _symbol
    ) external;

    function add_reward(address, address) external;

    function set_claimer(address) external;

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function transfer(address _to, uint256 _value) external returns (bool);

    function working_balances(address _address) external returns (uint256);

    function set_reward_distributor(address _rewardToken, address _newDistrib) external;
}

Settings
{
  "remappings": [
    "solady/=lib/solady/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_vaultImplementation","type":"address"},{"internalType":"address","name":"_liquidityGaugeImplementation","type":"address"},{"internalType":"address","name":"_rewardReceiverImplementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"GAUGE_ALREADY_USED","type":"error"},{"inputs":[],"name":"INVALID_GAUGE","type":"error"},{"inputs":[],"name":"INVALID_TOKEN","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"rewardDistributor","type":"address"},{"indexed":false,"internalType":"address","name":"lp","type":"address"},{"indexed":false,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"stakingConvex","type":"address"}],"name":"PoolDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"rewardDistributor","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"gauge","type":"address"}],"name":"PoolDeployed","type":"event"},{"inputs":[],"name":"BOOSTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CLAIM_HELPER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONVEX_MINIMAL_PROXY_FACTORY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CVX","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GAUGE_CONTROLLER","outputs":[{"internalType":"contract IGaugeController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SDT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SDT_DISTRIBUTOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VESDT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VE_BOOST_PROXY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VE_FUNDER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"create","outputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"rewardDistributor","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"bool","name":"_deployPool","type":"bool"},{"internalType":"bool","name":"_deployConvex","type":"bool"}],"name":"create","outputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"rewardDistributor","type":"address"},{"internalType":"address","name":"stakingConvex","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidityGaugeImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardReceiverImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"contract IStrategy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"syncExtraRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

6101206040523480156200001257600080fd5b5060405162001f7738038062001f7783398101604081905262000035916200007c565b6001600160a01b0393841660a05293831660805290821660c0528116610100521660e052620000ec565b80516001600160a01b03811681146200007757600080fd5b919050565b600080600080600060a086880312156200009557600080fd5b620000a0866200005f565b9450620000b0602087016200005f565b9350620000c0604087016200005f565b9250620000d0606087016200005f565b9150620000e0608087016200005f565b90509295509295909350565b60805160a05160c05160e05161010051611db3620001c4600039600081816101b40152610ac3015260006103030152600081816102dc0152610b7f015260008181610367015281816115a7015261169501526000818161029a0152818161056c0152818161060b0152818161069a015281816108070152818161084e0152818161094301528181610a1d01528181610b3201528181610ceb01528181610d5e01528181610dde01528181610ecb01528181610f4e015281816110e3015281816112840152818161157801526116160152611db36000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063918f8674116100ad578063bba48a9011610071578063bba48a90146102d7578063d4bba87b146102fe578063f7a6bc7b14610325578063f7c618c114610362578063fb7049cd1461038957600080fd5b8063918f8674146102425780639ed9331814610259578063a77f02451461027a578063a8c62e7614610295578063ba32c619146102bc57600080fd5b80634e8090ce116100f45780634e8090ce146101af57806358a13f08146101d657806362810e1a146101f1578063759cb53b1461020c57806375b0ffd11461022757600080fd5b80631326c2471461012657806322884e2c1461015e578063401c9eec1461017957806348fc3c2d14610194575b600080fd5b61014173baf05d7aa4129ca14ec45cc9d4103a9ab9a9ff6081565b6040516001600160a01b0390911681526020015b60405180910390f35b610141732f50d538606fa9edd2b11e2446beb18c9d5846bb81565b61014173d67bdbeff01fc492f1864e61756e5fbb3f17350681565b610141730c30476f66034e11782938df8e4384970b6c9e8a81565b6101417f000000000000000000000000000000000000000000000000000000000000000081565b610141739c99dffc1de1aff7e7c1f36fcdd49063a281e18c81565b61014173539e65190a371ce73244a98dec42ba635cca512c81565b610141734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b81565b61014173f403c135812408bfbe8713b5a23a04b3d48aae3181565b61024b61271081565b604051908152602001610155565b61026c61026736600461192e565b61039e565b604051610155929190611952565b610141734e795a6f991e305e3f28a3b1b2b4b9789d2cd5a181565b6101417f000000000000000000000000000000000000000000000000000000000000000081565b6101417373968b9a57c6e53d41345fd57a6e6ae27d6cdb2f81565b6101417f000000000000000000000000000000000000000000000000000000000000000081565b6101417f000000000000000000000000000000000000000000000000000000000000000081565b61033861033336600461197a565b6103b3565b604080516001600160a01b0394851681529284166020840152921691810191909152606001610155565b6101417f000000000000000000000000000000000000000000000000000000000000000081565b61039c61039736600461192e565b610921565b005b6000806103aa836109d2565b91509150915091565b600080600080600073f403c135812408bfbe8713b5a23a04b3d48aae316001600160a01b0316631526fe27896040518263ffffffff1660e01b81526004016103fd91815260200190565b60c060405180830381865afa15801561041a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043e91906119bc565b505050925050915085156104d457604051630ecaea7360e01b81526001600160a01b038316600482015260248101899052734e795a6f991e305e3f28a3b1b2b4b9789d2cd5a190630ecaea73906044016020604051808303816000875af11580156104ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d19190611a43565b92505b861561054a576104e3816109d2565b604080516001600160a01b03848116825283811660208301528681168284015285811660608301528716608082015290519297509095507fb9b8d50b80f9a41ca6bb6a3e3e8fc694fe041d8059f91a504be694b820cd0573919081900360a00190a1610916565b604051632a704bc360e21b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9c12f0c90602401602060405180830381865afa1580156105b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d99190611a43565b604051636eb1769f60e11b8152909150734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b9063dd62ed3e90610635907f0000000000000000000000000000000000000000000000000000000000000000908590600401611952565b602060405180830381865afa158015610652573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106769190611a60565b600003610772576040516001600160a01b03828116602483015260001960448301527f0000000000000000000000000000000000000000000000000000000000000000169063b61d27f690734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b9060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b031916815261072893929190600401611ac9565b6000604051808303816000875af1158015610747573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261076f9190810190611b83565b50505b604051632474e32f60e11b8152734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b60048201526000906001600160a01b038316906348e9c65e9060240160c060405180830381865afa1580156107cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f19190611be8565b6020015190506001600160a01b038116610913577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b61d27f6836000734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b7f000000000000000000000000000000000000000000000000000000000000000060405160240161087e929190611952565b60408051601f198184030181529181526020820180516001600160e01b031663e8de0d4d60e01b1790525160e085901b6001600160e01b03191681526108c993929190600401611ac9565b6000604051808303816000875af11580156108e8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109109190810190611b83565b50505b50505b505093509350939050565b604051632a704bc360e21b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9c12f0c90602401602060405180830381865afa15801561098c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b09190611a43565b90506001600160a01b0381166109c4575050565b6109ce828261101b565b5050565b6000806109de836112ff565b6109fb57604051633859027960e21b815260040160405180910390fd5b604051632a704bc360e21b81526001600160a01b0384811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9c12f0c90602401602060405180830381865afa158015610a66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8a9190611a43565b6001600160a01b031614610ab1576040516345f0cd7160e01b815260040160405180910390fd5b6000610abc84611401565b9050610ae77f0000000000000000000000000000000000000000000000000000000000000000611465565b60408051606084811b6bffffffffffffffffffffffff1990811660208085018290528a841b8316603486015285516028818703018152604886018752805191012060688501919091527f0000000000000000000000000000000000000000000000000000000000000000831b8216607c8501529185901b1660908301528251608481840301815260a490920190925291935090610bae7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168284611472565b94506000610bbb84611489565b60405163819dc9fb60e01b81529092506001600160a01b038716915063819dc9fb90610c4990899030907373968b9a57c6e53d41345fd57a6e6ae27d6cdb2f90730c30476f66034e11782938df8e4384970b6c9e8a9073d67bdbeff01fc492f1864e61756e5fbb3f17350690739c99dffc1de1aff7e7c1f36fcdd49063a281e18c9086908b90600401611c74565b600060405180830381600087803b158015610c6357600080fd5b505af1158015610c77573d6000803e3d6000fd5b50505050856001600160a01b0316638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610cb657600080fd5b505af1158015610cca573d6000803e3d6000fd5b5050604051631370877b60e11b81526001600160a01b0389811660048301527f00000000000000000000000000000000000000000000000000000000000000001692506326e10ef69150602401600060405180830381600087803b158015610d3157600080fd5b505af1158015610d45573d6000803e3d6000fd5b50506040516308df9b5960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063237e6d649150610d979087908b90600401611952565b600060405180830381600087803b158015610db157600080fd5b505af1158015610dc5573d6000803e3d6000fd5b50506040516314f3279560e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506353cc9e549150610e17908a908990600401611952565b600060405180830381600087803b158015610e3157600080fd5b505af1158015610e45573d6000803e3d6000fd5b50506040516329de95bf60e01b815273539e65190a371ce73244a98dec42ba635cca512c60048201526001600160a01b03881692506329de95bf9150602401600060405180830381600087803b158015610e9e57600080fd5b505af1158015610eb2573d6000803e3d6000fd5b50506040516301ad106960e61b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015288169250636b441a409150602401600060405180830381600087803b158015610f1957600080fd5b505af1158015610f2d573d6000803e3d6000fd5b5050604051631cb2800b60e01b81526001600160a01b0388811660048301527f0000000000000000000000000000000000000000000000000000000000000000169250631cb2800b9150602401600060405180830381600087803b158015610f9457600080fd5b505af1158015610fa8573d6000803e3d6000fd5b50505050610fb587611561565b610fbf878661101b565b604080516001600160a01b0388811682528781166020830152868116828401528916606082015290517f5f7560a5797edc6f72421362defa094d690eb9f7ced3cc5a5c13383502e4fcc59181900360800190a150505050915091565b6040516000602482018190529060440160408051601f198184030181529181526020820180516001600160e01b03166354c49fe960e01b179052519091506000906001600160a01b03851690611072908490611cd8565b6000604051808303816000865af19150503d80600081146110af576040519150601f19603f3d011682016040523d82523d6000602084013e6110b4565b606091505b505090508061114557604051635afc6e4760e11b81526001600160a01b038581166004830152600160248301527f0000000000000000000000000000000000000000000000000000000000000000169063b5f8dc8e90604401600060405180830381600087803b15801561112757600080fd5b505af115801561113b573d6000803e3d6000fd5b5050505050505050565b60005b60088160ff1610156112f8576040516354c49fe960e01b815260ff821660048201526000906001600160a01b038716906354c49fe990602401602060405180830381865afa15801561119e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c29190611a43565b90506001600160a01b0381166111d857506112f8565b604051632474e32f60e11b81526001600160a01b038281166004830152600091908716906348e9c65e9060240160c060405180830381865afa158015611222573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112469190611be8565b60200151905061125582611691565b801561126857506001600160a01b038116155b156112ee5760405163023cb23960e41b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323cb2390906112bb908a908690600401611952565b600060405180830381600087803b1580156112d557600080fd5b505af11580156112e9573d6000803e3d6000fd5b505050505b5050600101611148565b5050505050565b604051633f9095b760e01b81526001600160a01b03821660048201526000908190732f50d538606fa9edd2b11e2446beb18c9d5846bb90633f9095b790602401602060405180830381865afa925050508015611378575060408051601f3d908101601f1916820190925261137591810190611cf4565b60015b6113855750600092915050565b5060019050826001600160a01b0316639c868ac06040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156113e4575060408051601f3d908101601f191682019092526113e191810190611d17565b60015b156113fb5780156113f9575060009392505050565b505b92915050565b6000816001600160a01b03166382c630666040518163ffffffff1660e01b8152600401602060405180830381865afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fb9190611a43565b60006113fb6000836117d3565b60006114816000858585611828565b949350505050565b606080826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156114ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114f29190810190611d34565b9150826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261155a9190810190611d34565b9050915091565b60405163023cb23960e41b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323cb2390906115cf9084907f000000000000000000000000000000000000000000000000000000000000000090600401611952565b600060405180830381600087803b1580156115e957600080fd5b505af11580156115fd573d6000803e3d6000fd5b505060405163023cb23960e41b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506323cb23909150611663908490734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b90600401611952565b600060405180830381600087803b15801561167d57600080fd5b505af11580156112f8573d6000803e3d6000fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614806116ef57506001600160a01b03821673baf05d7aa4129ca14ec45cc9d4103a9ab9a9ff60145b8061171657506001600160a01b0382167373968b9a57c6e53d41345fd57a6e6ae27d6cdb2f145b8061173d57506001600160a01b038216734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b145b1561174a57506000919050565b604051633f9095b760e01b81526001600160a01b0383166004820152732f50d538606fa9edd2b11e2446beb18c9d5846bb90633f9095b790602401602060405180830381865afa9250505080156117be575060408051601f3d908101601f191682019092526117bb91810190611cf4565b60015b6117ca57506001919050565b50600092915050565b60006c5af43d3d93803e602a57fd5bf36021528160145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c84f090508061181d5763301164256000526004601cfd5b600060215292915050565b600060608303516040840351602085035185518060208801018051600283016c5af43d3d93803e606057fd5bf38a528a600d8b035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218b03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8b035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018b03528060f01b835288606c8201604c8c038ef5975050866118f55763301164256000526004601cfd5b90528652601f19860152603f19850152605f19909301929092525092915050565b6001600160a01b038116811461192b57600080fd5b50565b60006020828403121561194057600080fd5b813561194b81611916565b9392505050565b6001600160a01b0392831681529116602082015260400190565b801515811461192b57600080fd5b60008060006060848603121561198f57600080fd5b8335925060208401356119a18161196c565b915060408401356119b18161196c565b809150509250925092565b60008060008060008060c087890312156119d557600080fd5b86516119e081611916565b60208801519096506119f181611916565b6040880151909550611a0281611916565b6060880151909450611a1381611916565b6080880151909350611a2481611916565b60a0880151909250611a358161196c565b809150509295509295509295565b600060208284031215611a5557600080fd5b815161194b81611916565b600060208284031215611a7257600080fd5b5051919050565b60005b83811015611a94578181015183820152602001611a7c565b50506000910152565b60008151808452611ab5816020860160208601611a79565b601f01601f19169290920160200192915050565b60018060a01b0384168152826020820152606060408201526000611af06060830184611a9d565b95945050505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115611b2a57611b2a611af9565b604051601f8501601f19908116603f01168101908282118183101715611b5257611b52611af9565b81604052809350858152868686011115611b6b57600080fd5b611b79866020830187611a79565b5050509392505050565b60008060408385031215611b9657600080fd5b8251611ba18161196c565b602084015190925067ffffffffffffffff811115611bbe57600080fd5b8301601f81018513611bcf57600080fd5b611bde85825160208401611b0f565b9150509250929050565b600060c08284031215611bfa57600080fd5b60405160c0810181811067ffffffffffffffff82111715611c1d57611c1d611af9565b6040528251611c2b81611916565b81526020830151611c3b81611916565b8060208301525060408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b6001600160a01b038981168252888116602083015287811660408301528681166060830152858116608083015284811660a0830152831660c082015261010060e08201819052600090611cc983820185611a9d565b9b9a5050505050505050505050565b60008251611cea818460208701611a79565b9190910192915050565b600060208284031215611d0657600080fd5b815180600f0b811461194b57600080fd5b600060208284031215611d2957600080fd5b815161194b8161196c565b600060208284031215611d4657600080fd5b815167ffffffffffffffff811115611d5d57600080fd5b8201601f81018413611d6e57600080fd5b61148184825160208401611b0f56fea26469706673582212207edead2c1abc9842c639e73d73320b0cc48d235619fd3a6a1e2b02c5e276a15364736f6c6343000813003300000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd520000000000000000000000005940611b5d6f16ea670f032f13e8a09567a8dff5000000000000000000000000c1e4775b3a589784aacd15265ac39d3b3c13ca3c000000000000000000000000d24d1fa18605006d222fbfe8476858b2dfc9a04e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063918f8674116100ad578063bba48a9011610071578063bba48a90146102d7578063d4bba87b146102fe578063f7a6bc7b14610325578063f7c618c114610362578063fb7049cd1461038957600080fd5b8063918f8674146102425780639ed9331814610259578063a77f02451461027a578063a8c62e7614610295578063ba32c619146102bc57600080fd5b80634e8090ce116100f45780634e8090ce146101af57806358a13f08146101d657806362810e1a146101f1578063759cb53b1461020c57806375b0ffd11461022757600080fd5b80631326c2471461012657806322884e2c1461015e578063401c9eec1461017957806348fc3c2d14610194575b600080fd5b61014173baf05d7aa4129ca14ec45cc9d4103a9ab9a9ff6081565b6040516001600160a01b0390911681526020015b60405180910390f35b610141732f50d538606fa9edd2b11e2446beb18c9d5846bb81565b61014173d67bdbeff01fc492f1864e61756e5fbb3f17350681565b610141730c30476f66034e11782938df8e4384970b6c9e8a81565b6101417f000000000000000000000000c1e4775b3a589784aacd15265ac39d3b3c13ca3c81565b610141739c99dffc1de1aff7e7c1f36fcdd49063a281e18c81565b61014173539e65190a371ce73244a98dec42ba635cca512c81565b610141734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b81565b61014173f403c135812408bfbe8713b5a23a04b3d48aae3181565b61024b61271081565b604051908152602001610155565b61026c61026736600461192e565b61039e565b604051610155929190611952565b610141734e795a6f991e305e3f28a3b1b2b4b9789d2cd5a181565b6101417f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd81565b6101417373968b9a57c6e53d41345fd57a6e6ae27d6cdb2f81565b6101417f0000000000000000000000005940611b5d6f16ea670f032f13e8a09567a8dff581565b6101417f000000000000000000000000d24d1fa18605006d222fbfe8476858b2dfc9a04e81565b61033861033336600461197a565b6103b3565b604080516001600160a01b0394851681529284166020840152921691810191909152606001610155565b6101417f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd5281565b61039c61039736600461192e565b610921565b005b6000806103aa836109d2565b91509150915091565b600080600080600073f403c135812408bfbe8713b5a23a04b3d48aae316001600160a01b0316631526fe27896040518263ffffffff1660e01b81526004016103fd91815260200190565b60c060405180830381865afa15801561041a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043e91906119bc565b505050925050915085156104d457604051630ecaea7360e01b81526001600160a01b038316600482015260248101899052734e795a6f991e305e3f28a3b1b2b4b9789d2cd5a190630ecaea73906044016020604051808303816000875af11580156104ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d19190611a43565b92505b861561054a576104e3816109d2565b604080516001600160a01b03848116825283811660208301528681168284015285811660608301528716608082015290519297509095507fb9b8d50b80f9a41ca6bb6a3e3e8fc694fe041d8059f91a504be694b820cd0573919081900360a00190a1610916565b604051632a704bc360e21b81526001600160a01b0382811660048301526000917f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd9091169063a9c12f0c90602401602060405180830381865afa1580156105b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d99190611a43565b604051636eb1769f60e11b8152909150734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b9063dd62ed3e90610635907f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd908590600401611952565b602060405180830381865afa158015610652573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106769190611a60565b600003610772576040516001600160a01b03828116602483015260001960448301527f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd169063b61d27f690734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b9060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b031916815261072893929190600401611ac9565b6000604051808303816000875af1158015610747573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261076f9190810190611b83565b50505b604051632474e32f60e11b8152734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b60048201526000906001600160a01b038316906348e9c65e9060240160c060405180830381865afa1580156107cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f19190611be8565b6020015190506001600160a01b038116610913577f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd6001600160a01b031663b61d27f6836000734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b7f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd60405160240161087e929190611952565b60408051601f198184030181529181526020820180516001600160e01b031663e8de0d4d60e01b1790525160e085901b6001600160e01b03191681526108c993929190600401611ac9565b6000604051808303816000875af11580156108e8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109109190810190611b83565b50505b50505b505093509350939050565b604051632a704bc360e21b81526001600160a01b0382811660048301526000917f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd9091169063a9c12f0c90602401602060405180830381865afa15801561098c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b09190611a43565b90506001600160a01b0381166109c4575050565b6109ce828261101b565b5050565b6000806109de836112ff565b6109fb57604051633859027960e21b815260040160405180910390fd5b604051632a704bc360e21b81526001600160a01b0384811660048301526000917f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd9091169063a9c12f0c90602401602060405180830381865afa158015610a66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8a9190611a43565b6001600160a01b031614610ab1576040516345f0cd7160e01b815260040160405180910390fd5b6000610abc84611401565b9050610ae77f000000000000000000000000c1e4775b3a589784aacd15265ac39d3b3c13ca3c611465565b60408051606084811b6bffffffffffffffffffffffff1990811660208085018290528a841b8316603486015285516028818703018152604886018752805191012060688501919091527f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd831b8216607c8501529185901b1660908301528251608481840301815260a490920190925291935090610bae7f0000000000000000000000005940611b5d6f16ea670f032f13e8a09567a8dff56001600160a01b03168284611472565b94506000610bbb84611489565b60405163819dc9fb60e01b81529092506001600160a01b038716915063819dc9fb90610c4990899030907373968b9a57c6e53d41345fd57a6e6ae27d6cdb2f90730c30476f66034e11782938df8e4384970b6c9e8a9073d67bdbeff01fc492f1864e61756e5fbb3f17350690739c99dffc1de1aff7e7c1f36fcdd49063a281e18c9086908b90600401611c74565b600060405180830381600087803b158015610c6357600080fd5b505af1158015610c77573d6000803e3d6000fd5b50505050856001600160a01b0316638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610cb657600080fd5b505af1158015610cca573d6000803e3d6000fd5b5050604051631370877b60e11b81526001600160a01b0389811660048301527f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd1692506326e10ef69150602401600060405180830381600087803b158015610d3157600080fd5b505af1158015610d45573d6000803e3d6000fd5b50506040516308df9b5960e21b81526001600160a01b037f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd16925063237e6d649150610d979087908b90600401611952565b600060405180830381600087803b158015610db157600080fd5b505af1158015610dc5573d6000803e3d6000fd5b50506040516314f3279560e21b81526001600160a01b037f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd1692506353cc9e549150610e17908a908990600401611952565b600060405180830381600087803b158015610e3157600080fd5b505af1158015610e45573d6000803e3d6000fd5b50506040516329de95bf60e01b815273539e65190a371ce73244a98dec42ba635cca512c60048201526001600160a01b03881692506329de95bf9150602401600060405180830381600087803b158015610e9e57600080fd5b505af1158015610eb2573d6000803e3d6000fd5b50506040516301ad106960e61b81526001600160a01b037f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd8116600483015288169250636b441a409150602401600060405180830381600087803b158015610f1957600080fd5b505af1158015610f2d573d6000803e3d6000fd5b5050604051631cb2800b60e01b81526001600160a01b0388811660048301527f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd169250631cb2800b9150602401600060405180830381600087803b158015610f9457600080fd5b505af1158015610fa8573d6000803e3d6000fd5b50505050610fb587611561565b610fbf878661101b565b604080516001600160a01b0388811682528781166020830152868116828401528916606082015290517f5f7560a5797edc6f72421362defa094d690eb9f7ced3cc5a5c13383502e4fcc59181900360800190a150505050915091565b6040516000602482018190529060440160408051601f198184030181529181526020820180516001600160e01b03166354c49fe960e01b179052519091506000906001600160a01b03851690611072908490611cd8565b6000604051808303816000865af19150503d80600081146110af576040519150601f19603f3d011682016040523d82523d6000602084013e6110b4565b606091505b505090508061114557604051635afc6e4760e11b81526001600160a01b038581166004830152600160248301527f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd169063b5f8dc8e90604401600060405180830381600087803b15801561112757600080fd5b505af115801561113b573d6000803e3d6000fd5b5050505050505050565b60005b60088160ff1610156112f8576040516354c49fe960e01b815260ff821660048201526000906001600160a01b038716906354c49fe990602401602060405180830381865afa15801561119e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c29190611a43565b90506001600160a01b0381166111d857506112f8565b604051632474e32f60e11b81526001600160a01b038281166004830152600091908716906348e9c65e9060240160c060405180830381865afa158015611222573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112469190611be8565b60200151905061125582611691565b801561126857506001600160a01b038116155b156112ee5760405163023cb23960e41b81526001600160a01b037f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd16906323cb2390906112bb908a908690600401611952565b600060405180830381600087803b1580156112d557600080fd5b505af11580156112e9573d6000803e3d6000fd5b505050505b5050600101611148565b5050505050565b604051633f9095b760e01b81526001600160a01b03821660048201526000908190732f50d538606fa9edd2b11e2446beb18c9d5846bb90633f9095b790602401602060405180830381865afa925050508015611378575060408051601f3d908101601f1916820190925261137591810190611cf4565b60015b6113855750600092915050565b5060019050826001600160a01b0316639c868ac06040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156113e4575060408051601f3d908101601f191682019092526113e191810190611d17565b60015b156113fb5780156113f9575060009392505050565b505b92915050565b6000816001600160a01b03166382c630666040518163ffffffff1660e01b8152600401602060405180830381865afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fb9190611a43565b60006113fb6000836117d3565b60006114816000858585611828565b949350505050565b606080826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156114ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114f29190810190611d34565b9150826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261155a9190810190611d34565b9050915091565b60405163023cb23960e41b81526001600160a01b037f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd16906323cb2390906115cf9084907f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd5290600401611952565b600060405180830381600087803b1580156115e957600080fd5b505af11580156115fd573d6000803e3d6000fd5b505060405163023cb23960e41b81526001600160a01b037f00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd1692506323cb23909150611663908490734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b90600401611952565b600060405180830381600087803b15801561167d57600080fd5b505af11580156112f8573d6000803e3d6000fd5b60007f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd526001600160a01b0316826001600160a01b031614806116ef57506001600160a01b03821673baf05d7aa4129ca14ec45cc9d4103a9ab9a9ff60145b8061171657506001600160a01b0382167373968b9a57c6e53d41345fd57a6e6ae27d6cdb2f145b8061173d57506001600160a01b038216734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b145b1561174a57506000919050565b604051633f9095b760e01b81526001600160a01b0383166004820152732f50d538606fa9edd2b11e2446beb18c9d5846bb90633f9095b790602401602060405180830381865afa9250505080156117be575060408051601f3d908101601f191682019092526117bb91810190611cf4565b60015b6117ca57506001919050565b50600092915050565b60006c5af43d3d93803e602a57fd5bf36021528160145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c84f090508061181d5763301164256000526004601cfd5b600060215292915050565b600060608303516040840351602085035185518060208801018051600283016c5af43d3d93803e606057fd5bf38a528a600d8b035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218b03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8b035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018b03528060f01b835288606c8201604c8c038ef5975050866118f55763301164256000526004601cfd5b90528652601f19860152603f19850152605f19909301929092525092915050565b6001600160a01b038116811461192b57600080fd5b50565b60006020828403121561194057600080fd5b813561194b81611916565b9392505050565b6001600160a01b0392831681529116602082015260400190565b801515811461192b57600080fd5b60008060006060848603121561198f57600080fd5b8335925060208401356119a18161196c565b915060408401356119b18161196c565b809150509250925092565b60008060008060008060c087890312156119d557600080fd5b86516119e081611916565b60208801519096506119f181611916565b6040880151909550611a0281611916565b6060880151909450611a1381611916565b6080880151909350611a2481611916565b60a0880151909250611a358161196c565b809150509295509295509295565b600060208284031215611a5557600080fd5b815161194b81611916565b600060208284031215611a7257600080fd5b5051919050565b60005b83811015611a94578181015183820152602001611a7c565b50506000910152565b60008151808452611ab5816020860160208601611a79565b601f01601f19169290920160200192915050565b60018060a01b0384168152826020820152606060408201526000611af06060830184611a9d565b95945050505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115611b2a57611b2a611af9565b604051601f8501601f19908116603f01168101908282118183101715611b5257611b52611af9565b81604052809350858152868686011115611b6b57600080fd5b611b79866020830187611a79565b5050509392505050565b60008060408385031215611b9657600080fd5b8251611ba18161196c565b602084015190925067ffffffffffffffff811115611bbe57600080fd5b8301601f81018513611bcf57600080fd5b611bde85825160208401611b0f565b9150509250929050565b600060c08284031215611bfa57600080fd5b60405160c0810181811067ffffffffffffffff82111715611c1d57611c1d611af9565b6040528251611c2b81611916565b81526020830151611c3b81611916565b8060208301525060408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b6001600160a01b038981168252888116602083015287811660408301528681166060830152858116608083015284811660a0830152831660c082015261010060e08201819052600090611cc983820185611a9d565b9b9a5050505050505050505050565b60008251611cea818460208701611a79565b9190910192915050565b600060208284031215611d0657600080fd5b815180600f0b811461194b57600080fd5b600060208284031215611d2957600080fd5b815161194b8161196c565b600060208284031215611d4657600080fd5b815167ffffffffffffffff811115611d5d57600080fd5b8201601f81018413611d6e57600080fd5b61148184825160208401611b0f56fea26469706673582212207edead2c1abc9842c639e73d73320b0cc48d235619fd3a6a1e2b02c5e276a15364736f6c63430008130033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd520000000000000000000000005940611b5d6f16ea670f032f13e8a09567a8dff5000000000000000000000000c1e4775b3a589784aacd15265ac39d3b3c13ca3c000000000000000000000000d24d1fa18605006d222fbfe8476858b2dfc9a04e

-----Decoded View---------------
Arg [0] : _strategy (address): 0x69D61428d089C2F35Bf6a472F540D0F82D1EA2cd
Arg [1] : _rewardToken (address): 0xD533a949740bb3306d119CC777fa900bA034cd52
Arg [2] : _vaultImplementation (address): 0x5940611B5d6f16eA670F032f13e8A09567A8dFF5
Arg [3] : _liquidityGaugeImplementation (address): 0xc1e4775B3A589784aAcD15265AC39D3B3c13Ca3c
Arg [4] : _rewardReceiverImplementation (address): 0xd24d1Fa18605006D222FBFe8476858b2DFc9A04E

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000069d61428d089c2f35bf6a472f540d0f82d1ea2cd
Arg [1] : 000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd52
Arg [2] : 0000000000000000000000005940611b5d6f16ea670f032f13e8a09567a8dff5
Arg [3] : 000000000000000000000000c1e4775b3a589784aacd15265ac39d3b3c13ca3c
Arg [4] : 000000000000000000000000d24d1fa18605006d222fbfe8476858b2dfc9a04e


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.