ETH Price: $1,975.43 (+0.08%)
 

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
Pause232264062025-08-26 16:12:59179 days ago1756224779IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000061241.29835898
Transfer Ownersh...232254222025-08-26 12:55:47179 days ago1756212947IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000126122.63695382
Set Registrar232254222025-08-26 12:55:47179 days ago1756212947IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000126362.63695382
Set Registrar232254222025-08-26 12:55:47179 days ago1756212947IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000126322.63695382
Set Gateway232254222025-08-26 12:55:47179 days ago1756212947IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000128172.63695382
Set Locker232254222025-08-26 12:55:47179 days ago1756212947IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000128042.63695382
Set Allocator232254222025-08-26 12:55:47179 days ago1756212947IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000128172.63695382
Set Factory232254212025-08-26 12:55:35179 days ago1756212935IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000113872.34692503
Set Strategy232254212025-08-26 12:55:35179 days ago1756212935IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000113922.34692503
Set Accountant232254212025-08-26 12:55:35179 days ago1756212935IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000114522.34692503
Set Fee Receiver232254212025-08-26 12:55:35179 days ago1756212935IN
0x2d8BcE1F...37A64d4fb
0 ETH0.000114132.34692503

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60806040232254152025-08-26 12:54:23179 days ago1756212863  Contract Creation0 ETH
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:
ProtocolController

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion
File 1 of 12 : ProtocolController.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol";

import {IStrategy} from "src/interfaces/IStrategy.sol";
import {IRewardVault} from "src/interfaces/IRewardVault.sol";
import {IProtocolController} from "src/interfaces/IProtocolController.sol";

/// @title ProtocolController.
/// @author Stake DAO
/// @custom:github @stake-dao
/// @custom:contact contact@stakedao.org

/// @notice ProtocolController is the central registry that facilitate the management of protocols integrations.
///         It allows the registration of vaults, management of protocol components (strategy, allocator, accountant, etc.),
///         and provides a permission system for granular access control.
///         It also supports pausing deposits for specific protocols while allowing withdrawals, and shutdown mechanisms per vault or at the protocol level.
contract ProtocolController is IProtocolController, Ownable2Step {
    /// @notice Stores the core components for each protocol integration.
    /// @dev    Each protocol (Curve, Balancer, etc.) has its own set of components.
    struct ProtocolComponents {
        address locker;
        address gateway;
        address strategy;
        address allocator;
        address accountant;
        address feeReceiver;
        address factory;
    }

    /// @notice Links a gauge to its associated vault and protocol.
    /// @dev    A gauge is the external yield source (e.g., Curve gauge) that the vault interacts with.
    struct Gauge {
        address vault;
        address asset;
        address rewardReceiver;
        bytes4 protocolId;
        bool isShutdown;
    }

    //////////////////////////////////////////////////////
    // --- STATE VARIABLES
    //////////////////////////////////////////////////////

    /// @notice Maps each gauge address to its configuration.
    mapping(address => Gauge) public gauge;

    /// @notice Authorized addresses that can register new vaults, such as factory contracts.
    mapping(address => bool) public registrar;

    /// @notice Addresses authorized to manage granular function-level permissions.
    mapping(address => bool) public permissionSetters;

    /// @notice Core components for each protocol, indexed by protocol ID.
    /// @dev    Protocol ID is typically keccak256("PROTOCOL_NAME") truncated to bytes4.
    mapping(bytes4 => ProtocolComponents) internal _protocolComponents;

    /// @notice Whitelisted allocation targets for each gauge.
    /// @dev    Strategies can only allocate funds to these pre-approved destinations (e.g., locker, sidecars).
    mapping(address => mapping(address => bool)) internal _isValidAllocationTargets;

    /// @notice Granular permission system: contract -> caller -> function -> allowed.
    /// @dev    Enables fine-grained access control for specific function calls. Main usecase is to allow router contracts
    ///         to deposit on behalf or claim on behalf of accounts.
    mapping(address => mapping(address => mapping(bytes4 => bool))) internal _permissions;

    /// @notice Per-protocol deposit pause state.
    /// @dev    When true for a protocol, deposits are paused but withdrawals remain functional.
    mapping(bytes4 => bool) public isPaused;

    //////////////////////////////////////////////////////
    // --- ERRORS & EVENTS
    //////////////////////////////////////////////////////

    /// @notice Event emitted when a protocol component is set.
    /// @param  protocolId The protocol identifier.
    /// @param  componentId The component identifier ("Strategy", "Allocator", "Accountant", "FeeReceiver", "Locker", "Gateway", "Factory").
    /// @param  component The component address.
    event ProtocolComponentSet(bytes4 indexed protocolId, string indexed componentId, address indexed component);

    /// @notice Event emitted when a vault is registered.
    /// @param  gauge The gauge address.
    /// @param  vault The vault address.
    /// @param  asset The asset address.
    /// @param  rewardReceiver The reward receiver address.
    /// @param  protocolId The protocol identifier.
    event VaultRegistered(
        address indexed gauge, address indexed vault, address indexed asset, address rewardReceiver, bytes4 protocolId
    );

    /// @notice Event emitted when a gauge is shutdown.
    /// @param  gauge The gauge address that is being shutdown.
    event GaugeShutdown(address indexed gauge);

    /// @notice Event emitted when a gauge is unshut down.
    /// @param  gauge The gauge address that is being unshut down.
    event GaugeUnshutdown(address indexed gauge);

    /// @notice Event emitted when a protocol is shutdown.
    /// @param  protocolId The protocol identifier of the protocol integration that is being shutdown.
    event ProtocolShutdown(bytes4 indexed protocolId);

    /// @notice Event emitted when a permission is set.
    /// @param  target The contract address where the permission is valid.
    /// @param  caller The caller address that is allowed to call the function.
    /// @param  selector The function selector that is being allowed or disallowed.
    /// @param  allowed Whether the caller is allowed to call the function on the contract.
    event PermissionSet(address indexed target, address indexed caller, bytes4 indexed selector, bool allowed);

    /// @notice Event emitted when a registrar is added or removed to the list of authorized registrars.
    /// @param  registrar The registrar address that is being set or unset.
    /// @param  allowed Whether the registrar is allowed to manage vault registrations and rewards tokens.
    event RegistrarPermissionSet(address indexed registrar, bool allowed);

    /// @notice Event emitted when a permission setter is set.
    /// @param  setter The permission setter address that is being set or unset and have rights to set permissions.
    /// @param  allowed Whether the permission setter is allowed to set permissions.
    event PermissionSetterSet(address indexed setter, bool allowed);

    /// @notice Event emitted when deposits are paused for a protocol.
    /// @param  protocolId The protocol identifier of the protocol integration that is being paused.
    event Paused(bytes4 indexed protocolId);

    /// @notice Event emitted when deposits are unpaused for a protocol.
    /// @param  protocolId The protocol identifier of the protocol integration that is being unpaused.
    event Unpaused(bytes4 indexed protocolId);

    /// @notice Thrown when a non-strategy calls a strategy-only function.
    error OnlyStrategy();

    /// @notice Thrown when a non-registrar calls a registrar-only function.
    error OnlyRegistrar();

    /// @notice Thrown when a zero address is used.
    error ZeroAddress();

    /// @notice Thrown when an accountant is already set.
    error AccountantAlreadySet();

    /// @notice Thrown when an unauthorized address tries to set permissions.
    error NotPermissionSetter();

    /// @notice Thrown when trying to unshutdown a gauge that is not shutdown.
    error GaugeNotShutdown();

    /// @notice Thrown when trying to shutdown a gauge that is already shutdown.
    error GaugeAlreadyShutdown();

    /// @notice Thrown when trying to set an allocation target that is already whitelisted.
    error InvalidAllocationTarget();

    //////////////////////////////////////////////////////
    // --- MODIFIERS
    //////////////////////////////////////////////////////

    /// @notice Ensures only authorized registrars or owner can register vaults.
    modifier onlyRegistrar() {
        require(registrar[msg.sender] || msg.sender == owner(), OnlyRegistrar());
        _;
    }

    /// @notice Ensures only authorized permission setters can modify permissions.
    modifier onlyPermissionSetter() {
        require(permissionSetters[msg.sender] || msg.sender == owner(), NotPermissionSetter());
        _;
    }

    constructor(address owner) Ownable(owner) {}

    //////////////////////////////////////////////////////
    // --- PERMISSION MANAGEMENT
    //////////////////////////////////////////////////////

    /// @notice Sets or revokes registrar permission for an address.
    /// @param  registrar_ The registrar address.
    /// @param  allowed Whether the registrar is allowed to register vaults.
    /// @custom:reverts Throws an error if the registrar address is zero.
    function setRegistrar(address registrar_, bool allowed) external onlyOwner {
        require(registrar_ != address(0), ZeroAddress());
        registrar[registrar_] = allowed;
        emit RegistrarPermissionSet(registrar_, allowed);
    }

    /// @notice Sets or revokes permission setter status for an address.
    /// @param  setter The permission setter address.
    /// @param  allowed Whether the address is allowed to set permissions.
    /// @custom:reverts Throws an error if the setter address is zero.
    function setPermissionSetter(address setter, bool allowed) external onlyOwner {
        require(setter != address(0), ZeroAddress());
        permissionSetters[setter] = allowed;
        emit PermissionSetterSet(setter, allowed);
    }

    /// @notice Sets a permission for a contract, caller, and function selector.
    /// @param  target The contract address where the permission is valid.
    /// @param  caller The caller address that is allowed to call the function.
    /// @param  selector The function selector that is being allowed or disallowed.
    /// @param  allowed Whether the caller is allowed to call the function.
    /// @custom:reverts Throws an error if the target or caller address is zero, or if the caller is not a permission setter.
    function setPermission(address target, address caller, bytes4 selector, bool allowed)
        external
        onlyPermissionSetter
    {
        require(target != address(0) && caller != address(0), ZeroAddress());
        _permissions[target][caller][selector] = allowed;
        emit PermissionSet(target, caller, selector, allowed);
    }

    //////////////////////////////////////////////////////
    // --- PROTOCOL COMPONENTS MANAGEMENT
    //////////////////////////////////////////////////////

    /// @notice Sets a protocol strategy.
    /// @param  protocolId The protocol identifier.
    /// @param  strategy The strategy address.
    /// @custom:reverts Throws an error if the _strategy address is zero.
    function setStrategy(bytes4 protocolId, address strategy) external onlyOwner {
        require(strategy != address(0), ZeroAddress());
        _protocolComponents[protocolId].strategy = strategy;
        emit ProtocolComponentSet(protocolId, "Strategy", strategy);
    }

    /// @notice Sets a protocol allocator.
    /// @param  protocolId The protocol identifier.
    /// @param  allocator The allocator address.
    /// @custom:reverts Throws an error if the allocator address is zero.
    function setAllocator(bytes4 protocolId, address allocator) external onlyOwner {
        require(allocator != address(0), ZeroAddress());
        _protocolComponents[protocolId].allocator = allocator;
        emit ProtocolComponentSet(protocolId, "Allocator", allocator);
    }

    /// @notice Sets a protocol accountant.
    /// @dev    Accountant is immutable once set to prevent reward accounting disruption.
    /// @param  protocolId The protocol identifier.
    /// @param  accountant The accountant address.
    /// @custom:reverts Throws an error if the accountant address is zero or if it was previously set.
    function setAccountant(bytes4 protocolId, address accountant) external onlyOwner {
        require(accountant != address(0), ZeroAddress());
        require(_protocolComponents[protocolId].accountant == address(0), AccountantAlreadySet());

        _protocolComponents[protocolId].accountant = accountant;
        emit ProtocolComponentSet(protocolId, "Accountant", accountant);
    }

    /// @notice Sets a protocol fee receiver.
    /// @param  protocolId The protocol identifier.
    /// @param  feeReceiver The fee receiver address.
    /// @custom:reverts Throws an error if the feeReceiver address is zero.
    function setFeeReceiver(bytes4 protocolId, address feeReceiver) external onlyOwner {
        require(feeReceiver != address(0), ZeroAddress());
        _protocolComponents[protocolId].feeReceiver = feeReceiver;
        emit ProtocolComponentSet(protocolId, "FeeReceiver", feeReceiver);
    }

    /// @notice Sets a protocol factory.
    /// @param  protocolId The protocol identifier.
    /// @param  factory The factory address.
    /// @custom:reverts Throws an error if the factory address is zero.
    function setFactory(bytes4 protocolId, address factory) external onlyOwner {
        require(factory != address(0), ZeroAddress());
        _protocolComponents[protocolId].factory = factory;
        emit ProtocolComponentSet(protocolId, "Factory", factory);
    }

    /// @notice Sets a protocol locker.
    /// @param  protocolId The protocol identifier.
    /// @param  locker The locker address.
    /// @custom:reverts Throws an error if the locker address is zero.
    function setLocker(bytes4 protocolId, address locker) external onlyOwner {
        require(locker != address(0), ZeroAddress());
        _protocolComponents[protocolId].locker = locker;
        emit ProtocolComponentSet(protocolId, "Locker", locker);
    }

    /// @notice Sets a protocol gateway
    /// @param  protocolId The protocol identifier
    /// @param  gateway The gateway address
    /// @custom:reverts Throws an error if the gateway address is zero.
    function setGateway(bytes4 protocolId, address gateway) external onlyOwner {
        require(gateway != address(0), ZeroAddress());
        _protocolComponents[protocolId].gateway = gateway;
        emit ProtocolComponentSet(protocolId, "Gateway", gateway);
    }

    //////////////////////////////////////////////////////
    // --- VAULT REGISTRATION & SHUTDOWN
    //////////////////////////////////////////////////////

    /// @notice Registers a vault for a gauge.
    /// @dev    Creates the association between an external gauge and our vault system.
    /// @param  gauge_ The gauge address (external protocol's staking contract).
    /// @param  vault The vault address (our ERC4626 vault).
    /// @param  asset The asset address (Token that users deposit).
    /// @param  rewardReceiver The reward receiver address (receives extra rewards from gauge).
    /// @param  protocolId The protocol identifier for the gauge.
    /// @custom:reverts Throws an error if any of the addresses are zero.
    function registerVault(address gauge_, address vault, address asset, address rewardReceiver, bytes4 protocolId)
        external
        onlyRegistrar
    {
        require(
            gauge_ != address(0) && vault != address(0) && asset != address(0) && rewardReceiver != address(0),
            ZeroAddress()
        );

        Gauge storage g = gauge[gauge_];
        g.vault = vault;
        g.asset = asset;
        g.protocolId = protocolId;
        g.rewardReceiver = rewardReceiver;

        emit VaultRegistered(gauge_, vault, asset, rewardReceiver, protocolId);
    }

    /// @notice Whitelists an allocation target for a gauge.
    /// @dev    Strategies can only send funds to whitelisted targets for security.
    /// @param  gauge The gauge address.
    /// @param  target The target address (e.g., locker or sidecar contract).
    /// @custom:reverts InvalidAllocationTarget if target is already whitelisted.
    function setValidAllocationTarget(address gauge, address target) external onlyRegistrar {
        require(!_isValidAllocationTargets[gauge][target], InvalidAllocationTarget());

        _isValidAllocationTargets[gauge][target] = true;
    }

    /// @notice Removes an allocation target from the whitelist.
    /// @dev    Used when a target is no longer needed or trusted.
    /// @param  gauge The gauge address.
    /// @param  target The target address to remove.
    /// @custom:reverts InvalidAllocationTarget if target is not currently whitelisted.
    function removeValidAllocationTarget(address gauge, address target) external onlyRegistrar {
        require(_isValidAllocationTargets[gauge][target], InvalidAllocationTarget());

        _isValidAllocationTargets[gauge][target] = false;
    }

    /// @notice Emergency shutdown for a specific gauge.
    /// @dev    Prevents new deposits while allowing withdrawals for user fund recovery.
    /// @param  gauge_ The gauge address to shut down.
    /// @custom:reverts GaugeAlreadyShutdown if gauge was previously shutdown.
    function shutdown(address gauge_) external onlyOwner {
        Gauge storage g = gauge[gauge_];
        require(!g.isShutdown, GaugeAlreadyShutdown());

        gauge[gauge_].isShutdown = true;

        // Shutdown the gauge and withdraw all funds.
        IStrategy(_protocolComponents[g.protocolId].strategy).shutdown(gauge_);

        emit GaugeShutdown(gauge_);
    }

    /// @notice Unshuts down a gauge.
    /// @dev    Allows a previously shutdown gauge to resume operations.
    /// @param  gauge_ The gauge address to unshut down.
    /// @custom:reverts GaugeNotShutdown if gauge was not previously shutdown.
    function unshutdown(address gauge_) external onlyOwner {
        require(gauge[gauge_].isShutdown, GaugeNotShutdown());

        // Mark the gauge as not shutdown.
        gauge[gauge_].isShutdown = false;

        // Resume the vault operations.
        IRewardVault(gauge[gauge_].vault).resumeVault();

        emit GaugeUnshutdown(gauge_);
    }

    /// @notice Pauses deposits for a specific protocol.
    /// @dev    Withdrawals remain functional during pause.
    /// @param  protocolId The protocol identifier to pause.
    function pause(bytes4 protocolId) external onlyOwner {
        isPaused[protocolId] = true;
        emit Paused(protocolId);
    }

    /// @notice Unpauses deposits for a specific protocol.
    /// @param  protocolId The protocol identifier to unpause.
    function unpause(bytes4 protocolId) external onlyOwner {
        isPaused[protocolId] = false;
        emit Unpaused(protocolId);
    }

    //////////////////////////////////////////////////////
    // --- VIEW FUNCTIONS
    //////////////////////////////////////////////////////

    /// @notice Returns the strategy address for a protocol.
    /// @param  protocolId The protocol identifier.
    /// @return _ The strategy address.
    function strategy(bytes4 protocolId) external view returns (address) {
        return _protocolComponents[protocolId].strategy;
    }

    /// @notice Returns the allocator address for a protocol.
    /// @param  protocolId The protocol identifier.
    /// @return _ The allocator address.
    function allocator(bytes4 protocolId) external view returns (address) {
        return _protocolComponents[protocolId].allocator;
    }

    /// @notice Returns the accountant address for a protocol.
    /// @param  protocolId The protocol identifier.
    /// @return _ The accountant address.
    function accountant(bytes4 protocolId) external view returns (address) {
        return _protocolComponents[protocolId].accountant;
    }

    /// @notice Returns the fee receiver address for a protocol.
    /// @param  protocolId The protocol identifier.
    /// @return _ The fee receiver address.
    function feeReceiver(bytes4 protocolId) external view returns (address) {
        return _protocolComponents[protocolId].feeReceiver;
    }

    /// @notice Returns the factory address for a protocol.
    /// @param  protocolId The protocol identifier.
    /// @return _ The factory address.
    function factory(bytes4 protocolId) external view returns (address) {
        return _protocolComponents[protocolId].factory;
    }

    /// @notice Returns the locker for a given protocol.
    /// @param  protocolId The protocol identifier.
    /// @return _ The locker address.
    function locker(bytes4 protocolId) external view returns (address) {
        return _protocolComponents[protocolId].locker;
    }

    /// @notice Returns the gateway for a given protocol.
    /// @param  protocolId The protocol identifier.
    /// @return _ The locker address.
    function gateway(bytes4 protocolId) external view returns (address) {
        return _protocolComponents[protocolId].gateway;
    }

    /// @notice Checks if an address is an authorized registrar.
    /// @param  registrar_ The address to check.
    /// @return _ Whether the address is an authorized registrar.
    function isRegistrar(address registrar_) external view returns (bool) {
        return registrar[registrar_];
    }

    /// @notice Returns the vault address for a gauge.
    /// @param  gauge_ The gauge address.
    /// @return _ The vault address.
    function vault(address gauge_) external view returns (address) {
        return gauge[gauge_].vault;
    }

    /// @notice Returns the reward receiver address for a gauge.
    /// @param  gauge_ The gauge address.
    /// @return _ The reward receiver address.
    function rewardReceiver(address gauge_) external view returns (address) {
        return gauge[gauge_].rewardReceiver;
    }

    /// @notice Returns the asset address for a gauge.
    /// @param  gauge_ The gauge address.
    /// @return _ The asset address.
    function asset(address gauge_) external view returns (address) {
        return gauge[gauge_].asset;
    }

    /// @notice Checks if a caller is allowed to call a function on a contract.
    /// @param  target The contract address.
    /// @param  caller The caller address.
    /// @param  selector The function selector.
    /// @return _ Whether the caller is allowed.
    function allowed(address target, address caller, bytes4 selector) external view returns (bool) {
        return _permissions[target][caller][selector] || caller == owner();
    }

    /// @notice Checks if a gauge is shutdown.
    /// @dev    Returns true if either the gauge itself or its protocol is shutdown.
    /// @param  gauge_ The gauge address.
    /// @return _ Whether the gauge is shutdown.
    function isShutdown(address gauge_) external view returns (bool) {
        return gauge[gauge_].isShutdown;
    }

    /// @notice Checks if a target is a valid allocation target for a gauge
    /// @param  gauge The gauge address
    /// @param  target The target address
    /// @return _ Whether the target is a valid allocation target
    function isValidAllocationTarget(address gauge, address target) external view returns (bool) {
        return _isValidAllocationTargets[gauge][target];
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.20;

import {Ownable} from "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This extension of the {Ownable} contract includes a two-step mechanism to transfer
 * ownership, where the new owner must call {acceptOwnership} in order to replace the
 * old one. This can help prevent common mistakes, such as transfers of ownership to
 * incorrect accounts, or to contracts that are unable to interact with the
 * permission system.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     *
     * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert OwnableUnauthorizedAccount(sender);
        }
        _transferOwnership(sender);
    }
}

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

import "src/interfaces/IAllocator.sol";

interface IStrategy {
    /// @notice The policy for harvesting rewards.
    enum HarvestPolicy {
        CHECKPOINT,
        HARVEST
    }

    struct PendingRewards {
        uint128 feeSubjectAmount;
        uint128 totalAmount;
    }

    function deposit(IAllocator.Allocation calldata allocation, HarvestPolicy policy)
        external
        returns (PendingRewards memory pendingRewards);
    function withdraw(IAllocator.Allocation calldata allocation, HarvestPolicy policy, address receiver)
        external
        returns (PendingRewards memory pendingRewards);

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

    function harvest(address gauge, bytes calldata extraData) external returns (PendingRewards memory pendingRewards);
    function flush() external;

    function shutdown(address gauge) external;
}

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

import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IAccountant} from "src/interfaces/IAccountant.sol";

/// @title IRewardVault
/// @notice Interface for the RewardVault contract
interface IRewardVault is IERC4626 {
    function addRewardToken(address rewardsToken, address distributor) external;

    function depositRewards(address _rewardsToken, uint128 _amount) external;

    function deposit(uint256 assets, address receiver, address referrer) external returns (uint256 shares);

    function deposit(address account, address receiver, uint256 assets, address referrer)
        external
        returns (uint256 shares);

    function claim(address[] calldata tokens, address receiver) external returns (uint256[] memory amounts);

    function claim(address account, address[] calldata tokens, address receiver)
        external
        returns (uint256[] memory amounts);

    function getRewardsDistributor(address token) external view returns (address);

    function getLastUpdateTime(address token) external view returns (uint32);

    function getPeriodFinish(address token) external view returns (uint32);

    function getRewardRate(address token) external view returns (uint128);

    function getRewardPerTokenStored(address token) external view returns (uint128);

    function getRewardPerTokenPaid(address token, address account) external view returns (uint128);

    function getClaimable(address token, address account) external view returns (uint128);

    function getRewardTokens() external view returns (address[] memory);

    function lastTimeRewardApplicable(address token) external view returns (uint256);

    function rewardPerToken(address token) external view returns (uint128);

    function earned(address account, address token) external view returns (uint128);

    function isRewardToken(address rewardToken) external view returns (bool);

    function resumeVault() external;

    function gauge() external view returns (address);

    function ACCOUNTANT() external view returns (IAccountant);

    function checkpoint(address account) external;

    function PROTOCOL_ID() external view returns (bytes4);
}

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

interface IProtocolController {
    function vault(address) external view returns (address);
    function asset(address) external view returns (address);
    function rewardReceiver(address) external view returns (address);

    function allowed(address, address, bytes4 selector) external view returns (bool);
    function permissionSetters(address) external view returns (bool);
    function isRegistrar(address) external view returns (bool);

    function strategy(bytes4 protocolId) external view returns (address);
    function allocator(bytes4 protocolId) external view returns (address);
    function accountant(bytes4 protocolId) external view returns (address);
    function feeReceiver(bytes4 protocolId) external view returns (address);
    function factory(bytes4 protocolId) external view returns (address);

    function isPaused(bytes4) external view returns (bool);
    function isShutdown(address) external view returns (bool);

    function registerVault(address _gauge, address _vault, address _asset, address _rewardReceiver, bytes4 _protocolId)
        external;

    function setValidAllocationTarget(address _gauge, address _target) external;
    function removeValidAllocationTarget(address _gauge, address _target) external;
    function isValidAllocationTarget(address _gauge, address _target) external view returns (bool);

    function shutdown(address _gauge) external;

    function setPermissionSetter(address _setter, bool _allowed) external;
    function setPermission(address _contract, address _caller, bytes4 _selector, bool _allowed) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

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

interface IAllocator {
    struct Allocation {
        address asset;
        address gauge;
        address[] targets;
        uint256[] amounts;
    }

    function getDepositAllocation(address asset, address gauge, uint256 amount)
        external
        view
        returns (Allocation memory);
    function getWithdrawalAllocation(address asset, address gauge, uint256 amount)
        external
        view
        returns (Allocation memory);
    function getRebalancedAllocation(address asset, address gauge, uint256 amount)
        external
        view
        returns (Allocation memory);

    function getAllocationTargets(address gauge) external view returns (address[] memory);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4626.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
 * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
 */
interface IERC4626 is IERC20, IERC20Metadata {
    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed sender,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address assetTokenAddress);

    /**
     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
     *
     * - SHOULD include any compounding that occurs from yield.
     * - MUST be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT revert.
     */
    function totalAssets() external view returns (uint256 totalManagedAssets);

    /**
     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToShares(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToAssets(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
     * through a deposit call.
     *
     * - MUST return a limited value if receiver is subject to some deposit limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
     * - MUST NOT revert.
     */
    function maxDeposit(address receiver) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
     *   in the same transaction.
     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewDeposit(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   deposit execution, and are accounted for during deposit.
     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
     * - MUST return a limited value if receiver is subject to some mint limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
     * - MUST NOT revert.
     */
    function maxMint(address receiver) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
     *   same transaction.
     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
     *   would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by minting.
     */
    function previewMint(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
     *   execution, and are accounted for during mint.
     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
     * Vault, through a withdraw call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxWithdraw(address owner) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
     *   called
     *   in the same transaction.
     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   withdraw execution, and are accounted for during withdraw.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
     * through a redeem call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxRedeem(address owner) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
     *   same transaction.
     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
     *   redemption would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
     */
    function previewRedeem(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   redeem execution, and are accounted for during redeem.
     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}

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

import {IStrategy} from "src/interfaces/IStrategy.sol";

interface IAccountant {
    function checkpoint(
        address gauge,
        address from,
        address to,
        uint128 amount,
        IStrategy.PendingRewards calldata pendingRewards,
        IStrategy.HarvestPolicy policy
    ) external;

    function checkpoint(
        address gauge,
        address from,
        address to,
        uint128 amount,
        IStrategy.PendingRewards calldata pendingRewards,
        IStrategy.HarvestPolicy policy,
        address referrer
    ) external;

    function totalSupply(address asset) external view returns (uint128);
    function balanceOf(address asset, address account) external view returns (uint128);

    function claim(address[] calldata _gauges, bytes[] calldata harvestData) external;
    function claim(address[] calldata _gauges, bytes[] calldata harvestData, address receiver) external;
    function claim(address[] calldata _gauges, address account, bytes[] calldata harvestData, address receiver)
        external;

    function claimProtocolFees() external;
    function harvest(address[] calldata _gauges, bytes[] calldata _harvestData, address _receiver) external;

    function REWARD_TOKEN() external view returns (address);

    function getPendingRewards(address vault) external view returns (uint128);
    function getPendingRewards(address vault, address account) external view returns (uint256);

    function SCALING_FACTOR() external view returns (uint128);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

Settings
{
  "remappings": [
    "forge-std/=node_modules/forge-std/",
    "shared/=node_modules/@stake-dao/shared/",
    "layerzerolabs/oft-evm/=node_modules/@layerzerolabs/oft-evm/",
    "@safe/=node_modules/@safe-global/safe-smart-account/",
    "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
    "@interfaces/=node_modules/@stake-dao/interfaces/src/interfaces/",
    "@address-book/=node_modules/@stake-dao/address-book/",
    "@layerzerolabs/=node_modules/@layerzerolabs/",
    "@safe-global/=node_modules/@safe-global/",
    "@solady/=node_modules/@solady/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountantAlreadySet","type":"error"},{"inputs":[],"name":"GaugeAlreadyShutdown","type":"error"},{"inputs":[],"name":"GaugeNotShutdown","type":"error"},{"inputs":[],"name":"InvalidAllocationTarget","type":"error"},{"inputs":[],"name":"NotPermissionSetter","type":"error"},{"inputs":[],"name":"OnlyRegistrar","type":"error"},{"inputs":[],"name":"OnlyStrategy","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeShutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeUnshutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"PermissionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"setter","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"PermissionSetterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"indexed":true,"internalType":"string","name":"componentId","type":"string"},{"indexed":true,"internalType":"address","name":"component","type":"address"}],"name":"ProtocolComponentSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"ProtocolShutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registrar","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"RegistrarPermissionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"address","name":"rewardReceiver","type":"address"},{"indexed":false,"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"VaultRegistered","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"accountant","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"allocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"caller","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"allowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge_","type":"address"}],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"feeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"gateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gauge","outputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"rewardReceiver","type":"address"},{"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"internalType":"bool","name":"isShutdown","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrar_","type":"address"}],"name":"isRegistrar","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge_","type":"address"}],"name":"isShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"target","type":"address"}],"name":"isValidAllocationTarget","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"locker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"permissionSetters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge_","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"rewardReceiver","type":"address"},{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"registerVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"registrar","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"target","type":"address"}],"name":"removeValidAllocationTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge_","type":"address"}],"name":"rewardReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"internalType":"address","name":"accountant","type":"address"}],"name":"setAccountant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"internalType":"address","name":"allocator","type":"address"}],"name":"setAllocator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"internalType":"address","name":"factory","type":"address"}],"name":"setFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"internalType":"address","name":"feeReceiver","type":"address"}],"name":"setFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"internalType":"address","name":"gateway","type":"address"}],"name":"setGateway","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"internalType":"address","name":"locker","type":"address"}],"name":"setLocker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"caller","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"setter","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setPermissionSetter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrar_","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setRegistrar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"},{"internalType":"address","name":"strategy","type":"address"}],"name":"setStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"target","type":"address"}],"name":"setValidAllocationTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge_","type":"address"}],"name":"shutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"protocolId","type":"bytes4"}],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge_","type":"address"}],"name":"unshutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge_","type":"address"}],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561000f575f5ffd5b5060405161182b38038061182b83398101604081905261002e916100d7565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b5050610104565b600180546001600160a01b031916905561008581610088565b50565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100e7575f5ffd5b81516001600160a01b03811681146100fd575f5ffd5b9392505050565b61171a806101115f395ff3fe608060405234801561000f575f5ffd5b506004361061023f575f3560e01c80638604dee611610135578063d5db72eb116100b4578063ef64d76311610079578063ef64d76314610706578063f1710d081461073b578063f2fde38b1461074e578063f46c6c6714610761578063f815c03d14610774575f5ffd5b8063d5db72eb14610682578063d5fe1d13146106ad578063e30c3978146106c0578063e397cb9e146106d1578063e64624fa146106f3575f5ffd5b8063b3890209116100fa578063b3890209146105df578063bac1e94b14610614578063c1bf1dcf14610627578063cce2f3fb1461063a578063cd3985921461064d575f5ffd5b80638604dee6146105685780638da5cb5b1461057b5780639c4667a21461058b578063a1292903146105b9578063b23a56f0146105cc575f5ffd5b80634cf64f33116101c15780637664a7e8116101865780637664a7e81461048f578063791d5d311461052757806379ba50971461053a5780637b730d16146105425780637c663ae214610555575f5ffd5b80634cf64f33146103e8578063622e152d146104235780636720a12014610436578063715018a614610465578063760ad7bb1461046d575f5ffd5b80630c642df1116102075780630c642df11461034557806322f1cf691461035a57806323404e6c1461038c5780633aa83ec71461039f5780634bc5d735146103b2575f5ffd5b80630595a6541461024357806305de62c01461029557806305f533cf146102b857806309b65e66146102ed57806309f142721461030f575b5f5ffd5b610278610251366004611521565b6001600160e01b0319165f908152600560205260409020600201546001600160a01b031690565b6040516001600160a01b0390911681526020015b60405180910390f35b6102a86102a3366004611557565b61079f565b604051901515815260200161028c565b6102786102c6366004611521565b6001600160e01b0319165f908152600560205260409020600101546001600160a01b031690565b6102a86102fb366004611521565b60086020525f908152604090205460ff1681565b61027861031d366004611521565b6001600160e01b0319165f90815260056020819052604090912001546001600160a01b031690565b610358610353366004611597565b6107fa565b005b610278610368366004611521565b6001600160e01b0319165f908152600560205260409020546001600160a01b031690565b61035861039a3660046115c8565b6108b4565b6103586103ad366004611521565b61096c565b6102a86103c03660046115e2565b6001600160a01b03165f9081526002602081905260409091200154600160c01b900460ff1690565b6102a86103f63660046115c8565b6001600160a01b039182165f90815260066020908152604080832093909416825291909152205460ff1690565b6103586104313660046115e2565b6109c0565b6102786104443660046115e2565b6001600160a01b039081165f90815260026020819052604090912001541690565b610358610ab6565b6102a861047b3660046115e2565b60046020525f908152604090205460ff1681565b6104e461049d3660046115e2565b600260208190525f91825260409091208054600182015491909201546001600160a01b039283169291821691811690600160a01b810460e01b90600160c01b900460ff1685565b604080516001600160a01b039687168152948616602086015292909416918301919091526001600160e01b0319166060820152901515608082015260a00161028c565b610358610535366004611597565b610ac9565b610358610b44565b610358610550366004611597565b610b8d565b6103586105633660046115fb565b610c0c565b610358610576366004611597565b610d70565b5f546001600160a01b0316610278565b6102786105993660046115e2565b6001600160a01b039081165f908152600260205260409020600101541690565b6103586105c73660046115c8565b610df0565b6103586105da366004611597565b610eac565b6102786105ed366004611521565b6001600160e01b0319165f908152600560205260409020600601546001600160a01b031690565b610358610622366004611521565b610f2f565b61035861063536600461166b565b610f80565b6103586106483660046115e2565b61100e565b61027861065b366004611521565b6001600160e01b0319165f908152600560205260409020600401546001600160a01b031690565b6102a86106903660046115e2565b6001600160a01b03165f9081526003602052604090205460ff1690565b6103586106bb366004611597565b611135565b6001546001600160a01b0316610278565b6102a86106df3660046115e2565b60036020525f908152604090205460ff1681565b610358610701366004611693565b6111fa565b610278610714366004611521565b6001600160e01b0319165f908152600560205260409020600301546001600160a01b031690565b61035861074936600461166b565b6112ff565b61035861075c3660046115e2565b611385565b61035861076f366004611597565b6113f5565b6102786107823660046115e2565b6001600160a01b039081165f908152600260205260409020541690565b6001600160a01b038084165f90815260076020908152604080832093861683529281528282206001600160e01b03198516835290529081205460ff16806107f257505f546001600160a01b038481169116145b949350505050565b610802611476565b6001600160a01b0381166108295760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060060180546001600160a01b0319166001600160a01b038416908117909155905166466163746f727960c81b81526007015b604051908190038120906001600160e01b03198516907f23a80e454b9e756d9b2ebb718293c09fe024b7adf6ea29070e27dd44dded2464905f90a45050565b335f9081526003602052604090205460ff16806108da57505f546001600160a01b031633145b6108f757604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b038083165f9081526006602090815260408083209385168352929052205460ff1661093c57604051635b7d61af60e01b815260040160405180910390fd5b6001600160a01b039182165f9081526006602090815260408083209390941682529190915220805460ff19169055565b610974611476565b6001600160e01b031981165f81815260086020526040808220805460ff19166001179055517fa5ced19b26a7fec9bfb9e35d68605a1241d62b1ab9a3b862f36a219891fdf5159190a250565b6109c8611476565b6001600160a01b0381165f9081526002602081905260409091200154600160c01b900460ff16610a0b57604051633728287760e11b815260040160405180910390fd5b6001600160a01b038082165f908152600260208190526040808320918201805460ff60c01b19169055905481516395a4cdcb60e01b815291519316926395a4cdcb9260048084019391929182900301818387803b158015610a6a575f5ffd5b505af1158015610a7c573d5f5f3e3d5ffd5b50506040516001600160a01b03841692507fc8e74fb3d97c0a82e22800e7bf8248c005c7aed9376e0893f8a2506ce1992c8991505f90a250565b610abe611476565b610ac75f6114a2565b565b610ad1611476565b6001600160a01b038116610af85760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902080546001600160a01b0319166001600160a01b0384169081179091559051652637b1b5b2b960d11b8152600601610875565b60015433906001600160a01b03168114610b815760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b610b8a816114a2565b50565b610b95611476565b6001600160a01b038116610bbc5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060010180546001600160a01b0319166001600160a01b0384169081179091559051664761746577617960c81b8152600701610875565b335f9081526003602052604090205460ff1680610c3257505f546001600160a01b031633145b610c4f57604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b03851615801590610c6f57506001600160a01b03841615155b8015610c8357506001600160a01b03831615155b8015610c9757506001600160a01b03821615155b610cb45760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038581165f8181526002602081815260409283902080548a87166001600160a01b0319918216811783556001830180548c8a1690841681179091559483018054988b1660e08b901c600160a01b029093166001600160c01b031990991698909817821790975584519081526001600160e01b031988169281019290925294919391927f01faf72cecd22e6d7b9a5d03dfdd583ecc5fd698872639d99a9731c240dbbcdd910160405180910390a4505050505050565b610d78611476565b6001600160a01b038116610d9f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060020180546001600160a01b0319166001600160a01b038416908117909155905167537472617465677960c01b8152600801610875565b335f9081526003602052604090205460ff1680610e1657505f546001600160a01b031633145b610e3357604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b038083165f9081526006602090815260408083209385168352929052205460ff1615610e7957604051635b7d61af60e01b815260040160405180910390fd5b6001600160a01b039182165f9081526006602090815260408083209390941682529190915220805460ff19166001179055565b610eb4611476565b6001600160a01b038116610edb5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560208190526040918290200180546001600160a01b0319166001600160a01b03841690811790915590516a2332b2a932b1b2b4bb32b960a91b8152600b01610875565b610f37611476565b6001600160e01b031981165f81815260086020526040808220805460ff19169055517fb95723779c5dae72a25db18011ec3a516b76f381329525a24e1b97605fb5fe989190a250565b610f88611476565b6001600160a01b038216610faf5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260036020908152604091829020805460ff191685151590811790915591519182527fd6a2ab6b0dbd98e539210db72e366dd068032c1abcfce8b8588bcee82052ded591015b60405180910390a25050565b611016611476565b6001600160a01b0381165f90815260026020819052604090912090810154600160c01b900460ff161561105c57604051631950f80960e21b815260040160405180910390fd5b6001600160a01b038281165f8181526002602081815260408084208301805460ff60c01b1916600160c01b179055868301546001600160e01b0319600160a01b90910460e01b1684526005909152918290200154905163cce2f3fb60e01b815260048101929092529091169063cce2f3fb906024015f604051808303815f87803b1580156110e8575f5ffd5b505af11580156110fa573d5f5f3e3d5ffd5b50506040516001600160a01b03851692507f5303f5e3277cb33a424732af8355550ed3446778c3b06e5cb9b79474773c95f091505f90a25050565b61113d611476565b6001600160a01b0381166111645760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409020600401546001600160a01b0316156111a7576040516314a2174b60e11b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060040180546001600160a01b0319166001600160a01b0384169081179091559051691058d8dbdd5b9d185b9d60b21b8152600a01610875565b335f9081526004602052604090205460ff168061122057505f546001600160a01b031633145b61123d576040516376df46cd60e11b815260040160405180910390fd5b6001600160a01b0384161580159061125d57506001600160a01b03831615155b61127a5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038481165f8181526007602090815260408083209488168084529482528083206001600160e01b0319881680855290835292819020805460ff19168715159081179091559051908152919392917f9d950e4919d7c91068179be3cd6a99029ee6fdfcf4fb488053aa79841b517e03910160405180910390a450505050565b611307611476565b6001600160a01b03821661132e5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260046020908152604091829020805460ff191685151590811790915591519182527f023ef6e50bf1aa5e0ac13acee4206b46ded01551f0247af798912f40d14baa799101611002565b61138d611476565b600180546001600160a01b0383166001600160a01b031990911681179091556113bd5f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6113fd611476565b6001600160a01b0381166114245760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060030180546001600160a01b0319166001600160a01b03841690811790915590516820b63637b1b0ba37b960b91b8152600901610875565b5f546001600160a01b03163314610ac75760405163118cdaa760e01b8152336004820152602401610b78565b600180546001600160a01b0319169055610b8a815f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80356001600160e01b03198116811461151c575f5ffd5b919050565b5f60208284031215611531575f5ffd5b61153a82611505565b9392505050565b80356001600160a01b038116811461151c575f5ffd5b5f5f5f60608486031215611569575f5ffd5b61157284611541565b925061158060208501611541565b915061158e60408501611505565b90509250925092565b5f5f604083850312156115a8575f5ffd5b6115b183611505565b91506115bf60208401611541565b90509250929050565b5f5f604083850312156115d9575f5ffd5b6115b183611541565b5f602082840312156115f2575f5ffd5b61153a82611541565b5f5f5f5f5f60a0868803121561160f575f5ffd5b61161886611541565b945061162660208701611541565b935061163460408701611541565b925061164260608701611541565b915061165060808701611505565b90509295509295909350565b8035801515811461151c575f5ffd5b5f5f6040838503121561167c575f5ffd5b61168583611541565b91506115bf6020840161165c565b5f5f5f5f608085870312156116a6575f5ffd5b6116af85611541565b93506116bd60208601611541565b92506116cb60408601611505565b91506116d96060860161165c565b90509295919450925056fea2646970667358221220043b1ee79e8f9be505cbab8a7b3dbcae4b92e202018e59b4a94efd18f5d43ac564736f6c634300081c0033000000000000000000000000000755fbe4a24d7478bfcfc1e561afce82d1ff62

Deployed Bytecode

0x608060405234801561000f575f5ffd5b506004361061023f575f3560e01c80638604dee611610135578063d5db72eb116100b4578063ef64d76311610079578063ef64d76314610706578063f1710d081461073b578063f2fde38b1461074e578063f46c6c6714610761578063f815c03d14610774575f5ffd5b8063d5db72eb14610682578063d5fe1d13146106ad578063e30c3978146106c0578063e397cb9e146106d1578063e64624fa146106f3575f5ffd5b8063b3890209116100fa578063b3890209146105df578063bac1e94b14610614578063c1bf1dcf14610627578063cce2f3fb1461063a578063cd3985921461064d575f5ffd5b80638604dee6146105685780638da5cb5b1461057b5780639c4667a21461058b578063a1292903146105b9578063b23a56f0146105cc575f5ffd5b80634cf64f33116101c15780637664a7e8116101865780637664a7e81461048f578063791d5d311461052757806379ba50971461053a5780637b730d16146105425780637c663ae214610555575f5ffd5b80634cf64f33146103e8578063622e152d146104235780636720a12014610436578063715018a614610465578063760ad7bb1461046d575f5ffd5b80630c642df1116102075780630c642df11461034557806322f1cf691461035a57806323404e6c1461038c5780633aa83ec71461039f5780634bc5d735146103b2575f5ffd5b80630595a6541461024357806305de62c01461029557806305f533cf146102b857806309b65e66146102ed57806309f142721461030f575b5f5ffd5b610278610251366004611521565b6001600160e01b0319165f908152600560205260409020600201546001600160a01b031690565b6040516001600160a01b0390911681526020015b60405180910390f35b6102a86102a3366004611557565b61079f565b604051901515815260200161028c565b6102786102c6366004611521565b6001600160e01b0319165f908152600560205260409020600101546001600160a01b031690565b6102a86102fb366004611521565b60086020525f908152604090205460ff1681565b61027861031d366004611521565b6001600160e01b0319165f90815260056020819052604090912001546001600160a01b031690565b610358610353366004611597565b6107fa565b005b610278610368366004611521565b6001600160e01b0319165f908152600560205260409020546001600160a01b031690565b61035861039a3660046115c8565b6108b4565b6103586103ad366004611521565b61096c565b6102a86103c03660046115e2565b6001600160a01b03165f9081526002602081905260409091200154600160c01b900460ff1690565b6102a86103f63660046115c8565b6001600160a01b039182165f90815260066020908152604080832093909416825291909152205460ff1690565b6103586104313660046115e2565b6109c0565b6102786104443660046115e2565b6001600160a01b039081165f90815260026020819052604090912001541690565b610358610ab6565b6102a861047b3660046115e2565b60046020525f908152604090205460ff1681565b6104e461049d3660046115e2565b600260208190525f91825260409091208054600182015491909201546001600160a01b039283169291821691811690600160a01b810460e01b90600160c01b900460ff1685565b604080516001600160a01b039687168152948616602086015292909416918301919091526001600160e01b0319166060820152901515608082015260a00161028c565b610358610535366004611597565b610ac9565b610358610b44565b610358610550366004611597565b610b8d565b6103586105633660046115fb565b610c0c565b610358610576366004611597565b610d70565b5f546001600160a01b0316610278565b6102786105993660046115e2565b6001600160a01b039081165f908152600260205260409020600101541690565b6103586105c73660046115c8565b610df0565b6103586105da366004611597565b610eac565b6102786105ed366004611521565b6001600160e01b0319165f908152600560205260409020600601546001600160a01b031690565b610358610622366004611521565b610f2f565b61035861063536600461166b565b610f80565b6103586106483660046115e2565b61100e565b61027861065b366004611521565b6001600160e01b0319165f908152600560205260409020600401546001600160a01b031690565b6102a86106903660046115e2565b6001600160a01b03165f9081526003602052604090205460ff1690565b6103586106bb366004611597565b611135565b6001546001600160a01b0316610278565b6102a86106df3660046115e2565b60036020525f908152604090205460ff1681565b610358610701366004611693565b6111fa565b610278610714366004611521565b6001600160e01b0319165f908152600560205260409020600301546001600160a01b031690565b61035861074936600461166b565b6112ff565b61035861075c3660046115e2565b611385565b61035861076f366004611597565b6113f5565b6102786107823660046115e2565b6001600160a01b039081165f908152600260205260409020541690565b6001600160a01b038084165f90815260076020908152604080832093861683529281528282206001600160e01b03198516835290529081205460ff16806107f257505f546001600160a01b038481169116145b949350505050565b610802611476565b6001600160a01b0381166108295760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060060180546001600160a01b0319166001600160a01b038416908117909155905166466163746f727960c81b81526007015b604051908190038120906001600160e01b03198516907f23a80e454b9e756d9b2ebb718293c09fe024b7adf6ea29070e27dd44dded2464905f90a45050565b335f9081526003602052604090205460ff16806108da57505f546001600160a01b031633145b6108f757604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b038083165f9081526006602090815260408083209385168352929052205460ff1661093c57604051635b7d61af60e01b815260040160405180910390fd5b6001600160a01b039182165f9081526006602090815260408083209390941682529190915220805460ff19169055565b610974611476565b6001600160e01b031981165f81815260086020526040808220805460ff19166001179055517fa5ced19b26a7fec9bfb9e35d68605a1241d62b1ab9a3b862f36a219891fdf5159190a250565b6109c8611476565b6001600160a01b0381165f9081526002602081905260409091200154600160c01b900460ff16610a0b57604051633728287760e11b815260040160405180910390fd5b6001600160a01b038082165f908152600260208190526040808320918201805460ff60c01b19169055905481516395a4cdcb60e01b815291519316926395a4cdcb9260048084019391929182900301818387803b158015610a6a575f5ffd5b505af1158015610a7c573d5f5f3e3d5ffd5b50506040516001600160a01b03841692507fc8e74fb3d97c0a82e22800e7bf8248c005c7aed9376e0893f8a2506ce1992c8991505f90a250565b610abe611476565b610ac75f6114a2565b565b610ad1611476565b6001600160a01b038116610af85760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902080546001600160a01b0319166001600160a01b0384169081179091559051652637b1b5b2b960d11b8152600601610875565b60015433906001600160a01b03168114610b815760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b610b8a816114a2565b50565b610b95611476565b6001600160a01b038116610bbc5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060010180546001600160a01b0319166001600160a01b0384169081179091559051664761746577617960c81b8152600701610875565b335f9081526003602052604090205460ff1680610c3257505f546001600160a01b031633145b610c4f57604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b03851615801590610c6f57506001600160a01b03841615155b8015610c8357506001600160a01b03831615155b8015610c9757506001600160a01b03821615155b610cb45760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038581165f8181526002602081815260409283902080548a87166001600160a01b0319918216811783556001830180548c8a1690841681179091559483018054988b1660e08b901c600160a01b029093166001600160c01b031990991698909817821790975584519081526001600160e01b031988169281019290925294919391927f01faf72cecd22e6d7b9a5d03dfdd583ecc5fd698872639d99a9731c240dbbcdd910160405180910390a4505050505050565b610d78611476565b6001600160a01b038116610d9f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060020180546001600160a01b0319166001600160a01b038416908117909155905167537472617465677960c01b8152600801610875565b335f9081526003602052604090205460ff1680610e1657505f546001600160a01b031633145b610e3357604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b038083165f9081526006602090815260408083209385168352929052205460ff1615610e7957604051635b7d61af60e01b815260040160405180910390fd5b6001600160a01b039182165f9081526006602090815260408083209390941682529190915220805460ff19166001179055565b610eb4611476565b6001600160a01b038116610edb5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560208190526040918290200180546001600160a01b0319166001600160a01b03841690811790915590516a2332b2a932b1b2b4bb32b960a91b8152600b01610875565b610f37611476565b6001600160e01b031981165f81815260086020526040808220805460ff19169055517fb95723779c5dae72a25db18011ec3a516b76f381329525a24e1b97605fb5fe989190a250565b610f88611476565b6001600160a01b038216610faf5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260036020908152604091829020805460ff191685151590811790915591519182527fd6a2ab6b0dbd98e539210db72e366dd068032c1abcfce8b8588bcee82052ded591015b60405180910390a25050565b611016611476565b6001600160a01b0381165f90815260026020819052604090912090810154600160c01b900460ff161561105c57604051631950f80960e21b815260040160405180910390fd5b6001600160a01b038281165f8181526002602081815260408084208301805460ff60c01b1916600160c01b179055868301546001600160e01b0319600160a01b90910460e01b1684526005909152918290200154905163cce2f3fb60e01b815260048101929092529091169063cce2f3fb906024015f604051808303815f87803b1580156110e8575f5ffd5b505af11580156110fa573d5f5f3e3d5ffd5b50506040516001600160a01b03851692507f5303f5e3277cb33a424732af8355550ed3446778c3b06e5cb9b79474773c95f091505f90a25050565b61113d611476565b6001600160a01b0381166111645760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409020600401546001600160a01b0316156111a7576040516314a2174b60e11b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060040180546001600160a01b0319166001600160a01b0384169081179091559051691058d8dbdd5b9d185b9d60b21b8152600a01610875565b335f9081526004602052604090205460ff168061122057505f546001600160a01b031633145b61123d576040516376df46cd60e11b815260040160405180910390fd5b6001600160a01b0384161580159061125d57506001600160a01b03831615155b61127a5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038481165f8181526007602090815260408083209488168084529482528083206001600160e01b0319881680855290835292819020805460ff19168715159081179091559051908152919392917f9d950e4919d7c91068179be3cd6a99029ee6fdfcf4fb488053aa79841b517e03910160405180910390a450505050565b611307611476565b6001600160a01b03821661132e5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260046020908152604091829020805460ff191685151590811790915591519182527f023ef6e50bf1aa5e0ac13acee4206b46ded01551f0247af798912f40d14baa799101611002565b61138d611476565b600180546001600160a01b0383166001600160a01b031990911681179091556113bd5f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6113fd611476565b6001600160a01b0381166114245760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060030180546001600160a01b0319166001600160a01b03841690811790915590516820b63637b1b0ba37b960b91b8152600901610875565b5f546001600160a01b03163314610ac75760405163118cdaa760e01b8152336004820152602401610b78565b600180546001600160a01b0319169055610b8a815f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80356001600160e01b03198116811461151c575f5ffd5b919050565b5f60208284031215611531575f5ffd5b61153a82611505565b9392505050565b80356001600160a01b038116811461151c575f5ffd5b5f5f5f60608486031215611569575f5ffd5b61157284611541565b925061158060208501611541565b915061158e60408501611505565b90509250925092565b5f5f604083850312156115a8575f5ffd5b6115b183611505565b91506115bf60208401611541565b90509250929050565b5f5f604083850312156115d9575f5ffd5b6115b183611541565b5f602082840312156115f2575f5ffd5b61153a82611541565b5f5f5f5f5f60a0868803121561160f575f5ffd5b61161886611541565b945061162660208701611541565b935061163460408701611541565b925061164260608701611541565b915061165060808701611505565b90509295509295909350565b8035801515811461151c575f5ffd5b5f5f6040838503121561167c575f5ffd5b61168583611541565b91506115bf6020840161165c565b5f5f5f5f608085870312156116a6575f5ffd5b6116af85611541565b93506116bd60208601611541565b92506116cb60408601611505565b91506116d96060860161165c565b90509295919450925056fea2646970667358221220043b1ee79e8f9be505cbab8a7b3dbcae4b92e202018e59b4a94efd18f5d43ac564736f6c634300081c0033

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

000000000000000000000000000755fbe4a24d7478bfcfc1e561afce82d1ff62

-----Decoded View---------------
Arg [0] : owner (address): 0x000755Fbe4A24d7478bfcFC1E561AfCE82d1ff62

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000000755fbe4a24d7478bfcfc1e561afce82d1ff62


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.