S Price: $0.06747 (-3.66%)
Gas: 55 Gwei

Contract

0x8D34Ee08482c65F0871ECc160e3C343a0deC728a

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Set Strategy408948142025-07-30 15:13:10179 days ago1753888390IN
0x8D34Ee08...a0deC728a
0 S0.0017434853
Transfer Ownersh...400164332025-07-24 12:20:09186 days ago1753359609IN
0x8D34Ee08...a0deC728a
0 S0.0028675157.75
Set Registrar400164332025-07-24 12:20:09186 days ago1753359609IN
0x8D34Ee08...a0deC728a
0 S0.0028727757.75
Set Gateway400164332025-07-24 12:20:09186 days ago1753359609IN
0x8D34Ee08...a0deC728a
0 S0.0029140657.75
Set Locker400164332025-07-24 12:20:09186 days ago1753359609IN
0x8D34Ee08...a0deC728a
0 S0.0029110657.75
Set Allocator400164272025-07-24 12:20:06186 days ago1753359606IN
0x8D34Ee08...a0deC728a
0 S0.0029139457.75
Set Factory400164272025-07-24 12:20:06186 days ago1753359606IN
0x8D34Ee08...a0deC728a
0 S0.0029322557.75
Set Strategy400164272025-07-24 12:20:06186 days ago1753359606IN
0x8D34Ee08...a0deC728a
0 S0.0029101357.75
Set Accountant400164202025-07-24 12:20:02186 days ago1753359602IN
0x8D34Ee08...a0deC728a
0 S0.0029253857.75
Set Fee Receiver400164152025-07-24 12:20:00186 days ago1753359600IN
0x8D34Ee08...a0deC728a
0 S0.0029384357.75

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
400164152025-07-24 12:20:00186 days ago1753359600  Contract Creation0 S
Cross-Chain Transactions
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 8 : 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 [email protected]

/// @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;

/// @title IRewardVault
/// @notice Interface for the RewardVault contract
interface IRewardVault {
    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;
}

/// 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.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;
    }
}

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,
  "libraries": {}
}

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"}]

608060405234801561000f575f5ffd5b5060405161182b38038061182b83398101604081905261002e916100d7565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b5050610104565b600180546001600160a01b031916905561008581610088565b50565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100e7575f5ffd5b81516001600160a01b03811681146100fd575f5ffd5b9392505050565b61171a806101115f395ff3fe608060405234801561000f575f5ffd5b506004361061023f575f3560e01c80638604dee611610135578063d5db72eb116100b4578063ef64d76311610079578063ef64d76314610706578063f1710d081461073b578063f2fde38b1461074e578063f46c6c6714610761578063f815c03d14610774575f5ffd5b8063d5db72eb14610682578063d5fe1d13146106ad578063e30c3978146106c0578063e397cb9e146106d1578063e64624fa146106f3575f5ffd5b8063b3890209116100fa578063b3890209146105df578063bac1e94b14610614578063c1bf1dcf14610627578063cce2f3fb1461063a578063cd3985921461064d575f5ffd5b80638604dee6146105685780638da5cb5b1461057b5780639c4667a21461058b578063a1292903146105b9578063b23a56f0146105cc575f5ffd5b80634cf64f33116101c15780637664a7e8116101865780637664a7e81461048f578063791d5d311461052757806379ba50971461053a5780637b730d16146105425780637c663ae214610555575f5ffd5b80634cf64f33146103e8578063622e152d146104235780636720a12014610436578063715018a614610465578063760ad7bb1461046d575f5ffd5b80630c642df1116102075780630c642df11461034557806322f1cf691461035a57806323404e6c1461038c5780633aa83ec71461039f5780634bc5d735146103b2575f5ffd5b80630595a6541461024357806305de62c01461029557806305f533cf146102b857806309b65e66146102ed57806309f142721461030f575b5f5ffd5b610278610251366004611521565b6001600160e01b0319165f908152600560205260409020600201546001600160a01b031690565b6040516001600160a01b0390911681526020015b60405180910390f35b6102a86102a3366004611557565b61079f565b604051901515815260200161028c565b6102786102c6366004611521565b6001600160e01b0319165f908152600560205260409020600101546001600160a01b031690565b6102a86102fb366004611521565b60086020525f908152604090205460ff1681565b61027861031d366004611521565b6001600160e01b0319165f90815260056020819052604090912001546001600160a01b031690565b610358610353366004611597565b6107fa565b005b610278610368366004611521565b6001600160e01b0319165f908152600560205260409020546001600160a01b031690565b61035861039a3660046115c8565b6108b4565b6103586103ad366004611521565b61096c565b6102a86103c03660046115e2565b6001600160a01b03165f9081526002602081905260409091200154600160c01b900460ff1690565b6102a86103f63660046115c8565b6001600160a01b039182165f90815260066020908152604080832093909416825291909152205460ff1690565b6103586104313660046115e2565b6109c0565b6102786104443660046115e2565b6001600160a01b039081165f90815260026020819052604090912001541690565b610358610ab6565b6102a861047b3660046115e2565b60046020525f908152604090205460ff1681565b6104e461049d3660046115e2565b600260208190525f91825260409091208054600182015491909201546001600160a01b039283169291821691811690600160a01b810460e01b90600160c01b900460ff1685565b604080516001600160a01b039687168152948616602086015292909416918301919091526001600160e01b0319166060820152901515608082015260a00161028c565b610358610535366004611597565b610ac9565b610358610b44565b610358610550366004611597565b610b8d565b6103586105633660046115fb565b610c0c565b610358610576366004611597565b610d70565b5f546001600160a01b0316610278565b6102786105993660046115e2565b6001600160a01b039081165f908152600260205260409020600101541690565b6103586105c73660046115c8565b610df0565b6103586105da366004611597565b610eac565b6102786105ed366004611521565b6001600160e01b0319165f908152600560205260409020600601546001600160a01b031690565b610358610622366004611521565b610f2f565b61035861063536600461166b565b610f80565b6103586106483660046115e2565b61100e565b61027861065b366004611521565b6001600160e01b0319165f908152600560205260409020600401546001600160a01b031690565b6102a86106903660046115e2565b6001600160a01b03165f9081526003602052604090205460ff1690565b6103586106bb366004611597565b611135565b6001546001600160a01b0316610278565b6102a86106df3660046115e2565b60036020525f908152604090205460ff1681565b610358610701366004611693565b6111fa565b610278610714366004611521565b6001600160e01b0319165f908152600560205260409020600301546001600160a01b031690565b61035861074936600461166b565b6112ff565b61035861075c3660046115e2565b611385565b61035861076f366004611597565b6113f5565b6102786107823660046115e2565b6001600160a01b039081165f908152600260205260409020541690565b6001600160a01b038084165f90815260076020908152604080832093861683529281528282206001600160e01b03198516835290529081205460ff16806107f257505f546001600160a01b038481169116145b949350505050565b610802611476565b6001600160a01b0381166108295760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060060180546001600160a01b0319166001600160a01b038416908117909155905166466163746f727960c81b81526007015b604051908190038120906001600160e01b03198516907f23a80e454b9e756d9b2ebb718293c09fe024b7adf6ea29070e27dd44dded2464905f90a45050565b335f9081526003602052604090205460ff16806108da57505f546001600160a01b031633145b6108f757604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b038083165f9081526006602090815260408083209385168352929052205460ff1661093c57604051635b7d61af60e01b815260040160405180910390fd5b6001600160a01b039182165f9081526006602090815260408083209390941682529190915220805460ff19169055565b610974611476565b6001600160e01b031981165f81815260086020526040808220805460ff19166001179055517fa5ced19b26a7fec9bfb9e35d68605a1241d62b1ab9a3b862f36a219891fdf5159190a250565b6109c8611476565b6001600160a01b0381165f9081526002602081905260409091200154600160c01b900460ff16610a0b57604051633728287760e11b815260040160405180910390fd5b6001600160a01b038082165f908152600260208190526040808320918201805460ff60c01b19169055905481516395a4cdcb60e01b815291519316926395a4cdcb9260048084019391929182900301818387803b158015610a6a575f5ffd5b505af1158015610a7c573d5f5f3e3d5ffd5b50506040516001600160a01b03841692507fc8e74fb3d97c0a82e22800e7bf8248c005c7aed9376e0893f8a2506ce1992c8991505f90a250565b610abe611476565b610ac75f6114a2565b565b610ad1611476565b6001600160a01b038116610af85760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902080546001600160a01b0319166001600160a01b0384169081179091559051652637b1b5b2b960d11b8152600601610875565b60015433906001600160a01b03168114610b815760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b610b8a816114a2565b50565b610b95611476565b6001600160a01b038116610bbc5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060010180546001600160a01b0319166001600160a01b0384169081179091559051664761746577617960c81b8152600701610875565b335f9081526003602052604090205460ff1680610c3257505f546001600160a01b031633145b610c4f57604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b03851615801590610c6f57506001600160a01b03841615155b8015610c8357506001600160a01b03831615155b8015610c9757506001600160a01b03821615155b610cb45760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038581165f8181526002602081815260409283902080548a87166001600160a01b0319918216811783556001830180548c8a1690841681179091559483018054988b1660e08b901c600160a01b029093166001600160c01b031990991698909817821790975584519081526001600160e01b031988169281019290925294919391927f01faf72cecd22e6d7b9a5d03dfdd583ecc5fd698872639d99a9731c240dbbcdd910160405180910390a4505050505050565b610d78611476565b6001600160a01b038116610d9f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060020180546001600160a01b0319166001600160a01b038416908117909155905167537472617465677960c01b8152600801610875565b335f9081526003602052604090205460ff1680610e1657505f546001600160a01b031633145b610e3357604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b038083165f9081526006602090815260408083209385168352929052205460ff1615610e7957604051635b7d61af60e01b815260040160405180910390fd5b6001600160a01b039182165f9081526006602090815260408083209390941682529190915220805460ff19166001179055565b610eb4611476565b6001600160a01b038116610edb5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560208190526040918290200180546001600160a01b0319166001600160a01b03841690811790915590516a2332b2a932b1b2b4bb32b960a91b8152600b01610875565b610f37611476565b6001600160e01b031981165f81815260086020526040808220805460ff19169055517fb95723779c5dae72a25db18011ec3a516b76f381329525a24e1b97605fb5fe989190a250565b610f88611476565b6001600160a01b038216610faf5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260036020908152604091829020805460ff191685151590811790915591519182527fd6a2ab6b0dbd98e539210db72e366dd068032c1abcfce8b8588bcee82052ded591015b60405180910390a25050565b611016611476565b6001600160a01b0381165f90815260026020819052604090912090810154600160c01b900460ff161561105c57604051631950f80960e21b815260040160405180910390fd5b6001600160a01b038281165f8181526002602081815260408084208301805460ff60c01b1916600160c01b179055868301546001600160e01b0319600160a01b90910460e01b1684526005909152918290200154905163cce2f3fb60e01b815260048101929092529091169063cce2f3fb906024015f604051808303815f87803b1580156110e8575f5ffd5b505af11580156110fa573d5f5f3e3d5ffd5b50506040516001600160a01b03851692507f5303f5e3277cb33a424732af8355550ed3446778c3b06e5cb9b79474773c95f091505f90a25050565b61113d611476565b6001600160a01b0381166111645760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409020600401546001600160a01b0316156111a7576040516314a2174b60e11b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060040180546001600160a01b0319166001600160a01b0384169081179091559051691058d8dbdd5b9d185b9d60b21b8152600a01610875565b335f9081526004602052604090205460ff168061122057505f546001600160a01b031633145b61123d576040516376df46cd60e11b815260040160405180910390fd5b6001600160a01b0384161580159061125d57506001600160a01b03831615155b61127a5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038481165f8181526007602090815260408083209488168084529482528083206001600160e01b0319881680855290835292819020805460ff19168715159081179091559051908152919392917f9d950e4919d7c91068179be3cd6a99029ee6fdfcf4fb488053aa79841b517e03910160405180910390a450505050565b611307611476565b6001600160a01b03821661132e5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260046020908152604091829020805460ff191685151590811790915591519182527f023ef6e50bf1aa5e0ac13acee4206b46ded01551f0247af798912f40d14baa799101611002565b61138d611476565b600180546001600160a01b0383166001600160a01b031990911681179091556113bd5f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6113fd611476565b6001600160a01b0381166114245760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060030180546001600160a01b0319166001600160a01b03841690811790915590516820b63637b1b0ba37b960b91b8152600901610875565b5f546001600160a01b03163314610ac75760405163118cdaa760e01b8152336004820152602401610b78565b600180546001600160a01b0319169055610b8a815f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80356001600160e01b03198116811461151c575f5ffd5b919050565b5f60208284031215611531575f5ffd5b61153a82611505565b9392505050565b80356001600160a01b038116811461151c575f5ffd5b5f5f5f60608486031215611569575f5ffd5b61157284611541565b925061158060208501611541565b915061158e60408501611505565b90509250925092565b5f5f604083850312156115a8575f5ffd5b6115b183611505565b91506115bf60208401611541565b90509250929050565b5f5f604083850312156115d9575f5ffd5b6115b183611541565b5f602082840312156115f2575f5ffd5b61153a82611541565b5f5f5f5f5f60a0868803121561160f575f5ffd5b61161886611541565b945061162660208701611541565b935061163460408701611541565b925061164260608701611541565b915061165060808701611505565b90509295509295909350565b8035801515811461151c575f5ffd5b5f5f6040838503121561167c575f5ffd5b61168583611541565b91506115bf6020840161165c565b5f5f5f5f608085870312156116a6575f5ffd5b6116af85611541565b93506116bd60208601611541565b92506116cb60408601611505565b91506116d96060860161165c565b90509295919450925056fea264697066735822122016de7a645609ae3633603ad230bbc5973e6b61807f2e7ff347699266333b14bb64736f6c634300081c0033000000000000000000000000000755fbe4a24d7478bfcfc1e561afce82d1ff62

Deployed Bytecode

0x608060405234801561000f575f5ffd5b506004361061023f575f3560e01c80638604dee611610135578063d5db72eb116100b4578063ef64d76311610079578063ef64d76314610706578063f1710d081461073b578063f2fde38b1461074e578063f46c6c6714610761578063f815c03d14610774575f5ffd5b8063d5db72eb14610682578063d5fe1d13146106ad578063e30c3978146106c0578063e397cb9e146106d1578063e64624fa146106f3575f5ffd5b8063b3890209116100fa578063b3890209146105df578063bac1e94b14610614578063c1bf1dcf14610627578063cce2f3fb1461063a578063cd3985921461064d575f5ffd5b80638604dee6146105685780638da5cb5b1461057b5780639c4667a21461058b578063a1292903146105b9578063b23a56f0146105cc575f5ffd5b80634cf64f33116101c15780637664a7e8116101865780637664a7e81461048f578063791d5d311461052757806379ba50971461053a5780637b730d16146105425780637c663ae214610555575f5ffd5b80634cf64f33146103e8578063622e152d146104235780636720a12014610436578063715018a614610465578063760ad7bb1461046d575f5ffd5b80630c642df1116102075780630c642df11461034557806322f1cf691461035a57806323404e6c1461038c5780633aa83ec71461039f5780634bc5d735146103b2575f5ffd5b80630595a6541461024357806305de62c01461029557806305f533cf146102b857806309b65e66146102ed57806309f142721461030f575b5f5ffd5b610278610251366004611521565b6001600160e01b0319165f908152600560205260409020600201546001600160a01b031690565b6040516001600160a01b0390911681526020015b60405180910390f35b6102a86102a3366004611557565b61079f565b604051901515815260200161028c565b6102786102c6366004611521565b6001600160e01b0319165f908152600560205260409020600101546001600160a01b031690565b6102a86102fb366004611521565b60086020525f908152604090205460ff1681565b61027861031d366004611521565b6001600160e01b0319165f90815260056020819052604090912001546001600160a01b031690565b610358610353366004611597565b6107fa565b005b610278610368366004611521565b6001600160e01b0319165f908152600560205260409020546001600160a01b031690565b61035861039a3660046115c8565b6108b4565b6103586103ad366004611521565b61096c565b6102a86103c03660046115e2565b6001600160a01b03165f9081526002602081905260409091200154600160c01b900460ff1690565b6102a86103f63660046115c8565b6001600160a01b039182165f90815260066020908152604080832093909416825291909152205460ff1690565b6103586104313660046115e2565b6109c0565b6102786104443660046115e2565b6001600160a01b039081165f90815260026020819052604090912001541690565b610358610ab6565b6102a861047b3660046115e2565b60046020525f908152604090205460ff1681565b6104e461049d3660046115e2565b600260208190525f91825260409091208054600182015491909201546001600160a01b039283169291821691811690600160a01b810460e01b90600160c01b900460ff1685565b604080516001600160a01b039687168152948616602086015292909416918301919091526001600160e01b0319166060820152901515608082015260a00161028c565b610358610535366004611597565b610ac9565b610358610b44565b610358610550366004611597565b610b8d565b6103586105633660046115fb565b610c0c565b610358610576366004611597565b610d70565b5f546001600160a01b0316610278565b6102786105993660046115e2565b6001600160a01b039081165f908152600260205260409020600101541690565b6103586105c73660046115c8565b610df0565b6103586105da366004611597565b610eac565b6102786105ed366004611521565b6001600160e01b0319165f908152600560205260409020600601546001600160a01b031690565b610358610622366004611521565b610f2f565b61035861063536600461166b565b610f80565b6103586106483660046115e2565b61100e565b61027861065b366004611521565b6001600160e01b0319165f908152600560205260409020600401546001600160a01b031690565b6102a86106903660046115e2565b6001600160a01b03165f9081526003602052604090205460ff1690565b6103586106bb366004611597565b611135565b6001546001600160a01b0316610278565b6102a86106df3660046115e2565b60036020525f908152604090205460ff1681565b610358610701366004611693565b6111fa565b610278610714366004611521565b6001600160e01b0319165f908152600560205260409020600301546001600160a01b031690565b61035861074936600461166b565b6112ff565b61035861075c3660046115e2565b611385565b61035861076f366004611597565b6113f5565b6102786107823660046115e2565b6001600160a01b039081165f908152600260205260409020541690565b6001600160a01b038084165f90815260076020908152604080832093861683529281528282206001600160e01b03198516835290529081205460ff16806107f257505f546001600160a01b038481169116145b949350505050565b610802611476565b6001600160a01b0381166108295760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060060180546001600160a01b0319166001600160a01b038416908117909155905166466163746f727960c81b81526007015b604051908190038120906001600160e01b03198516907f23a80e454b9e756d9b2ebb718293c09fe024b7adf6ea29070e27dd44dded2464905f90a45050565b335f9081526003602052604090205460ff16806108da57505f546001600160a01b031633145b6108f757604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b038083165f9081526006602090815260408083209385168352929052205460ff1661093c57604051635b7d61af60e01b815260040160405180910390fd5b6001600160a01b039182165f9081526006602090815260408083209390941682529190915220805460ff19169055565b610974611476565b6001600160e01b031981165f81815260086020526040808220805460ff19166001179055517fa5ced19b26a7fec9bfb9e35d68605a1241d62b1ab9a3b862f36a219891fdf5159190a250565b6109c8611476565b6001600160a01b0381165f9081526002602081905260409091200154600160c01b900460ff16610a0b57604051633728287760e11b815260040160405180910390fd5b6001600160a01b038082165f908152600260208190526040808320918201805460ff60c01b19169055905481516395a4cdcb60e01b815291519316926395a4cdcb9260048084019391929182900301818387803b158015610a6a575f5ffd5b505af1158015610a7c573d5f5f3e3d5ffd5b50506040516001600160a01b03841692507fc8e74fb3d97c0a82e22800e7bf8248c005c7aed9376e0893f8a2506ce1992c8991505f90a250565b610abe611476565b610ac75f6114a2565b565b610ad1611476565b6001600160a01b038116610af85760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902080546001600160a01b0319166001600160a01b0384169081179091559051652637b1b5b2b960d11b8152600601610875565b60015433906001600160a01b03168114610b815760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b610b8a816114a2565b50565b610b95611476565b6001600160a01b038116610bbc5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060010180546001600160a01b0319166001600160a01b0384169081179091559051664761746577617960c81b8152600701610875565b335f9081526003602052604090205460ff1680610c3257505f546001600160a01b031633145b610c4f57604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b03851615801590610c6f57506001600160a01b03841615155b8015610c8357506001600160a01b03831615155b8015610c9757506001600160a01b03821615155b610cb45760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038581165f8181526002602081815260409283902080548a87166001600160a01b0319918216811783556001830180548c8a1690841681179091559483018054988b1660e08b901c600160a01b029093166001600160c01b031990991698909817821790975584519081526001600160e01b031988169281019290925294919391927f01faf72cecd22e6d7b9a5d03dfdd583ecc5fd698872639d99a9731c240dbbcdd910160405180910390a4505050505050565b610d78611476565b6001600160a01b038116610d9f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060020180546001600160a01b0319166001600160a01b038416908117909155905167537472617465677960c01b8152600801610875565b335f9081526003602052604090205460ff1680610e1657505f546001600160a01b031633145b610e3357604051632fed761f60e01b815260040160405180910390fd5b6001600160a01b038083165f9081526006602090815260408083209385168352929052205460ff1615610e7957604051635b7d61af60e01b815260040160405180910390fd5b6001600160a01b039182165f9081526006602090815260408083209390941682529190915220805460ff19166001179055565b610eb4611476565b6001600160a01b038116610edb5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560208190526040918290200180546001600160a01b0319166001600160a01b03841690811790915590516a2332b2a932b1b2b4bb32b960a91b8152600b01610875565b610f37611476565b6001600160e01b031981165f81815260086020526040808220805460ff19169055517fb95723779c5dae72a25db18011ec3a516b76f381329525a24e1b97605fb5fe989190a250565b610f88611476565b6001600160a01b038216610faf5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260036020908152604091829020805460ff191685151590811790915591519182527fd6a2ab6b0dbd98e539210db72e366dd068032c1abcfce8b8588bcee82052ded591015b60405180910390a25050565b611016611476565b6001600160a01b0381165f90815260026020819052604090912090810154600160c01b900460ff161561105c57604051631950f80960e21b815260040160405180910390fd5b6001600160a01b038281165f8181526002602081815260408084208301805460ff60c01b1916600160c01b179055868301546001600160e01b0319600160a01b90910460e01b1684526005909152918290200154905163cce2f3fb60e01b815260048101929092529091169063cce2f3fb906024015f604051808303815f87803b1580156110e8575f5ffd5b505af11580156110fa573d5f5f3e3d5ffd5b50506040516001600160a01b03851692507f5303f5e3277cb33a424732af8355550ed3446778c3b06e5cb9b79474773c95f091505f90a25050565b61113d611476565b6001600160a01b0381166111645760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409020600401546001600160a01b0316156111a7576040516314a2174b60e11b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060040180546001600160a01b0319166001600160a01b0384169081179091559051691058d8dbdd5b9d185b9d60b21b8152600a01610875565b335f9081526004602052604090205460ff168061122057505f546001600160a01b031633145b61123d576040516376df46cd60e11b815260040160405180910390fd5b6001600160a01b0384161580159061125d57506001600160a01b03831615155b61127a5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038481165f8181526007602090815260408083209488168084529482528083206001600160e01b0319881680855290835292819020805460ff19168715159081179091559051908152919392917f9d950e4919d7c91068179be3cd6a99029ee6fdfcf4fb488053aa79841b517e03910160405180910390a450505050565b611307611476565b6001600160a01b03821661132e5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260046020908152604091829020805460ff191685151590811790915591519182527f023ef6e50bf1aa5e0ac13acee4206b46ded01551f0247af798912f40d14baa799101611002565b61138d611476565b600180546001600160a01b0383166001600160a01b031990911681179091556113bd5f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6113fd611476565b6001600160a01b0381166114245760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031982165f908152600560205260409081902060030180546001600160a01b0319166001600160a01b03841690811790915590516820b63637b1b0ba37b960b91b8152600901610875565b5f546001600160a01b03163314610ac75760405163118cdaa760e01b8152336004820152602401610b78565b600180546001600160a01b0319169055610b8a815f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80356001600160e01b03198116811461151c575f5ffd5b919050565b5f60208284031215611531575f5ffd5b61153a82611505565b9392505050565b80356001600160a01b038116811461151c575f5ffd5b5f5f5f60608486031215611569575f5ffd5b61157284611541565b925061158060208501611541565b915061158e60408501611505565b90509250925092565b5f5f604083850312156115a8575f5ffd5b6115b183611505565b91506115bf60208401611541565b90509250929050565b5f5f604083850312156115d9575f5ffd5b6115b183611541565b5f602082840312156115f2575f5ffd5b61153a82611541565b5f5f5f5f5f60a0868803121561160f575f5ffd5b61161886611541565b945061162660208701611541565b935061163460408701611541565b925061164260608701611541565b915061165060808701611505565b90509295509295909350565b8035801515811461151c575f5ffd5b5f5f6040838503121561167c575f5ffd5b61168583611541565b91506115bf6020840161165c565b5f5f5f5f608085870312156116a6575f5ffd5b6116af85611541565b93506116bd60208601611541565b92506116cb60408601611505565b91506116d96060860161165c565b90509295919450925056fea264697066735822122016de7a645609ae3633603ad230bbc5973e6b61807f2e7ff347699266333b14bb64736f6c634300081c0033

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 Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.