S Price: $0.719741 (-10.88%)

Contract

0xB85213e2be9fd369Eb502532d0Ae9a8Fc1D8883E

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer Ownersh...98545972025-02-24 17:13:1420 hrs ago1740417194IN
0xB85213e2...Fc1D8883E
0 S0.0015769655
Initialize98542992025-02-24 17:11:2620 hrs ago1740417086IN
0xB85213e2...Fc1D8883E
0 S0.0014852255

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Voter

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 13 : Voter.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "contracts/interfaces/IVTOKEN.sol";
import "contracts/interfaces/IPlugin.sol";
import "contracts/interfaces/IGauge.sol";
import "contracts/interfaces/IBribe.sol";
import "contracts/interfaces/IMinter.sol";
import "contracts/interfaces/IGaugeFactory.sol";
import "contracts/interfaces/IBribeFactory.sol";

/**
 * @title Voter
 * @author akita
 * 
 * Voter contract is used to vote on plugins. When a Plugin is added a Gauge and Bribe are deployed for that Plugin.
 * VTOKEN holders can cast votes on Plugins in the Voter contract. The Voter will distribute OTOKEN to those Plugin's
 * gauges every week based on the votes cast. When an account casts a vote on a plugin, its corresponding Bribe
 * balance will be updated to reflect that account's votes for them to receive voting rewards from that plugin.
 * 
 * Voter votes must be equal to Bribe balanceOf for that plugin for all accounts at all times.
 * Voter weights must be equal to Bribe totalSupply at all times.
 */
contract Voter is ReentrancyGuard, Ownable {

    /*----------  CONSTANTS  --------------------------------------------*/

    uint internal constant DURATION = 7 days; // duration of each voting epoch

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

    address public immutable VTOKEN;        // the voting token that governs these contracts
    address public immutable OTOKEN;        // the token that is distributed to gauges for rewards
    address public immutable gaugefactory;  // the gauge factory that creates gauges  
    address public immutable bribefactory;  // the bribe factory that creates bribes
    address public minter;                  // the minter that mints OTOKENs to Voter contract for distribution

    uint public totalWeight;                                        // total voting weight
    address[] public plugins;                                       // all plugins viable for incentives
    mapping(address => address) public gauges;                      // plugin => gauge
    mapping(address => address) public pluginForGauge;              // gauge => plugin
    mapping(address => address) public bribes;                      // plugin => bribe
    mapping(address => uint256) public weights;                     // plugin => weight
    mapping(address => mapping(address => uint256)) public votes;   // account => plugin => votes
    mapping(address => address[]) public pluginVote;                // account => plugins
    mapping(address => uint) public usedWeights;                    // account => total voting weight of user
    mapping(address => uint) public lastVoted;                      // account => timestamp of last vote, to ensure one vote per epoch
    mapping(address => bool) public isGauge;                        // gauge => true if is gauge
    mapping(address => bool) public isAlive;                        // gauge => true if is alive

    uint internal index;                            // index of current voting epoch
    mapping(address => uint) internal supplyIndex;  // plugin => index of supply at last reward distribution
    mapping(address => uint) public claimable;      // plugin => claimable rewards

    /*----------  ERRORS ------------------------------------------------*/

    error Voter__AlreadyVotedThisEpoch();
    error Voter__NotAuthorizedGovernance();
    error Voter__PluginLengthNotEqualToWeightLength();
    error Voter__NotAuthorizedMinter();
    error Voter__InvalidZeroAddress();
    error Voter__NotMinter();
    error Voter__GaugeExists();
    error Voter__GaugeIsDead();
    error Voter__GaugeIsAlive();
    error Voter__NotGauge();

    /*----------  EVENTS ------------------------------------------------*/

    event Voter__GaugeCreated(address creator, address indexed plugin, address indexed gauge,  address bribe);
    event Voter__GaugeKilled(address indexed gauge);
    event Voter__GaugeRevived(address indexed gauge);
    event Voter__Voted(address indexed voter, uint256 weight);
    event Voter__Abstained(address account, uint256 weight);
    event Voter__Deposit(address indexed plugin, address indexed gauge, address account, uint amount);
    event Voter__Withdraw(address indexed plugin, address indexed gauge, address account, uint amount);
    event Voter__NotifyReward(address indexed sender, address indexed reward, uint amount);
    event Voter__DistributeReward(address indexed sender, address indexed gauge, uint amount);
    event Voter__BribeRewardAdded(address indexed bribe, address indexed reward);

    /*----------  MODIFIERS  --------------------------------------------*/

    modifier onlyNewEpoch(address account) {
        if ((block.timestamp / DURATION) * DURATION < lastVoted[account]) revert Voter__AlreadyVotedThisEpoch();
        _;
    }

    modifier onlyGov {
        if (msg.sender != owner() && msg.sender != IMinter(minter).team()) revert Voter__NotAuthorizedGovernance();
        _;
    }

    modifier nonZeroAddress(address _account) {
        if (_account == address(0)) revert Voter__InvalidZeroAddress();
        _;
    }

    /*----------  FUNCTIONS  --------------------------------------------*/

    /**
     * @notice construct a voter contract 
     * @param _VTOKEN VTOKEN address which is used to get voting power
     * @param _gaugefactory GaugeFactory address which is used to create gauges
     * @param _bribefactory BribeFactory address which is used to create bribes
     */
    constructor(address _VTOKEN, address _gaugefactory, address _bribefactory) {
        VTOKEN = _VTOKEN;
        OTOKEN = IVTOKEN(_VTOKEN).OTOKEN();
        gaugefactory = _gaugefactory;
        bribefactory = _bribefactory;
        minter = msg.sender;
    }

    /**
     * @notice Resets msg.sender's votes to zero on all plugins. Can only be called once per epoch.
     *         This is necessary for the user to withdraw staked VTOKENs by setting users voting weight to 0.
     */
    function reset() 
        external 
        onlyNewEpoch(msg.sender) 
    {
        address account = msg.sender;
        lastVoted[account] = block.timestamp;
        _reset(account);
    }

    /**
     * @notice Allocates voting power for msg.sender to input plugins based on input weights. Will update bribe balances
     *         to track voting rewards. Makes users voting weight nonzero. Can only be called once per epoch. 
     * @param _plugins list of plugins to vote on
     * @param _weights list of weights corresponding to plugins
     */
    function vote(address[] calldata _plugins, uint256[] calldata _weights) 
        external 
        onlyNewEpoch(msg.sender) 
    {
        if (_plugins.length != _weights.length) revert Voter__PluginLengthNotEqualToWeightLength();
        lastVoted[msg.sender] = block.timestamp;
        _vote(msg.sender, _plugins, _weights);
    }

    /**
     * @notice Claims rewards for msg.sender from list of gauges.
     * @param _gauges list of gauges to claim rewards from
     */
    function claimRewards(address[] memory _gauges) external {
        for (uint i = 0; i < _gauges.length; i++) {
            IGauge(_gauges[i]).getReward(msg.sender);
        }
    }

    /**
     * @notice Claims rewards for msg.sender from list of bribes.
     * @param _bribes list of bribes to claim rewards from
     */
    function claimBribes(address[] memory _bribes) external {
        for (uint i = 0; i < _bribes.length; i++) {
            IBribe(_bribes[i]).getReward(msg.sender);
        }
    }

    /**
     * @notice Claims voting rewards for each plugin and distributes it to corresponding bribe contracts
     * @param _plugins list of plugins to claim rewards and distribute from
     */
    function distributeToBribes(address[] memory _plugins) external {
        for (uint i = 0; i < _plugins.length; i++) {
            IPlugin(_plugins[i]).claimAndDistribute();
        }
    }

    /**
     * @notice Distributes OTOKEN to _gauge, notifies gauge contract to start distributing OTOKEN to plugin depositors.
     * @param _gauge gauge to distribute OTOKEN to
     */
    function distribute(address _gauge) public nonReentrant {
        IMinter(minter).update_period();
        _updateFor(_gauge); // should set claimable to 0 if killed
        uint _claimable = claimable[_gauge];
        if (_claimable > IGauge(_gauge).left(OTOKEN) && _claimable / DURATION > 0) {
            claimable[_gauge] = 0;
            IGauge(_gauge).notifyRewardAmount(OTOKEN, _claimable);
            emit Voter__DistributeReward(msg.sender, _gauge, _claimable);
        }
    }

    /**
     * @notice Distributes OTOKEN to gauges from start to finish
     * @param start starting index of gauges to distribute to
     * @param finish ending index of gauges to distribute to
     */
    function distribute(uint start, uint finish) public {
        for (uint x = start; x < finish; x++) {
            distribute(gauges[plugins[x]]);
        }
    }

    /**
     * @notice Distributes OTOKEN to all gauges
     */
    function distro() external {
        distribute(0, plugins.length);
    }

    /**
     * @notice For the minter to notify the voter contract of the amount of OTOKEN to distribute
     * @param amount amount of OTOKEN to distribute
     */
    function notifyRewardAmount(uint amount) external {
        _safeTransferFrom(OTOKEN, msg.sender, address(this), amount); // transfer the distro in
        uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim
        if (_ratio > 0) {
            index += _ratio;
        }
        emit Voter__NotifyReward(msg.sender, OTOKEN, amount);
    }

    function updateFor(address[] memory _gauges) external {
        for (uint i = 0; i < _gauges.length; i++) {
            _updateFor(_gauges[i]);
        }
    }

    function updateForRange(uint start, uint end) public {
        for (uint i = start; i < end; i++) {
            _updateFor(gauges[plugins[i]]);
        }
    }

    function updateAll() external {
        updateForRange(0, plugins.length);
    }

    function updateGauge(address _gauge) external {
        _updateFor(_gauge);
    }

    /*----------  RESTRICTED FUNCTIONS  ---------------------------------*/

    function initialize(address _minter) 
        external 
    {
        if (msg.sender != minter) revert Voter__NotMinter();
        minter = _minter;
    }

    function addPlugin(address _plugin) 
        external 
        onlyGov 
        returns (address) 
    {
        if (gauges[_plugin] != address(0)) revert Voter__GaugeExists();

        address _gauge = IGaugeFactory(gaugefactory).createGauge(address(this), _plugin);
        IGauge(_gauge).addReward(OTOKEN);
        IPlugin(_plugin).setGauge(_gauge);
        IERC20(OTOKEN).approve(_gauge, type(uint).max);

        address _bribe = IBribeFactory(bribefactory).createBribe(address(this));
        address[] memory _bribeTokens = IPlugin(_plugin).getBribeTokens();
        for (uint256 i = 0; i < _bribeTokens.length; i++) {
            IBribe(_bribe).addReward(_bribeTokens[i]);
        }
        IPlugin(_plugin).setBribe(_bribe);

        gauges[_plugin] = _gauge;
        bribes[_plugin] = _bribe;
        pluginForGauge[_gauge] = _plugin;
        isGauge[_gauge] = true;
        isAlive[_gauge] = true;
        _updateFor(_gauge);
        plugins.push(_plugin);
        emit Voter__GaugeCreated(msg.sender, _plugin, _gauge, _bribe); 
        return _gauge;
    }

    function killGauge(address _gauge) 
        external 
        onlyGov 
    {
        if (!isAlive[_gauge]) revert Voter__GaugeIsDead();
        isAlive[_gauge] = false;
        claimable[_gauge] = 0;
        emit Voter__GaugeKilled(_gauge);
    }

    function reviveGauge(address _gauge) 
        external 
        onlyGov 
    {
        if (isAlive[_gauge]) revert Voter__GaugeIsAlive();
        isAlive[_gauge] = true;
        emit Voter__GaugeRevived(_gauge);
    }

    function addBribeReward(address _bribe, address _rewardToken) 
        external 
        onlyGov 
        nonZeroAddress(_rewardToken)
    {
        IBribe(_bribe).addReward(_rewardToken);
        emit Voter__BribeRewardAdded(_bribe, _rewardToken);
    }

    function emitDeposit(address account, uint amount) 
        external 
    {
        if (!isGauge[msg.sender]) revert Voter__NotGauge();
        if (!isAlive[msg.sender]) revert Voter__GaugeIsDead();
        emit Voter__Deposit(pluginForGauge[msg.sender], msg.sender, account, amount);
    }

    function emitWithdraw(address account, uint amount) external {
        if (!isGauge[msg.sender]) revert Voter__NotGauge();
        emit Voter__Withdraw(pluginForGauge[msg.sender], msg.sender, account, amount);
    }

    function _reset(address account) internal {
        address[] storage _pluginVote = pluginVote[account];
        uint _pluginVoteCnt = _pluginVote.length;
        uint256 _totalWeight = 0;

        for (uint i = 0; i < _pluginVoteCnt; i ++) {
            address _plugin = _pluginVote[i];
            uint256 _votes = votes[account][_plugin];

            if (_votes > 0) {
                _updateFor(gauges[_plugin]);
                weights[_plugin] -= _votes;
                votes[account][_plugin] -= _votes;
                IBribe(bribes[_plugin])._withdraw(IBribe(bribes[_plugin]).balanceOf(account), account);
                _totalWeight += _votes;
                emit Voter__Abstained(account, _votes);
            }
        }
        totalWeight -= uint256(_totalWeight);
        usedWeights[account] = 0;
        delete pluginVote[account];
    }

    function _vote(address account, address[] memory _pluginVote, uint256[] memory _weights) internal {
        _reset(account);
        uint _pluginCnt = _pluginVote.length;
        uint256 _weight = IVTOKEN(VTOKEN).balanceOf(account);
        uint256 _totalVoteWeight = 0;
        uint256 _totalWeight = 0;
        uint256 _usedWeight = 0;

        for (uint i = 0; i < _pluginCnt; i++) {
            address _plugin = _pluginVote[i];
            address _gauge = gauges[_plugin];
            if (isGauge[_gauge] && isAlive[_gauge]) { 
                _totalVoteWeight += _weights[i];
            }
        }

        for (uint i = 0; i < _pluginCnt; i++) {
            address _plugin = _pluginVote[i];
            address _gauge = gauges[_plugin];

            if (isGauge[_gauge] && isAlive[_gauge]) { 
                uint256 _pluginWeight = _weights[i] * _weight / _totalVoteWeight;
                require(votes[account][_plugin] == 0);
                require(_pluginWeight != 0);
                _updateFor(_gauge);

                pluginVote[account].push(_plugin);

                weights[_plugin] += _pluginWeight;
                votes[account][_plugin] += _pluginWeight;
                IBribe(bribes[_plugin])._deposit(uint256(_pluginWeight), account); 
                _usedWeight += _pluginWeight;
                _totalWeight += _pluginWeight;
                emit Voter__Voted(account, _pluginWeight);
            }
        }

        totalWeight += uint256(_totalWeight);
        usedWeights[account] = uint256(_usedWeight);
    }

    function _updateFor(address _gauge) internal {
        address _plugin = pluginForGauge[_gauge];
        uint256 _supplied = weights[_plugin];
        if (_supplied > 0) {
            uint _supplyIndex = supplyIndex[_gauge];
            uint _index = index; // get global index0 for accumulated distro
            supplyIndex[_gauge] = _index; // update _gauge current position to global position
            uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued
            if (_delta > 0) {
                uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token
                if (isAlive[_gauge]) {
                    claimable[_gauge] += _share;
                }
            }
        } else {
            supplyIndex[_gauge] = index; // new users are set to the default global state
        }
    }

    function _safeTransferFrom(address token, address from, address to, uint256 value) internal {
        require(token.code.length > 0);
        (bool success, bytes memory data) =
        token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))));
    }

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

    function getPlugins() external view returns (address[] memory) {
        return plugins;
    }

    function length() external view returns (uint) {
        return plugins.length;
    }

}

File 2 of 13 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../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.
 *
 * By default, the owner account will be the one that deploys the contract. 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;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @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 {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @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 {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _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);
    }
}

File 3 of 13 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

File 4 of 13 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
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 amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` 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 amount) external returns (bool);
}

File 5 of 13 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

File 6 of 13 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

File 7 of 13 : IBribe.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IBribe {
    /*----------  FUNCTIONS  --------------------------------------------*/
    function getReward(address account) external;
    function notifyRewardAmount(address token, uint amount) external;
    /*----------  RESTRICTED FUNCTIONS  ---------------------------------*/
    function _deposit(uint amount, address account) external;
    function _withdraw(uint amount, address account) external;
    function addReward(address rewardToken) external;
    /*----------  VIEW FUNCTIONS  ---------------------------------------*/
    function balanceOf(address account) external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function rewardPerToken(address reward) external view returns (uint);
    function getRewardForDuration(address reward) external view returns (uint);
    function left(address reward) external view returns (uint);
    function earned(address account, address reward) external view returns (uint);
    function getRewardTokens() external view returns (address[] memory);
    function DURATION() external view returns (uint);
    function isRewardToken(address token) external view returns (bool);
}

File 8 of 13 : IBribeFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IBribeFactory {
    /*----------  FUNCTIONS  --------------------------------------------*/
    /*----------  RESTRICTED FUNCTIONS  ---------------------------------*/
    function createBribe(address voter) external returns (address);
    /*----------  VIEW FUNCTIONS  ---------------------------------------*/
}

File 9 of 13 : IGauge.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IGauge {
    /*----------  FUNCTIONS  --------------------------------------------*/
    function getReward(address account) external;
    function notifyRewardAmount(address token, uint amount) external;
    /*----------  RESTRICTED FUNCTIONS  ---------------------------------*/
    function _deposit(address account, uint256 amount) external;
    function _withdraw(address account, uint256 amount) external;
    function addReward(address rewardToken) external;
    /*----------  VIEW FUNCTIONS  ---------------------------------------*/
    function balanceOf(address account) external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function rewardPerToken(address reward) external view returns (uint);
    function getRewardForDuration(address reward) external view returns (uint);
    function earned(address account, address reward) external view returns (uint);
    function left(address token) external view returns (uint);
}

File 10 of 13 : IGaugeFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IGaugeFactory {
    /*----------  FUNCTIONS  --------------------------------------------*/
    /*----------  RESTRICTED FUNCTIONS  ---------------------------------*/
    function createGauge(address voter, address token) external returns (address);
    /*----------  VIEW FUNCTIONS  ---------------------------------------*/
}

File 11 of 13 : IMinter.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IMinter {
    /*----------  FUNCTIONS  --------------------------------------------*/
    function update_period() external returns (uint256);
    /*----------  RESTRICTED FUNCTIONS  ---------------------------------*/
    /*----------  VIEW FUNCTIONS  ---------------------------------------*/
    function team() external view returns (address);
    function weekly() external view returns (uint256);
}

File 12 of 13 : IPlugin.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IPlugin {
    /*----------  FUNCTIONS  --------------------------------------------*/
    function claimAndDistribute() external;
    /*----------  RESTRICTED FUNCTIONS  ---------------------------------*/
    function setGauge(address gauge) external;
    function setBribe(address bribe) external;
    /*----------  VIEW FUNCTIONS  ---------------------------------------*/
    function balanceOf(address account) external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function getUnderlyingName() external view returns (string memory);
    function getUnderlyingSymbol() external view returns (string memory);
    function getUnderlyingAddress() external view returns (address);
    function getProtocol() external view returns (string memory);
    function getTokensInUnderlying() external view returns (address[] memory);
    function getBribeTokens() external view returns (address[] memory);
    function getUnderlyingDecimals() external view returns (uint8);
}

File 13 of 13 : IVTOKEN.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IVTOKEN {
    /*----------  FUNCTIONS  --------------------------------------------*/
    /*----------  RESTRICTED FUNCTIONS  ---------------------------------*/
    /*----------  VIEW FUNCTIONS  ---------------------------------------*/
    function OTOKEN() external view returns (address);
    function balanceOf(address account) external view returns (uint256);
    function balanceOfTOKEN(address account) external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function totalSupplyTOKEN() external view returns (uint256);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200,
    "details": {}
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_VTOKEN","type":"address"},{"internalType":"address","name":"_gaugefactory","type":"address"},{"internalType":"address","name":"_bribefactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Voter__AlreadyVotedThisEpoch","type":"error"},{"inputs":[],"name":"Voter__GaugeExists","type":"error"},{"inputs":[],"name":"Voter__GaugeIsAlive","type":"error"},{"inputs":[],"name":"Voter__GaugeIsDead","type":"error"},{"inputs":[],"name":"Voter__InvalidZeroAddress","type":"error"},{"inputs":[],"name":"Voter__NotAuthorizedGovernance","type":"error"},{"inputs":[],"name":"Voter__NotAuthorizedMinter","type":"error"},{"inputs":[],"name":"Voter__NotGauge","type":"error"},{"inputs":[],"name":"Voter__NotMinter","type":"error"},{"inputs":[],"name":"Voter__PluginLengthNotEqualToWeightLength","type":"error"},{"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":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"Voter__Abstained","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bribe","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"}],"name":"Voter__BribeRewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"plugin","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Voter__Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Voter__DistributeReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"address","name":"plugin","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"bribe","type":"address"}],"name":"Voter__GaugeCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"Voter__GaugeKilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"Voter__GaugeRevived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Voter__NotifyReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"Voter__Voted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"plugin","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Voter__Withdraw","type":"event"},{"inputs":[],"name":"OTOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VTOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bribe","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"}],"name":"addBribeReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_plugin","type":"address"}],"name":"addPlugin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bribefactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bribes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_bribes","type":"address[]"}],"name":"claimBribes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauges","type":"address[]"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"finish","type":"uint256"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_plugins","type":"address[]"}],"name":"distributeToBribes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distro","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gaugefactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gauges","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPlugins","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAlive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGauge","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"killGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastVoted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"length","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pluginForGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pluginVote","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"plugins","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"reviveGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauges","type":"address[]"}],"name":"updateFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"updateForRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"updateGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usedWeights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_plugins","type":"address[]"},{"internalType":"uint256[]","name":"_weights","type":"uint256[]"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"votes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"weights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

6101006040523480156200001257600080fd5b5060405162002bfe38038062002bfe833981016040819052620000359162000156565b60016000556200004533620000e7565b6001600160a01b03831660808190526040805163315137c360e21b8152905163c544df0c916004808201926020929091908290030181865afa15801562000090573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b69190620001a0565b6001600160a01b0390811660a05291821660c0521660e05250600280546001600160a01b03191633179055620001c5565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b60805160a05160c05160e0516129c06200023e6000396000818161033301526116bf0152600081816103c301526114c90152600081816105bd015281816107f30152818161086c01528181610a1901528181610ad50152818161154f01526116370152600081816106760152611d7d01526129c06000f3fe608060405234801561001057600080fd5b50600436106102685760003560e01c80638da5cb5b11610151578063b9a09fd5116100c3578063d826f88f11610087578063d826f88f1461061d578063d8867fc814610625578063f0a317eb14610638578063f2fde38b1461064b578063f9f031df1461065e578063fb5484271461067157600080fd5b8063b9a09fd51461057c578063c4d66de8146105a5578063c544df0c146105b8578063cad1b906146105df578063d560b0d71461060a57600080fd5b80639f06247b116101155780639f06247b146104d5578063a2d869b2146104e8578063a7cac846146104fd578063a8c5d95a1461051d578063aa79979b14610546578063b014da211461056957600080fd5b80638da5cb5b1461047557806396c82e5714610486578063992a79331461048f5780639a61df89146104a25780639b6a9d72146104c257600080fd5b80634978c512116101ea5780636ecbe38a116101ae5780636ecbe38a1461040e5780636f816a2014610421578063715018a6146104345780637625391a1461043c578063773fac7d1461044f5780637ceed4af1461046257600080fd5b80634978c5121461039057806353d78693146103a357806363453ae1146103ab57806368c3acb3146103be5780636c60f246146103e557600080fd5b806328ba84ca1161023157806328ba84ca1461031b57806338752a9d1461032e5780633c6b16ab14610355578063402914f51461036857806347b3c6ba1461038857600080fd5b80622f8de41461026d57806307546172146102a05780631703e5f9146102cb5780631f7b6d32146102fe578063240f977414610306575b600080fd5b61028d61027b3660046124f7565b600b6020526000908152604090205481565b6040519081526020015b60405180910390f35b6002546102b3906001600160a01b031681565b6040516001600160a01b039091168152602001610297565b6102ee6102d93660046124f7565b600e6020526000908152604090205460ff1681565b6040519015158152602001610297565b60045461028d565b610319610314366004612586565b610698565b005b610319610329366004612625565b610732565b6102b37f000000000000000000000000000000000000000000000000000000000000000081565b610319610363366004612651565b6107ee565b61028d6103763660046124f7565b60116020526000908152604090205481565b6103196108b9565b61031961039e366004612586565b6108ca565b610319610955565b6103196103b93660046124f7565b610964565b6102b37f000000000000000000000000000000000000000000000000000000000000000081565b6102b36103f33660046124f7565b6006602052600090815260409020546001600160a01b031681565b61031961041c3660046124f7565b610b8e565b61031961042f3660046126b6565b610b97565b610319610c85565b61031961044a366004612722565b610c97565b6102b361045d366004612625565b610d02565b610319610470366004612744565b610d3a565b6001546001600160a01b03166102b3565b61028d60035481565b61031961049d3660046124f7565b610ebb565b61028d6104b03660046124f7565b600c6020526000908152604090205481565b6103196104d0366004612722565b61100b565b6103196104e33660046124f7565b611071565b6104f06111b8565b604051610297919061277d565b61028d61050b3660046124f7565b60086020526000908152604090205481565b6102b361052b3660046124f7565b6007602052600090815260409020546001600160a01b031681565b6102ee6105543660046124f7565b600d6020526000908152604090205460ff1681565b610319610577366004612625565b61121a565b6102b361058a3660046124f7565b6005602052600090815260409020546001600160a01b031681565b6103196105b33660046124f7565b61129e565b6102b37f000000000000000000000000000000000000000000000000000000000000000081565b61028d6105ed366004612744565b600960209081526000928352604080842090915290825290205481565b610319610618366004612586565b6112eb565b61031961132b565b6102b36106333660046124f7565b61138d565b6102b3610646366004612651565b6119c3565b6103196106593660046124f7565b6119ed565b61031961066c366004612586565b611a68565b6102b37f000000000000000000000000000000000000000000000000000000000000000081565b60005b815181101561072e578181815181106106b6576106b66127ca565b6020908102919091010151604051630c00007b60e41b81523360048201526001600160a01b039091169063c00007b090602401600060405180830381600087803b15801561070357600080fd5b505af1158015610717573d6000803e3d6000fd5b505050508080610726906127f6565b91505061069b565b5050565b336000908152600d602052604090205460ff166107625760405163aa7a99d160e01b815260040160405180910390fd5b336000908152600e602052604090205460ff1661079257604051635cf06fbb60e01b815260040160405180910390fd5b336000818152600660209081526040918290205482516001600160a01b0387811682529281018690529116917f676e2de14d55ed76a3c1fb73016d65a60e9e45ffb1720966f847bc76fc01904291015b60405180910390a35050565b61081a7f0000000000000000000000000000000000000000000000000000000000000000333084611afe565b60035460009061083283670de0b6b3a764000061280f565b61083c919061282c565b9050801561085c5780600f6000828254610856919061284e565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907fa7c0e3f096d59a05405bc674c2930dbfe8cdd9db8930398f3578a957a5b327c9906020016107e2565b6004546108c890600090610c97565b565b60005b815181101561072e578181815181106108e8576108e86127ca565b60200260200101516001600160a01b031663dfb89c376040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b50505050808061094d906127f6565b9150506108cd565b6004546108c89060009061100b565b61096c611bf6565b600260009054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af11580156109c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e59190612861565b506109ef81611c4f565b6001600160a01b0381811660008181526011602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610a67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8b9190612861565b81118015610aa557506000610aa362093a808361282c565b115b15610b80576001600160a01b03828116600081815260116020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610b2757600080fd5b505af1158015610b3b573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507fb7d7e9f93634a3439166473675551d7f6e6d8d29acdd43c8868bfeac1c17650f9060200160405180910390a35b50610b8b6001600055565b50565b610b8b81611c4f565b336000818152600c602052604090205462093a80610bb5814261282c565b610bbf919061280f565b1015610bde57604051632cef5c4560e21b815260040160405180910390fd5b838214610bfe5760405163070fd29b60e01b815260040160405180910390fd5b336000818152600c602090815260409182902042905581518782028181018301909352878152610c7e939290918991899182919085019084908082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250611d5092505050565b5050505050565b610c8d61216b565b6108c860006121c5565b815b81811015610cfd57610ceb6005600060048481548110610cbb57610cbb6127ca565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610964565b80610cf5816127f6565b915050610c99565b505050565b600a6020528160005260406000208181548110610d1e57600080fd5b6000918252602090912001546001600160a01b03169150829050565b6001546001600160a01b03163314801590610ddd5750600260009054906101000a90046001600160a01b03166001600160a01b03166385f2aef26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc7919061287a565b6001600160a01b0316336001600160a01b031614155b15610dfb5760405163498eeef360e11b815260040160405180910390fd5b806001600160a01b038116610e235760405163c7a2af7360e01b815260040160405180910390fd5b604051639c9b2e2160e01b81526001600160a01b038381166004830152841690639c9b2e2190602401600060405180830381600087803b158015610e6657600080fd5b505af1158015610e7a573d6000803e3d6000fd5b50506040516001600160a01b038086169350861691507fbfdcae251dd92547c00a8a0235edcb67767e26e9c38e4270c0767c910319262690600090a3505050565b6001546001600160a01b03163314801590610f5e5750600260009054906101000a90046001600160a01b03166001600160a01b03166385f2aef26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f48919061287a565b6001600160a01b0316336001600160a01b031614155b15610f7c5760405163498eeef360e11b815260040160405180910390fd5b6001600160a01b0381166000908152600e602052604090205460ff16610fb557604051635cf06fbb60e01b815260040160405180910390fd5b6001600160a01b0381166000818152600e60209081526040808320805460ff191690556011909152808220829055517f557faf519fb7278ebcd3d18b0674298ba37a470ca81e53c21b2ec03152eb50139190a250565b815b81811015610cfd5761105f600560006004848154811061102f5761102f6127ca565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416611c4f565b80611069816127f6565b91505061100d565b6001546001600160a01b031633148015906111145750600260009054906101000a90046001600160a01b03166001600160a01b03166385f2aef26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110fe919061287a565b6001600160a01b0316336001600160a01b031614155b156111325760405163498eeef360e11b815260040160405180910390fd5b6001600160a01b0381166000908152600e602052604090205460ff161561116c5760405163ac6553cd60e01b815260040160405180910390fd5b6001600160a01b0381166000818152600e6020526040808220805460ff19166001179055517fa3bc6dfaf4a139af831043f7e724799e66ac206addc97cac3f547c6a9e1dc79d9190a250565b6060600480548060200260200160405190810160405280929190818152602001828054801561121057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116111f2575b5050505050905090565b336000908152600d602052604090205460ff1661124a5760405163aa7a99d160e01b815260040160405180910390fd5b336000818152600660209081526040918290205482516001600160a01b0387811682529281018690529116917fb28188e4b81dda8b3fc5cb831e49457c4adb49016c8dfd8a1513cf9894245cab91016107e2565b6002546001600160a01b031633146112c957604051633179cd7560e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60005b815181101561072e5761131982828151811061130c5761130c6127ca565b6020026020010151611c4f565b80611323816127f6565b9150506112ee565b336000818152600c602052604090205462093a80611349814261282c565b611353919061280f565b101561137257604051632cef5c4560e21b815260040160405180910390fd5b336000818152600c6020526040902042905561072e81612217565b60006113a16001546001600160a01b031690565b6001600160a01b0316336001600160a01b03161415801561144a5750600260009054906101000a90046001600160a01b03166001600160a01b03166385f2aef26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611410573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611434919061287a565b6001600160a01b0316336001600160a01b031614155b156114685760405163498eeef360e11b815260040160405180910390fd5b6001600160a01b0382811660009081526005602052604090205416156114a1576040516325d9db2f60e01b815260040160405180910390fd5b604051631e533a8f60e21b81523060048201526001600160a01b0383811660248301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063794cea3c906044016020604051808303816000875af1158015611514573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611538919061287a565b604051639c9b2e2160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015291925090821690639c9b2e2190602401600060405180830381600087803b15801561159f57600080fd5b505af11580156115b3573d6000803e3d6000fd5b50506040516355a68ed360e01b81526001600160a01b038481166004830152861692506355a68ed39150602401600060405180830381600087803b1580156115fa57600080fd5b505af115801561160e573d6000803e3d6000fd5b505060405163095ea7b360e01b81526001600160a01b03848116600483015260001960248301527f000000000000000000000000000000000000000000000000000000000000000016925063095ea7b391506044016020604051808303816000875af1158015611682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a69190612897565b50604051631af469cb60e21b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bd1a72c906024016020604051808303816000875af1158015611710573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611734919061287a565b90506000846001600160a01b031663e33ca8396040518163ffffffff1660e01b8152600401600060405180830381865afa158015611776573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261179e91908101906128b9565b905060005b815181101561184557826001600160a01b0316639c9b2e218383815181106117cd576117cd6127ca565b60200260200101516040518263ffffffff1660e01b815260040161180091906001600160a01b0391909116815260200190565b600060405180830381600087803b15801561181a57600080fd5b505af115801561182e573d6000803e3d6000fd5b50505050808061183d906127f6565b9150506117a3565b5060405163740ef7e760e11b81526001600160a01b03838116600483015286169063e81defce90602401600060405180830381600087803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b5050506001600160a01b0380871660008181526005602090815260408083208054868b166001600160a01b03199182168117909255600784528285208054978b16978216979097179096558352600682528083208054909516909317909355600d8352818120805460ff199081166001908117909255600e90945291902080549092161790555061192d83611c4f565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b03878116918217909255604080513381528584166020820152928616927fb920b936f556d443772609e0cc06a72c3bb67fc606de10dcdd51323d1ddbc7fc910160405180910390a350909392505050565b600481815481106119d357600080fd5b6000918252602090912001546001600160a01b0316905081565b6119f561216b565b6001600160a01b038116611a5f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b610b8b816121c5565b60005b815181101561072e57818181518110611a8657611a866127ca565b6020908102919091010151604051630c00007b60e41b81523360048201526001600160a01b039091169063c00007b090602401600060405180830381600087803b158015611ad357600080fd5b505af1158015611ae7573d6000803e3d6000fd5b505050508080611af6906127f6565b915050611a6b565b6000846001600160a01b03163b11611b1557600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611b799190612948565b6000604051808303816000865af19150503d8060008114611bb6576040519150601f19603f3d011682016040523d82523d6000602084013e611bbb565b606091505b5091509150818015611be5575080511580611be5575080806020019051810190611be59190612897565b611bee57600080fd5b505050505050565b600260005403611c485760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611a56565b6002600055565b6001600160a01b038082166000908152600660209081526040808320549093168083526008909152919020548015611d2f576001600160a01b03831660009081526010602052604081208054600f549182905591611cad8383612977565b90508015611bee576000670de0b6b3a7640000611cca838761280f565b611cd4919061282c565b6001600160a01b0388166000908152600e602052604090205490915060ff1615611d26576001600160a01b03871660009081526011602052604081208054839290611d2090849061284e565b90915550505b50505050505050565b600f546001600160a01b038416600090815260106020526040902055505050565b611d5983612217565b81516040516370a0823160e01b81526001600160a01b0385811660048301526000917f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa158015611dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dea9190612861565b90506000806000805b85811015611eae576000888281518110611e0f57611e0f6127ca565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600d909452205490925060ff168015611e6c57506001600160a01b0381166000908152600e602052604090205460ff165b15611e9957888381518110611e8357611e836127ca565b602002602001015186611e96919061284e565b95505b50508080611ea6906127f6565b915050611df3565b5060005b8581101561212e576000888281518110611ece57611ece6127ca565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600d909452205490925060ff168015611f2b57506001600160a01b0381166000908152600e602052604090205460ff165b1561211957600086888b8681518110611f4657611f466127ca565b6020026020010151611f58919061280f565b611f62919061282c565b6001600160a01b03808e1660009081526009602090815260408083209388168352929052205490915015611f9557600080fd5b80600003611fa257600080fd5b611fab82611c4f565b6001600160a01b038c81166000908152600a6020908152604080832080546001810182559084528284200180546001600160a01b031916948816948517905592825260089052908120805483929061200490849061284e565b90915550506001600160a01b03808d1660009081526009602090815260408083209387168352929052908120805483929061204090849061284e565b90915550506001600160a01b0380841660009081526007602052604090819020549051630463cd9760e41b8152600481018490528e8316602482015291169063463cd97090604401600060405180830381600087803b1580156120a257600080fd5b505af11580156120b6573d6000803e3d6000fd5b5050505080856120c6919061284e565b94506120d2818761284e565b95508b6001600160a01b03167f4e79ebbde53238af74dcfc3a1819c8bce25caeca7056ea649e4243650874d5b28260405161210f91815260200190565b60405180910390a2505b50508080612126906127f6565b915050611eb2565b508160036000828254612141919061284e565b90915550506001600160a01b039097166000908152600b6020526040902096909655505050505050565b6001546001600160a01b031633146108c85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611a56565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0381166000908152600a6020526040812080549091805b82811015612464576000848281548110612251576122516127ca565b60009182526020808320909101546001600160a01b03898116845260098352604080852091909216808552925290912054909150801561244f576001600160a01b038083166000908152600560205260409020546122af9116611c4f565b6001600160a01b038216600090815260086020526040812080548392906122d7908490612977565b90915550506001600160a01b03808816600090815260096020908152604080832093861683529290529081208054839290612313908490612977565b90915550506001600160a01b03828116600090815260076020526040908190205490516370a0823160e01b8152898316600482015291169063293311ab9082906370a0823190602401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d9190612861565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b038a166024820152604401600060405180830381600087803b1580156123e557600080fd5b505af11580156123f9573d6000803e3d6000fd5b505050508084612409919061284e565b604080516001600160a01b038a168152602081018490529195507f606e9fc568ae450083d6885f24864ca5d406faf7b0bfc1eb2132caaf25b8e02d910160405180910390a15b5050808061245c906127f6565b915050612235565b5080600360008282546124779190612977565b90915550506001600160a01b0384166000908152600b60209081526040808320839055600a90915281206124aa916124b0565b50505050565b5080546000825590600052602060002090810190610b8b91905b808211156124de57600081556001016124ca565b5090565b6001600160a01b0381168114610b8b57600080fd5b60006020828403121561250957600080fd5b8135612514816124e2565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561255a5761255a61251b565b604052919050565b600067ffffffffffffffff82111561257c5761257c61251b565b5060051b60200190565b6000602080838503121561259957600080fd5b823567ffffffffffffffff8111156125b057600080fd5b8301601f810185136125c157600080fd5b80356125d46125cf82612562565b612531565b81815260059190911b820183019083810190878311156125f357600080fd5b928401925b8284101561261a57833561260b816124e2565b825292840192908401906125f8565b979650505050505050565b6000806040838503121561263857600080fd5b8235612643816124e2565b946020939093013593505050565b60006020828403121561266357600080fd5b5035919050565b60008083601f84011261267c57600080fd5b50813567ffffffffffffffff81111561269457600080fd5b6020830191508360208260051b85010111156126af57600080fd5b9250929050565b600080600080604085870312156126cc57600080fd5b843567ffffffffffffffff808211156126e457600080fd5b6126f08883890161266a565b9096509450602087013591508082111561270957600080fd5b506127168782880161266a565b95989497509550505050565b6000806040838503121561273557600080fd5b50508035926020909101359150565b6000806040838503121561275757600080fd5b8235612762816124e2565b91506020830135612772816124e2565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156127be5783516001600160a01b031683529284019291840191600101612799565b50909695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612808576128086127e0565b5060010190565b8082028115828204841417612826576128266127e0565b92915050565b60008261284957634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115612826576128266127e0565b60006020828403121561287357600080fd5b5051919050565b60006020828403121561288c57600080fd5b8151612514816124e2565b6000602082840312156128a957600080fd5b8151801515811461251457600080fd5b600060208083850312156128cc57600080fd5b825167ffffffffffffffff8111156128e357600080fd5b8301601f810185136128f457600080fd5b80516129026125cf82612562565b81815260059190911b8201830190838101908783111561292157600080fd5b928401925b8284101561261a578351612939816124e2565b82529284019290840190612926565b6000825160005b81811015612969576020818601810151858301520161294f565b506000920191825250919050565b81810381811115612826576128266127e056fea264697066735822122059c0f41993eaa95bffd62176b7f806c128aa5afcc1487cb4aafafe6bf388f93b64736f6c63430008130033000000000000000000000000d5dcbddd672b80ea9179a21b7691a34fb85615f2000000000000000000000000ea1db4c7a507a736a0388ff0bfed24b4ba424429000000000000000000000000b557fa65af0f482e34799efa76176b269cd88c40

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102685760003560e01c80638da5cb5b11610151578063b9a09fd5116100c3578063d826f88f11610087578063d826f88f1461061d578063d8867fc814610625578063f0a317eb14610638578063f2fde38b1461064b578063f9f031df1461065e578063fb5484271461067157600080fd5b8063b9a09fd51461057c578063c4d66de8146105a5578063c544df0c146105b8578063cad1b906146105df578063d560b0d71461060a57600080fd5b80639f06247b116101155780639f06247b146104d5578063a2d869b2146104e8578063a7cac846146104fd578063a8c5d95a1461051d578063aa79979b14610546578063b014da211461056957600080fd5b80638da5cb5b1461047557806396c82e5714610486578063992a79331461048f5780639a61df89146104a25780639b6a9d72146104c257600080fd5b80634978c512116101ea5780636ecbe38a116101ae5780636ecbe38a1461040e5780636f816a2014610421578063715018a6146104345780637625391a1461043c578063773fac7d1461044f5780637ceed4af1461046257600080fd5b80634978c5121461039057806353d78693146103a357806363453ae1146103ab57806368c3acb3146103be5780636c60f246146103e557600080fd5b806328ba84ca1161023157806328ba84ca1461031b57806338752a9d1461032e5780633c6b16ab14610355578063402914f51461036857806347b3c6ba1461038857600080fd5b80622f8de41461026d57806307546172146102a05780631703e5f9146102cb5780631f7b6d32146102fe578063240f977414610306575b600080fd5b61028d61027b3660046124f7565b600b6020526000908152604090205481565b6040519081526020015b60405180910390f35b6002546102b3906001600160a01b031681565b6040516001600160a01b039091168152602001610297565b6102ee6102d93660046124f7565b600e6020526000908152604090205460ff1681565b6040519015158152602001610297565b60045461028d565b610319610314366004612586565b610698565b005b610319610329366004612625565b610732565b6102b37f000000000000000000000000b557fa65af0f482e34799efa76176b269cd88c4081565b610319610363366004612651565b6107ee565b61028d6103763660046124f7565b60116020526000908152604090205481565b6103196108b9565b61031961039e366004612586565b6108ca565b610319610955565b6103196103b93660046124f7565b610964565b6102b37f000000000000000000000000ea1db4c7a507a736a0388ff0bfed24b4ba42442981565b6102b36103f33660046124f7565b6006602052600090815260409020546001600160a01b031681565b61031961041c3660046124f7565b610b8e565b61031961042f3660046126b6565b610b97565b610319610c85565b61031961044a366004612722565b610c97565b6102b361045d366004612625565b610d02565b610319610470366004612744565b610d3a565b6001546001600160a01b03166102b3565b61028d60035481565b61031961049d3660046124f7565b610ebb565b61028d6104b03660046124f7565b600c6020526000908152604090205481565b6103196104d0366004612722565b61100b565b6103196104e33660046124f7565b611071565b6104f06111b8565b604051610297919061277d565b61028d61050b3660046124f7565b60086020526000908152604090205481565b6102b361052b3660046124f7565b6007602052600090815260409020546001600160a01b031681565b6102ee6105543660046124f7565b600d6020526000908152604090205460ff1681565b610319610577366004612625565b61121a565b6102b361058a3660046124f7565b6005602052600090815260409020546001600160a01b031681565b6103196105b33660046124f7565b61129e565b6102b37f000000000000000000000000fd3e3c69698b722c8fc3c20b853dce35c149f4a081565b61028d6105ed366004612744565b600960209081526000928352604080842090915290825290205481565b610319610618366004612586565b6112eb565b61031961132b565b6102b36106333660046124f7565b61138d565b6102b3610646366004612651565b6119c3565b6103196106593660046124f7565b6119ed565b61031961066c366004612586565b611a68565b6102b37f000000000000000000000000d5dcbddd672b80ea9179a21b7691a34fb85615f281565b60005b815181101561072e578181815181106106b6576106b66127ca565b6020908102919091010151604051630c00007b60e41b81523360048201526001600160a01b039091169063c00007b090602401600060405180830381600087803b15801561070357600080fd5b505af1158015610717573d6000803e3d6000fd5b505050508080610726906127f6565b91505061069b565b5050565b336000908152600d602052604090205460ff166107625760405163aa7a99d160e01b815260040160405180910390fd5b336000908152600e602052604090205460ff1661079257604051635cf06fbb60e01b815260040160405180910390fd5b336000818152600660209081526040918290205482516001600160a01b0387811682529281018690529116917f676e2de14d55ed76a3c1fb73016d65a60e9e45ffb1720966f847bc76fc01904291015b60405180910390a35050565b61081a7f000000000000000000000000fd3e3c69698b722c8fc3c20b853dce35c149f4a0333084611afe565b60035460009061083283670de0b6b3a764000061280f565b61083c919061282c565b9050801561085c5780600f6000828254610856919061284e565b90915550505b6040518281526001600160a01b037f000000000000000000000000fd3e3c69698b722c8fc3c20b853dce35c149f4a0169033907fa7c0e3f096d59a05405bc674c2930dbfe8cdd9db8930398f3578a957a5b327c9906020016107e2565b6004546108c890600090610c97565b565b60005b815181101561072e578181815181106108e8576108e86127ca565b60200260200101516001600160a01b031663dfb89c376040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b50505050808061094d906127f6565b9150506108cd565b6004546108c89060009061100b565b61096c611bf6565b600260009054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af11580156109c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e59190612861565b506109ef81611c4f565b6001600160a01b0381811660008181526011602052604090819020549051634cde602960e11b81527f000000000000000000000000fd3e3c69698b722c8fc3c20b853dce35c149f4a09093166004840152916399bcc05290602401602060405180830381865afa158015610a67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8b9190612861565b81118015610aa557506000610aa362093a808361282c565b115b15610b80576001600160a01b03828116600081815260116020526040808220919091555163b66503cf60e01b81527f000000000000000000000000fd3e3c69698b722c8fc3c20b853dce35c149f4a09092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610b2757600080fd5b505af1158015610b3b573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507fb7d7e9f93634a3439166473675551d7f6e6d8d29acdd43c8868bfeac1c17650f9060200160405180910390a35b50610b8b6001600055565b50565b610b8b81611c4f565b336000818152600c602052604090205462093a80610bb5814261282c565b610bbf919061280f565b1015610bde57604051632cef5c4560e21b815260040160405180910390fd5b838214610bfe5760405163070fd29b60e01b815260040160405180910390fd5b336000818152600c602090815260409182902042905581518782028181018301909352878152610c7e939290918991899182919085019084908082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250611d5092505050565b5050505050565b610c8d61216b565b6108c860006121c5565b815b81811015610cfd57610ceb6005600060048481548110610cbb57610cbb6127ca565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610964565b80610cf5816127f6565b915050610c99565b505050565b600a6020528160005260406000208181548110610d1e57600080fd5b6000918252602090912001546001600160a01b03169150829050565b6001546001600160a01b03163314801590610ddd5750600260009054906101000a90046001600160a01b03166001600160a01b03166385f2aef26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc7919061287a565b6001600160a01b0316336001600160a01b031614155b15610dfb5760405163498eeef360e11b815260040160405180910390fd5b806001600160a01b038116610e235760405163c7a2af7360e01b815260040160405180910390fd5b604051639c9b2e2160e01b81526001600160a01b038381166004830152841690639c9b2e2190602401600060405180830381600087803b158015610e6657600080fd5b505af1158015610e7a573d6000803e3d6000fd5b50506040516001600160a01b038086169350861691507fbfdcae251dd92547c00a8a0235edcb67767e26e9c38e4270c0767c910319262690600090a3505050565b6001546001600160a01b03163314801590610f5e5750600260009054906101000a90046001600160a01b03166001600160a01b03166385f2aef26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f48919061287a565b6001600160a01b0316336001600160a01b031614155b15610f7c5760405163498eeef360e11b815260040160405180910390fd5b6001600160a01b0381166000908152600e602052604090205460ff16610fb557604051635cf06fbb60e01b815260040160405180910390fd5b6001600160a01b0381166000818152600e60209081526040808320805460ff191690556011909152808220829055517f557faf519fb7278ebcd3d18b0674298ba37a470ca81e53c21b2ec03152eb50139190a250565b815b81811015610cfd5761105f600560006004848154811061102f5761102f6127ca565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416611c4f565b80611069816127f6565b91505061100d565b6001546001600160a01b031633148015906111145750600260009054906101000a90046001600160a01b03166001600160a01b03166385f2aef26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110fe919061287a565b6001600160a01b0316336001600160a01b031614155b156111325760405163498eeef360e11b815260040160405180910390fd5b6001600160a01b0381166000908152600e602052604090205460ff161561116c5760405163ac6553cd60e01b815260040160405180910390fd5b6001600160a01b0381166000818152600e6020526040808220805460ff19166001179055517fa3bc6dfaf4a139af831043f7e724799e66ac206addc97cac3f547c6a9e1dc79d9190a250565b6060600480548060200260200160405190810160405280929190818152602001828054801561121057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116111f2575b5050505050905090565b336000908152600d602052604090205460ff1661124a5760405163aa7a99d160e01b815260040160405180910390fd5b336000818152600660209081526040918290205482516001600160a01b0387811682529281018690529116917fb28188e4b81dda8b3fc5cb831e49457c4adb49016c8dfd8a1513cf9894245cab91016107e2565b6002546001600160a01b031633146112c957604051633179cd7560e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60005b815181101561072e5761131982828151811061130c5761130c6127ca565b6020026020010151611c4f565b80611323816127f6565b9150506112ee565b336000818152600c602052604090205462093a80611349814261282c565b611353919061280f565b101561137257604051632cef5c4560e21b815260040160405180910390fd5b336000818152600c6020526040902042905561072e81612217565b60006113a16001546001600160a01b031690565b6001600160a01b0316336001600160a01b03161415801561144a5750600260009054906101000a90046001600160a01b03166001600160a01b03166385f2aef26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611410573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611434919061287a565b6001600160a01b0316336001600160a01b031614155b156114685760405163498eeef360e11b815260040160405180910390fd5b6001600160a01b0382811660009081526005602052604090205416156114a1576040516325d9db2f60e01b815260040160405180910390fd5b604051631e533a8f60e21b81523060048201526001600160a01b0383811660248301526000917f000000000000000000000000ea1db4c7a507a736a0388ff0bfed24b4ba4244299091169063794cea3c906044016020604051808303816000875af1158015611514573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611538919061287a565b604051639c9b2e2160e01b81526001600160a01b037f000000000000000000000000fd3e3c69698b722c8fc3c20b853dce35c149f4a08116600483015291925090821690639c9b2e2190602401600060405180830381600087803b15801561159f57600080fd5b505af11580156115b3573d6000803e3d6000fd5b50506040516355a68ed360e01b81526001600160a01b038481166004830152861692506355a68ed39150602401600060405180830381600087803b1580156115fa57600080fd5b505af115801561160e573d6000803e3d6000fd5b505060405163095ea7b360e01b81526001600160a01b03848116600483015260001960248301527f000000000000000000000000fd3e3c69698b722c8fc3c20b853dce35c149f4a016925063095ea7b391506044016020604051808303816000875af1158015611682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a69190612897565b50604051631af469cb60e21b81523060048201526000907f000000000000000000000000b557fa65af0f482e34799efa76176b269cd88c406001600160a01b031690636bd1a72c906024016020604051808303816000875af1158015611710573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611734919061287a565b90506000846001600160a01b031663e33ca8396040518163ffffffff1660e01b8152600401600060405180830381865afa158015611776573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261179e91908101906128b9565b905060005b815181101561184557826001600160a01b0316639c9b2e218383815181106117cd576117cd6127ca565b60200260200101516040518263ffffffff1660e01b815260040161180091906001600160a01b0391909116815260200190565b600060405180830381600087803b15801561181a57600080fd5b505af115801561182e573d6000803e3d6000fd5b50505050808061183d906127f6565b9150506117a3565b5060405163740ef7e760e11b81526001600160a01b03838116600483015286169063e81defce90602401600060405180830381600087803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b5050506001600160a01b0380871660008181526005602090815260408083208054868b166001600160a01b03199182168117909255600784528285208054978b16978216979097179096558352600682528083208054909516909317909355600d8352818120805460ff199081166001908117909255600e90945291902080549092161790555061192d83611c4f565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b03878116918217909255604080513381528584166020820152928616927fb920b936f556d443772609e0cc06a72c3bb67fc606de10dcdd51323d1ddbc7fc910160405180910390a350909392505050565b600481815481106119d357600080fd5b6000918252602090912001546001600160a01b0316905081565b6119f561216b565b6001600160a01b038116611a5f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b610b8b816121c5565b60005b815181101561072e57818181518110611a8657611a866127ca565b6020908102919091010151604051630c00007b60e41b81523360048201526001600160a01b039091169063c00007b090602401600060405180830381600087803b158015611ad357600080fd5b505af1158015611ae7573d6000803e3d6000fd5b505050508080611af6906127f6565b915050611a6b565b6000846001600160a01b03163b11611b1557600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611b799190612948565b6000604051808303816000865af19150503d8060008114611bb6576040519150601f19603f3d011682016040523d82523d6000602084013e611bbb565b606091505b5091509150818015611be5575080511580611be5575080806020019051810190611be59190612897565b611bee57600080fd5b505050505050565b600260005403611c485760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611a56565b6002600055565b6001600160a01b038082166000908152600660209081526040808320549093168083526008909152919020548015611d2f576001600160a01b03831660009081526010602052604081208054600f549182905591611cad8383612977565b90508015611bee576000670de0b6b3a7640000611cca838761280f565b611cd4919061282c565b6001600160a01b0388166000908152600e602052604090205490915060ff1615611d26576001600160a01b03871660009081526011602052604081208054839290611d2090849061284e565b90915550505b50505050505050565b600f546001600160a01b038416600090815260106020526040902055505050565b611d5983612217565b81516040516370a0823160e01b81526001600160a01b0385811660048301526000917f000000000000000000000000d5dcbddd672b80ea9179a21b7691a34fb85615f2909116906370a0823190602401602060405180830381865afa158015611dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dea9190612861565b90506000806000805b85811015611eae576000888281518110611e0f57611e0f6127ca565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600d909452205490925060ff168015611e6c57506001600160a01b0381166000908152600e602052604090205460ff165b15611e9957888381518110611e8357611e836127ca565b602002602001015186611e96919061284e565b95505b50508080611ea6906127f6565b915050611df3565b5060005b8581101561212e576000888281518110611ece57611ece6127ca565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600d909452205490925060ff168015611f2b57506001600160a01b0381166000908152600e602052604090205460ff165b1561211957600086888b8681518110611f4657611f466127ca565b6020026020010151611f58919061280f565b611f62919061282c565b6001600160a01b03808e1660009081526009602090815260408083209388168352929052205490915015611f9557600080fd5b80600003611fa257600080fd5b611fab82611c4f565b6001600160a01b038c81166000908152600a6020908152604080832080546001810182559084528284200180546001600160a01b031916948816948517905592825260089052908120805483929061200490849061284e565b90915550506001600160a01b03808d1660009081526009602090815260408083209387168352929052908120805483929061204090849061284e565b90915550506001600160a01b0380841660009081526007602052604090819020549051630463cd9760e41b8152600481018490528e8316602482015291169063463cd97090604401600060405180830381600087803b1580156120a257600080fd5b505af11580156120b6573d6000803e3d6000fd5b5050505080856120c6919061284e565b94506120d2818761284e565b95508b6001600160a01b03167f4e79ebbde53238af74dcfc3a1819c8bce25caeca7056ea649e4243650874d5b28260405161210f91815260200190565b60405180910390a2505b50508080612126906127f6565b915050611eb2565b508160036000828254612141919061284e565b90915550506001600160a01b039097166000908152600b6020526040902096909655505050505050565b6001546001600160a01b031633146108c85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611a56565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0381166000908152600a6020526040812080549091805b82811015612464576000848281548110612251576122516127ca565b60009182526020808320909101546001600160a01b03898116845260098352604080852091909216808552925290912054909150801561244f576001600160a01b038083166000908152600560205260409020546122af9116611c4f565b6001600160a01b038216600090815260086020526040812080548392906122d7908490612977565b90915550506001600160a01b03808816600090815260096020908152604080832093861683529290529081208054839290612313908490612977565b90915550506001600160a01b03828116600090815260076020526040908190205490516370a0823160e01b8152898316600482015291169063293311ab9082906370a0823190602401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d9190612861565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b038a166024820152604401600060405180830381600087803b1580156123e557600080fd5b505af11580156123f9573d6000803e3d6000fd5b505050508084612409919061284e565b604080516001600160a01b038a168152602081018490529195507f606e9fc568ae450083d6885f24864ca5d406faf7b0bfc1eb2132caaf25b8e02d910160405180910390a15b5050808061245c906127f6565b915050612235565b5080600360008282546124779190612977565b90915550506001600160a01b0384166000908152600b60209081526040808320839055600a90915281206124aa916124b0565b50505050565b5080546000825590600052602060002090810190610b8b91905b808211156124de57600081556001016124ca565b5090565b6001600160a01b0381168114610b8b57600080fd5b60006020828403121561250957600080fd5b8135612514816124e2565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561255a5761255a61251b565b604052919050565b600067ffffffffffffffff82111561257c5761257c61251b565b5060051b60200190565b6000602080838503121561259957600080fd5b823567ffffffffffffffff8111156125b057600080fd5b8301601f810185136125c157600080fd5b80356125d46125cf82612562565b612531565b81815260059190911b820183019083810190878311156125f357600080fd5b928401925b8284101561261a57833561260b816124e2565b825292840192908401906125f8565b979650505050505050565b6000806040838503121561263857600080fd5b8235612643816124e2565b946020939093013593505050565b60006020828403121561266357600080fd5b5035919050565b60008083601f84011261267c57600080fd5b50813567ffffffffffffffff81111561269457600080fd5b6020830191508360208260051b85010111156126af57600080fd5b9250929050565b600080600080604085870312156126cc57600080fd5b843567ffffffffffffffff808211156126e457600080fd5b6126f08883890161266a565b9096509450602087013591508082111561270957600080fd5b506127168782880161266a565b95989497509550505050565b6000806040838503121561273557600080fd5b50508035926020909101359150565b6000806040838503121561275757600080fd5b8235612762816124e2565b91506020830135612772816124e2565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156127be5783516001600160a01b031683529284019291840191600101612799565b50909695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612808576128086127e0565b5060010190565b8082028115828204841417612826576128266127e0565b92915050565b60008261284957634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115612826576128266127e0565b60006020828403121561287357600080fd5b5051919050565b60006020828403121561288c57600080fd5b8151612514816124e2565b6000602082840312156128a957600080fd5b8151801515811461251457600080fd5b600060208083850312156128cc57600080fd5b825167ffffffffffffffff8111156128e357600080fd5b8301601f810185136128f457600080fd5b80516129026125cf82612562565b81815260059190911b8201830190838101908783111561292157600080fd5b928401925b8284101561261a578351612939816124e2565b82529284019290840190612926565b6000825160005b81811015612969576020818601810151858301520161294f565b506000920191825250919050565b81810381811115612826576128266127e056fea264697066735822122059c0f41993eaa95bffd62176b7f806c128aa5afcc1487cb4aafafe6bf388f93b64736f6c63430008130033

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

000000000000000000000000d5dcbddd672b80ea9179a21b7691a34fb85615f2000000000000000000000000ea1db4c7a507a736a0388ff0bfed24b4ba424429000000000000000000000000b557fa65af0f482e34799efa76176b269cd88c40

-----Decoded View---------------
Arg [0] : _VTOKEN (address): 0xD5dCbDdd672b80EA9179A21B7691A34fb85615F2
Arg [1] : _gaugefactory (address): 0xeA1DB4c7a507A736A0388fF0bFeD24b4bA424429
Arg [2] : _bribefactory (address): 0xb557Fa65aF0f482E34799eFA76176B269Cd88c40

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000d5dcbddd672b80ea9179a21b7691a34fb85615f2
Arg [1] : 000000000000000000000000ea1db4c7a507a736a0388ff0bfed24b4ba424429
Arg [2] : 000000000000000000000000b557fa65af0f482e34799efa76176b269cd88c40


Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

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