Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
Voter
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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; } }
// 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); } }
// 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; } }
// 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); }
// 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; } }
// 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); } } }
// 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); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; interface IBribeFactory { /*---------- FUNCTIONS --------------------------------------------*/ /*---------- RESTRICTED FUNCTIONS ---------------------------------*/ function createBribe(address voter) external returns (address); /*---------- VIEW FUNCTIONS ---------------------------------------*/ }
// 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); }
// 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 ---------------------------------------*/ }
// 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); }
// 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); }
// 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); }
{ "optimizer": { "enabled": true, "runs": 200, "details": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.