Overview
ETH Balance
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
15450678 | 77 days ago | 0 ETH | ||||
15450350 | 77 days ago | 0 ETH | ||||
15450275 | 77 days ago | 0 ETH | ||||
15450083 | 77 days ago | 0 ETH | ||||
15449365 | 77 days ago | 0 ETH | ||||
15449342 | 77 days ago | 0 ETH | ||||
15449315 | 77 days ago | 0 ETH | ||||
15449094 | 77 days ago | 0 ETH | ||||
15449084 | 77 days ago | 0 ETH | ||||
15448997 | 77 days ago | 0 ETH | ||||
15448956 | 77 days ago | 0 ETH | ||||
15448875 | 77 days ago | 0 ETH | ||||
15448608 | 77 days ago | 0 ETH | ||||
15448426 | 77 days ago | 0 ETH | ||||
15448376 | 77 days ago | 0 ETH | ||||
15447942 | 77 days ago | 0 ETH | ||||
15447912 | 77 days ago | 0 ETH | ||||
15447892 | 77 days ago | 0 ETH | ||||
15447878 | 77 days ago | 0 ETH | ||||
15447874 | 77 days ago | 0 ETH | ||||
15447871 | 77 days ago | 0 ETH | ||||
15447786 | 77 days ago | 0 ETH | ||||
15447462 | 77 days ago | 0 ETH | ||||
15447253 | 77 days ago | 0 ETH | ||||
15447174 | 77 days ago | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
VoterV5
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; // Package Imports import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; // Local Imports import {IBribe} from "./IBribe.sol"; import {IGauge} from "../interfaces/IGauge.sol"; import {IOptionTokenV3} from '../OptionToken/IOptionTokenV3.sol'; import {IMinter} from "../interfaces/IMinter.sol"; import {IPermissionsRegistry} from "../interfaces/IPermissionsRegistry.sol"; import {IVoterV5_GaugeLogic} from "./VoterV5_GaugeLogic.sol"; import {Constants} from "../Constants.sol"; import {VoterV5_Storage} from "./VoterV5_Storage.sol"; import {IVotingEscrowV2} from "./VotingEscrow/interfaces/IVotingEscrowV2.sol"; import {DelegateCallLib} from "../libraries/DelegateCallLib.sol"; contract VoterV5 is VoterV5_Storage, ReentrancyGuardUpgradeable { using SafeERC20 for IERC20; event GaugeCreated( address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool ); event GaugeKilled(address indexed gauge); event GaugeRevived(address indexed gauge); event Voted(address indexed voter, uint256 weight); event Abstained(address voter, uint256 weight); event NotifyReward(address indexed sender, address indexed reward, uint256 amount); event DistributeReward(address indexed sender, address indexed gauge, uint256 amount); event Whitelisted(address indexed whitelister, address indexed token); event WhitelistedPool(address indexed whitelister, address indexed token); event Blacklisted(address indexed blacklister, address indexed token); event Attach(address indexed owner, address indexed gauge, uint256 tokenId); event Detach(address indexed owner, address indexed gauge, uint256 tokenId); event SetMinter(address indexed old, address indexed latest); event SetOptions(address indexed old, address indexed latest); event SetDepositor(address indexed old, bool enabled); event SetBribeFactory(address indexed old, address indexed latest); event SetPairFactory(address indexed old, address indexed latest); event SetPermissionRegistry(address indexed old, address indexed latest); event SetGaugeFactory(address indexed old, address indexed latest); event SetBribeFor(bool isInternal, address indexed old, address indexed latest, address indexed gauge); event SetVoteDelay(uint256 old, uint256 latest); event AddFactories(address indexed pairfactory, address indexed gaugefactory); error InsufficientVotingPower(); constructor() {} function initialize( address __ve, address _pairFactory, address _gaugeFactory, address _bribes, address _gaugeLogic ) public initializer { // __Ownable_init(); __ReentrancyGuard_init(); _ve = __ve; base = address(IVotingEscrowV2(__ve).token()); _factories.push(_pairFactory); isFactory[_pairFactory]++; _gaugeFactories.push(_gaugeFactory); isGaugeFactory[_gaugeFactory] = true; bribefactory = _bribes; minter = msg.sender; permissionRegistry = msg.sender; VOTE_DELAY = 0; DURATION = Constants.EPOCH; MAX_VOTE_DELAY = Constants.EPOCH; initflag = false; gaugeLogic = IVoterV5_GaugeLogic(_gaugeLogic); } /* ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- MODIFIERS -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ /// @dev Using function instead of modifier to save gas function VoterAdmin() private view { require(IPermissionsRegistry(permissionRegistry).hasRole("VOTER_ADMIN", msg.sender), "VOTER_ADMIN"); } /// @dev Using function instead of modifier to save gas function Governance() private view { require(IPermissionsRegistry(permissionRegistry).hasRole("GOVERNANCE", msg.sender), "GOVERNANCE"); } /// @notice initialize the voter contract /// @param _tokens array of tokens to whitelist /// @param _minter the minter of $lynx function _init(address[] memory _tokens, address _permissionsRegistry, address _minter, address _oLynx) external { require(msg.sender == minter || IPermissionsRegistry(permissionRegistry).hasRole("VOTER_ADMIN", msg.sender)); require(!initflag); for (uint256 i = 0; i < _tokens.length; i++) { _whitelist(_tokens[i]); } minter = _minter; permissionRegistry = _permissionsRegistry; if (_oLynx != address(0)) { oLynx = _oLynx; /// @dev base must be approved to mint oLynx. IERC20(base).approve(oLynx, type(uint256).max); } isGaugeDepositor[oLynx] = true; initflag = true; } /* ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- VoterAdmin -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ /// @notice set vote delay in seconds function setVoteDelay(uint256 _delay) external { VoterAdmin(); require(_delay != VOTE_DELAY, "already set"); require(_delay <= MAX_VOTE_DELAY, "max delay"); emit SetVoteDelay(VOTE_DELAY, _delay); VOTE_DELAY = _delay; } /// @notice Set a new Minter function setMinter(address _minter) external { VoterAdmin(); require(_minter != address(0), "addr0"); require(_minter.code.length > 0, "!contract"); emit SetMinter(minter, _minter); minter = _minter; } /// @notice Set options token function setOptionsToken(address _oToken) external { VoterAdmin(); require(_oToken.code.length > 0, "!contract"); emit SetOptions(oLynx, _oToken); address oldToken = oLynx; if(oldToken != address(0)) IERC20(base).approve(oldToken, 0); isGaugeDepositor[oldToken] = false; oLynx = _oToken; IERC20(base).approve(oLynx, type(uint256).max); isGaugeDepositor[oLynx] = true; /// @dev this is to avoid gas limits. If this happens the function will need to be manually ran externally uint256 stop = pools.length < 100 ? pools.length : 100; if (pools.length > 0) refreshApprovals(0, stop, oldToken); } /// @notice revoke oldOtoken approval and include new one /// @param start start index point of the pools array /// @param finish finish index point of the pools array /// @param _oldOtoken token to revoke /// @dev this function is manually used in case we have too many pools and gasLimit is reached function refreshApprovals(uint256 start, uint256 finish, address _oldOtoken) public nonReentrant { VoterAdmin(); for (uint256 x = start; x < finish; x++) { _refreshApproval(gauges[pools[x]], _oldOtoken); } } function _refreshApproval(address _gauge, address _oldOtoken) internal { if(_oldOtoken != address(0)) { IERC20(_oldOtoken).approve(_gauge, 0); } if (oLynx == address(0)) { IERC20(base).approve(_gauge, type(uint256).max); } else { IERC20(oLynx).approve(_gauge, type(uint256).max); IERC20(base).approve(_gauge, 0); } } /// @notice Set depositor that can deposit locked token on behalf of user token function setGaugeDepositor(address _depositor, bool _enabled) external { VoterAdmin(); isGaugeDepositor[_depositor] = _enabled; emit SetDepositor(_depositor, _enabled); } /// @notice Set a new Bribe Factory function setBribeFactory(address _bribeFactory) external { VoterAdmin(); require(_bribeFactory.code.length > 0, "!contract"); require(_bribeFactory != address(0), "addr0"); emit SetBribeFactory(bribefactory, _bribeFactory); bribefactory = _bribeFactory; } /// @notice Set a new PermissionRegistry function setPermissionsRegistry(address _permissionRegistry) external { VoterAdmin(); require(_permissionRegistry.code.length > 0, "!contract"); require(_permissionRegistry != address(0), "addr0"); emit SetPermissionRegistry(permissionRegistry, _permissionRegistry); permissionRegistry = _permissionRegistry; } /// @notice Set a new bribes for a given gauge function setNewBribes(address _gauge, address _internal, address _external) external { VoterAdmin(); require(isGauge[_gauge], "!gauge"); require(_gauge.code.length > 0, "!contract"); _setInternalBribe(_gauge, _internal); _setExternalBribe(_gauge, _external); } /// @notice Set a new internal bribe for a given gauge function setInternalBribeFor(address _gauge, address _internal) external { VoterAdmin(); require(isGauge[_gauge], "!gauge"); _setInternalBribe(_gauge, _internal); } /// @notice Set a new External bribe for a given gauge function setExternalBribeFor(address _gauge, address _external) external { VoterAdmin(); require(isGauge[_gauge], "!gauge"); _setExternalBribe(_gauge, _external); } function _setInternalBribe(address _gauge, address _internal) private { require(_internal.code.length > 0, "!contract"); emit SetBribeFor(true, internal_bribes[_gauge], _internal, _gauge); internal_bribes[_gauge] = _internal; } function _setExternalBribe(address _gauge, address _external) private { require(_external.code.length > 0, "!contract"); emit SetBribeFor(false, internal_bribes[_gauge], _external, _gauge); external_bribes[_gauge] = _external; } function addFactory(address _pairFactory, address _gaugeFactory) external { VoterAdmin(); require(_pairFactory != address(0), "addr0"); require(_gaugeFactory != address(0), "addr0"); require(!isGaugeFactory[_gaugeFactory], "gFact"); require(_pairFactory.code.length > 0, "!contract"); require(_gaugeFactory.code.length > 0, "!contract"); _factories.push(_pairFactory); _gaugeFactories.push(_gaugeFactory); isFactory[_pairFactory]++; isGaugeFactory[_gaugeFactory] = true; emit AddFactories(_pairFactory, _gaugeFactory); } function replaceFactory(address _pairFactory, address _gaugeFactory, uint256 _pos) external { VoterAdmin(); require(_pairFactory != address(0), "addr0"); require(_gaugeFactory != address(0), "addr0"); require(isGaugeFactory[_gaugeFactory], "!gFact"); address oldPF = _factories[_pos]; address oldGF = _gaugeFactories[_pos]; isFactory[oldPF]--; isGaugeFactory[oldGF] = false; _factories[_pos] = (_pairFactory); _gaugeFactories[_pos] = (_gaugeFactory); isFactory[_pairFactory]++; isGaugeFactory[_gaugeFactory] = true; emit SetGaugeFactory(oldGF, _gaugeFactory); emit SetPairFactory(oldPF, _pairFactory); } function removeFactory(uint256 _pos) external { VoterAdmin(); address oldPF = _factories[_pos]; address oldGF = _gaugeFactories[_pos]; require(isFactory[oldPF] > 0, "!fact"); require(isGaugeFactory[oldGF], "!gFact"); _factories[_pos] = address(0); _gaugeFactories[_pos] = address(0); isFactory[oldPF]--; isGaugeFactory[oldGF] = false; emit SetGaugeFactory(oldGF, address(0)); emit SetPairFactory(oldPF, address(0)); } /* ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- GOVERNANCE -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ /// @notice Whitelist a token for gauge creation function whitelist(address[] memory _token) external { Governance(); uint256 i = 0; for (i = 0; i < _token.length; i++) { _whitelist(_token[i]); } } function _whitelist(address _token) private { require(!isWhitelisted[_token], "in"); require(_token.code.length > 0, "!contract"); isWhitelisted[_token] = true; emit Whitelisted(msg.sender, _token); } /// @notice Whitelist a pool for gauge creation function whitelistPool(address[] memory _pool) external { Governance(); uint256 i = 0; for (i = 0; i < _pool.length; i++) { _whitelistPool(_pool[i]); } } function _whitelistPool(address _token) private { require(!isWhitelistedPool[_token], "in"); require(_token.code.length > 0, "!contract"); isWhitelistedPool[_token] = true; emit WhitelistedPool(msg.sender, _token); } /// @notice Blacklist a malicious token function blacklist(address[] memory _token) external { Governance(); uint256 i = 0; for (i = 0; i < _token.length; i++) { _blacklist(_token[i]); } } function _blacklist(address _token) private { require(isWhitelisted[_token], "out"); isWhitelisted[_token] = false; emit Blacklisted(msg.sender, _token); } /// @notice Kill a malicious gauge /// @param _gauge gauge to kill function killGauge(address _gauge) external { Governance(); require(isAlive[_gauge], "killed"); // disable allowance IERC20(base).approve(_gauge, 0); IERC20(oLynx).approve(_gauge, 0); // Return claimable back to minter uint256 _claimable = claimable[_gauge]; if (_claimable > 0) { IERC20(base).safeTransfer(minter, _claimable); delete claimable[_gauge]; } isAlive[_gauge] = false; claimable[_gauge] = 0; uint _time = _epochTimestamp(); totalWeightsPerEpoch[_time] -= weightsPerEpoch[_time][poolForGauge[_gauge]]; emit GaugeKilled(_gauge); } /// @notice Revive a malicious gauge /// @param _gauge gauge to revive function reviveGauge(address _gauge) external { Governance(); require(!isAlive[_gauge], "alive"); require(isGauge[_gauge], "not a gauge"); isAlive[_gauge] = true; // reset allowance IERC20(base).approve(_gauge, type(uint256).max); IERC20(oLynx).approve(_gauge, type(uint256).max); emit GaugeRevived(_gauge); } /* ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- USER INTERACTION -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ /// @notice Reset the votes of a given TokenID function reset() external nonReentrant { address _voter = msg.sender; _voteDelay(_voter); _reset(_voter); lastVoted[_voter] = _epochTimestamp() + 1; } function _reset(address _voter) internal { address[] storage _poolVote = poolVote[_voter]; uint256 _poolVoteCnt = _poolVote.length; uint256 _totalWeight = 0; uint256 _time = _epochTimestamp(); bool votedInEpoch = lastVoted[_voter] > _time; for (uint256 i = 0; i < _poolVoteCnt; i++) { address _pool = _poolVote[i]; uint256 _votes = votes[_voter][_pool]; if (_votes != 0) { // if user last vote is < than epochTimestamp then votes are 0! IF not underflow occur if (votedInEpoch) weightsPerEpoch[_time][_pool] -= _votes; votes[_voter][_pool] -= _votes; IBribe(internal_bribes[gauges[_pool]]).withdraw(uint256(_votes), _voter); IBribe(external_bribes[gauges[_pool]]).withdraw(uint256(_votes), _voter); // if is alive remove _votes, else don't because we already done it in killGauge() if (isAlive[gauges[_pool]]) _totalWeight += _votes; emit Abstained(_voter, _votes); } } // if user last vote is < than epochTimestamp then _totalWeight is 0! IF not underflow occur if (lastVoted[_voter] < _time) _totalWeight = 0; totalWeightsPerEpoch[_time] -= _totalWeight; delete poolVote[_voter]; } /// @notice Recast the saved votes of a given TokenID function poke() external nonReentrant { address _voter = msg.sender; _voteDelay(_voter); address[] memory _poolVote = poolVote[_voter]; uint256 _poolCnt = _poolVote.length; uint256[] memory _weights = new uint256[](_poolCnt); for (uint256 i = 0; i < _poolCnt; i++) { _weights[i] = votes[_voter][_poolVote[i]]; } _vote(_voter, _poolVote, _weights); lastVoted[_voter] = _epochTimestamp() + 1; } /// @notice Vote for pools /// @param _poolVote array of LPs addresses to vote (eg.: [sAMM usdc-usdt , sAMM busd-usdt, vAMM wbnb-the ,...]) /// @param _weights array of weights for each LPs (eg.: [10 , 90 , 45 ,...]) function vote(address[] calldata _poolVote, uint256[] calldata _weights) external nonReentrant { _voteDelay(msg.sender); require(_poolVote.length == _weights.length, "Pool/Weights length !="); _vote(msg.sender, _poolVote, _weights); lastVoted[msg.sender] = _epochTimestamp() + 1; } function _vote(address _voter, address[] memory _poolVote, uint256[] memory _weights) internal { _reset(_voter); uint256 _poolCnt = _poolVote.length; uint256 _time = _epochTimestamp(); uint256 _weight = IVotingEscrowV2(_ve).getPastVotes(_voter, _time); uint256 _totalVoteWeight = 0; uint256 _totalWeight = 0; uint256 _usedWeight = 0; for (uint i = 0; i < _poolCnt; i++) { if (isAlive[gauges[_poolVote[i]]]) _totalVoteWeight += _weights[i]; } for (uint256 i = 0; i < _poolCnt; i++) { address _pool = _poolVote[i]; address _gauge = gauges[_pool]; if (isGauge[_gauge] && isAlive[_gauge]) { uint256 _poolWeight = (_weights[i] * _weight) / _totalVoteWeight; require(votes[_voter][_pool] == 0); if (_poolWeight == 0) revert InsufficientVotingPower(); poolVote[_voter].push(_pool); weightsPerEpoch[_time][_pool] += _poolWeight; votes[_voter][_pool] += _poolWeight; IBribe(internal_bribes[_gauge]).deposit(uint256(_poolWeight), _voter); IBribe(external_bribes[_gauge]).deposit(uint256(_poolWeight), _voter); _usedWeight += _poolWeight; _totalWeight += _poolWeight; emit Voted(msg.sender, _poolWeight); } } /// @note shall we store when voting? // if (_usedWeight > 0) IVotingEscrowV2(_ve).voting(_voter); totalWeightsPerEpoch[_time] += _totalWeight; } /// @notice claim LP gauge rewards function claimRewards(address[] memory _gauges) external { for (uint256 i = 0; i < _gauges.length; i++) { IGauge(_gauges[i]).getReward(msg.sender); } } /// @notice claim bribes rewards given a TokenID function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint256 _tokenId) external { require(IVotingEscrowV2(_ve).isApprovedOrOwner(msg.sender, _tokenId), "!approved/Owner"); require(_bribes.length == _tokens.length, "Bribes/Tokens length !="); for (uint256 i = 0; i < _bribes.length; i++) { IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]); } } /// @notice claim fees rewards given a TokenID function claimFees(address[] memory _fees, address[][] memory _tokens, uint256 _tokenId) external { require(IVotingEscrowV2(_ve).isApprovedOrOwner(msg.sender, _tokenId), "!approved/Owner"); require(_fees.length == _tokens.length, "Fee/Tokens length !="); for (uint256 i = 0; i < _fees.length; i++) { IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]); } } /// @notice claim bribes rewards given an address function claimBribes(address[] memory _bribes, address[][] memory _tokens) external { require(_bribes.length == _tokens.length, "Bribes/Tokens length !="); for (uint256 i = 0; i < _bribes.length; i++) { IBribe(_bribes[i]).getRewardForAddress(msg.sender, _tokens[i]); } } /// @notice claim fees rewards given an address function claimFees(address[] memory _bribes, address[][] memory _tokens) external { require(_bribes.length == _tokens.length, "Fee/Tokens length !="); for (uint256 i = 0; i < _bribes.length; i++) { IBribe(_bribes[i]).getRewardForAddress(msg.sender, _tokens[i]); } } /// @notice check if user can vote function _voteDelay(address _voter) internal view { require(block.timestamp > lastVoted[_voter] + VOTE_DELAY && block.timestamp > _epochTimestamp(), "ERR: VOTE_DELAY"); } /* ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- GAUGE CREATION -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ /// @notice create multiple gauges function createGauges( address[] memory _pool, uint256[] memory _gaugeTypes ) external nonReentrant returns (address[] memory, address[] memory, address[] memory) { require(_pool.length == _gaugeTypes.length, "len mismatch"); require(_pool.length <= 10, "max 10"); address[] memory _gauge = new address[](_pool.length); address[] memory _int = new address[](_pool.length); address[] memory _ext = new address[](_pool.length); uint256 i = 0; for (i; i < _pool.length; i++) { (_gauge[i], _int[i], _ext[i]) = _createGauge(_pool[i], _gaugeTypes[i]); } return (_gauge, _int, _ext); } /// @notice create a gauge function createGauge( address _pool, uint256 _gaugeType ) external nonReentrant returns (address _gauge, address _internal_bribe, address _external_bribe) { (_gauge, _internal_bribe, _external_bribe) = _createGauge(_pool, _gaugeType); } /// @notice create a gauge /// @param _pool LP address /// @param _gaugeType the type of the gauge you want to create /// @dev Logic offloaded to VoterV5_GaugeLogic contract to bring contract size into 24kb range. /// See gaugeLogic contract for more details. function _createGauge( address _pool, uint256 _gaugeType ) internal returns (address _gauge, address _internal_bribe, address _external_bribe) { (bool success, bytes memory initialResult) = address(gaugeLogic).delegatecall( abi.encodeWithSelector(IVoterV5_GaugeLogic.createGauge.selector, _pool, _gaugeType) ); bytes memory result = DelegateCallLib.handleDelegateCallResult(success, initialResult); // Decode the result (_gauge, _internal_bribe, _external_bribe) = abi.decode(result, (address, address, address)); emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool); } /* ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- VIEW FUNCTIONS -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ /// @notice view the total length of the pools function length() external view returns (uint256) { return pools.length; } /// @notice view the total length of the voted pools given a tokenId function poolVoteLength(address voter) external view returns (uint256) { return poolVote[voter].length; } function factories() external view returns (address[] memory) { return _factories; } function factoryLength() external view returns (uint256) { return _factories.length; } function gaugeFactories() external view returns (address[] memory) { return _gaugeFactories; } function gaugeFactoriesLength() external view returns (uint256) { return _gaugeFactories.length; } function weights(address _pool) public view returns (uint256) { uint256 _time = _epochTimestamp(); return weightsPerEpoch[_time][_pool]; } function weightsAt(address _pool, uint256 _time) public view returns (uint256) { return weightsPerEpoch[_time][_pool]; } function totalWeight() public view returns (uint256) { uint256 _time = _epochTimestamp(); return totalWeightsPerEpoch[_time]; } function totalWeightAt(uint256 _time) public view returns (uint256) { return totalWeightsPerEpoch[_time]; } function _epochTimestamp() public view returns (uint256) { return IMinter(minter).active_period(); } /* ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- DISTRIBUTION -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ /// @notice notify reward amount for gauge /// @dev the function is called by the minter each epoch. Anyway anyone can top up some extra rewards. /// @param amount amount to distribute function notifyRewardAmount(uint256 amount) external { require(msg.sender == minter, "!minter"); IERC20(base).safeTransferFrom(msg.sender, address(this), amount); uint256 _totalWeight = totalWeightAt(_epochTimestamp() - Constants.EPOCH); // minter call notify after updates active_period, loads votes - 1 week uint256 _ratio = 0; if (_totalWeight > 0) _ratio = (amount * 1e18) / _totalWeight; // 1e18 adjustment is removed during claim if (_ratio > 0) { index += _ratio; } emit NotifyReward(msg.sender, base, amount); } /// @notice distribute the LP Fees to the internal bribes /// @param _gauges gauge address where to claim the fees /// @dev the gauge is the owner of the LPs so it has to claim function distributeFees(address[] memory _gauges) external { for (uint256 i = 0; i < _gauges.length; i++) { if (isGauge[_gauges[i]] && isAlive[_gauges[i]]) { IGauge(_gauges[i]).claimFees(); } } } /// @notice Distribute the emission for ALL gauges function distributeAll() external nonReentrant { IMinter(minter).update_period(); uint256 x = 0; uint256 stop = pools.length; for (x; x < stop; x++) { _distribute(gauges[pools[x]]); } } /// @notice distribute the emission for N gauges /// @param start start index point of the pools array /// @param finish finish index point of the pools array /// @dev this function is used in case we have too many pools and gasLimit is reached function distribute(uint256 start, uint256 finish) public nonReentrant { IMinter(minter).update_period(); for (uint256 x = start; x < finish; x++) { _distribute(gauges[pools[x]]); } } /// @notice distribute reward onyl for given gauges /// @dev this function is used in case some distribution fails function distribute(address[] memory _gauges) external nonReentrant { IMinter(minter).update_period(); for (uint256 x = 0; x < _gauges.length; x++) { _distribute(_gauges[x]); } } /// @notice distribute the emission function _distribute(address _gauge) internal { uint256 lastTimestamp = gaugesDistributionTimestamp[_gauge]; uint256 currentTimestamp = _epochTimestamp(); if (lastTimestamp < currentTimestamp) { _updateForAfterDistribution(_gauge); // should set claimable to 0 if killed uint256 _claimable = claimable[_gauge]; // distribute only if claimable is > 0, currentEpoch != lastepoch and gauge is alive if (_claimable > 0 && isAlive[_gauge]) { claimable[_gauge] = 0; gaugesDistributionTimestamp[_gauge] = currentTimestamp; /// @dev approvals set to MAX_UINT256 in _createGauge() if (oLynx != address(0)) { IOptionTokenV3(oLynx).mint(address(this), _claimable); IGauge(_gauge).notifyRewardAmount(oLynx, _claimable); } else { IGauge(_gauge).notifyRewardAmount(base, _claimable); } emit DistributeReward(msg.sender, _gauge, _claimable); } } } /* ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- HELPERS -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ /// @notice update info for gauges /// @dev this function track the gauge index to emit the correct $lynx amount after the distribution function _updateForAfterDistribution(address _gauge) private { address _pool = poolForGauge[_gauge]; uint256 _time = _epochTimestamp() - Constants.EPOCH; uint256 _supplied = weightsPerEpoch[_time][_pool]; if (_supplied > 0) { uint256 _supplyIndex = supplyIndex[_gauge]; uint256 _index = index; // get global index0 for accumulated distro supplyIndex[_gauge] = _index; // update _gauge current position to global position uint256 _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued if (_delta > 0) { uint256 _share = (_supplied * _delta) / 1e18; // add accrued difference for each supplied token if (isAlive[_gauge]) { claimable[_gauge] += _share; } else { IERC20(base).safeTransfer(minter, _share); // send rewards back to Minter so they're not stuck in Voter } } } else { supplyIndex[_gauge] = index; // new users are set to the default global state } } function ve() external view returns (address) { return _ve; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /** * @title The interface for the Algebra Factory * @dev Credit to Uniswap Labs under GPL-2.0-or-later license: * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces */ interface IAlgebraFactory { /** * @notice Emitted when the owner of the factory is changed * @param newOwner The owner after the owner was changed */ event Owner(address indexed newOwner); /** * @notice Emitted when the vault address is changed * @param newVaultAddress The vault address after the address was changed */ event VaultAddress(address indexed newVaultAddress); /** * @notice Emitted when a pool is created * @param token0 The first token of the pool by address sort order * @param token1 The second token of the pool by address sort order * @param pool The address of the created pool */ event Pool(address indexed token0, address indexed token1, address pool); /** * @notice Emitted when the farming address is changed * @param newFarmingAddress The farming address after the address was changed */ event FarmingAddress(address indexed newFarmingAddress); event FeeConfiguration( uint16 alpha1, uint16 alpha2, uint32 beta1, uint32 beta2, uint16 gamma1, uint16 gamma2, uint32 volumeBeta, uint16 volumeGamma, uint16 baseFee ); /** * @notice Returns the current owner of the factory * @dev Can be changed by the current owner via setOwner * @return The address of the factory owner */ function owner() external view returns (address); /** * @notice Returns the current poolDeployerAddress * @return The address of the poolDeployer */ function poolDeployer() external view returns (address); /** * @dev Is retrieved from the pools to restrict calling * certain functions not by a tokenomics contract * @return The tokenomics contract address */ function farmingAddress() external view returns (address); function vaultAddress() external view returns (address); /** * @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist * @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order * @param tokenA The contract address of either token0 or token1 * @param tokenB The contract address of the other token * @return pool The pool address */ function poolByPair(address tokenA, address tokenB) external view returns (address pool); /** * @notice Creates a pool for the given two tokens and fee * @param tokenA One of the two tokens in the desired pool * @param tokenB The other of the two tokens in the desired pool * @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved * from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments * are invalid. * @return pool The address of the newly created pool */ function createPool(address tokenA, address tokenB) external returns (address pool); /** * @notice Updates the owner of the factory * @dev Must be called by the current owner * @param _owner The new owner of the factory */ function setOwner(address _owner) external; /** * @dev updates tokenomics address on the factory * @param _farmingAddress The new tokenomics contract address */ function setFarmingAddress(address _farmingAddress) external; /** * @dev updates vault address on the factory * @param _vaultAddress The new vault contract address */ function setVaultAddress(address _vaultAddress) external; /** * @notice Changes initial fee configuration for new pools * @dev changes coefficients for sigmoids: α / (1 + e^( (β-x) / γ)) * alpha1 + alpha2 + baseFee (max possible fee) must be <= type(uint16).max * gammas must be > 0 * @param alpha1 max value of the first sigmoid * @param alpha2 max value of the second sigmoid * @param beta1 shift along the x-axis for the first sigmoid * @param beta2 shift along the x-axis for the second sigmoid * @param gamma1 horizontal stretch factor for the first sigmoid * @param gamma2 horizontal stretch factor for the second sigmoid * @param volumeBeta shift along the x-axis for the outer volume-sigmoid * @param volumeGamma horizontal stretch factor the outer volume-sigmoid * @param baseFee minimum possible fee */ function setBaseFeeConfiguration( uint16 alpha1, uint16 alpha2, uint32 beta1, uint32 beta2, uint16 gamma1, uint16 gamma2, uint32 volumeBeta, uint16 volumeGamma, uint16 baseFee ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ReentrancyGuardUpgradeable is Initializable { // 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; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _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; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol) pragma solidity ^0.8.0; /** * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts. * * _Available since v4.5._ */ interface IVotes { /** * @dev Emitted when an account changes their delegate. */ event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); /** * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes. */ event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); /** * @dev Returns the current amount of votes that `account` has. */ function getVotes(address account) external view returns (uint256); /** * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is * configured to use block numbers, this will return the value at the end of the corresponding block. */ function getPastVotes(address account, uint256 timepoint) external view returns (uint256); /** * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is * configured to use block numbers, this will return the value at the end of the corresponding block. * * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. * Votes that have not been delegated are still part of total supply, even though they would not participate in a * vote. */ function getPastTotalSupply(uint256 timepoint) external view returns (uint256); /** * @dev Returns the delegate that `account` has chosen. */ function delegates(address account) external view returns (address); /** * @dev Delegates votes from the sender to `delegatee`. */ function delegate(address delegatee) external; /** * @dev Delegates votes from signer to `delegatee`. */ function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5805.sol) pragma solidity ^0.8.0; import "../governance/utils/IVotes.sol"; import "./IERC6372.sol"; interface IERC5805 is IERC6372, IVotes {}
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol) pragma solidity ^0.8.0; interface IERC6372 { /** * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting). */ function clock() external view returns (uint48); /** * @dev Description of the clock */ // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// 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 (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// 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.13; library Constants { uint48 constant EPOCH = 1 weeks; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IBribeFactory { function createInternalBribe(address[] memory) external returns (address); function createExternalBribe(address[] memory) external returns (address); function createBribe(address _owner,address _token0,address _token1, string memory _type) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IERC20 { function totalSupply() external view returns (uint256); function transfer(address recipient, uint amount) external returns (bool); function decimals() external view returns (uint8); function symbol() external view returns (string memory); function balanceOf(address) external view returns (uint); function transferFrom(address sender, address recipient, uint amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); event Transfer(address indexed from, address indexed to, uint value); event Approval(address indexed owner, address indexed spender, uint value); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IGauge { function notifyRewardAmount(address token, uint amount) external; function getReward(address account, address[] memory tokens) external; function getReward(address account) external; function claimFees() external returns (uint claimed0, uint claimed1); function rewardRate(address _pair) external view returns (uint); function balanceOf(address _account) external view returns (uint); function isForPair() external view returns (bool); function totalSupply() external view returns (uint); function earned(address token, address account) external view returns (uint); function stakeToken() external view returns (address); function setDistribution(address _distro) external; function addRewardToken(address _rewardToken) external; function updateRewardToken() external; function activateEmergencyMode() external; function stopEmergencyMode() external; function setInternalBribe(address intbribe) external; function setGaugeRewarder(address _gr) external; function setFeeVault(address _feeVault) external; function depositWithLock(address account, uint256 amount, uint256 _lockDuration) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IGaugeFactory { function createGauge(address, address, address, address, bool, address[] memory) external returns (address); function createGaugeV2(address _rewardToken,address _ve,address _token,address _distribution, address _internal_bribe, address _external_bribe, bool _isPair) external returns (address) ; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IHypervisor { function pool() external view returns(address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IMinter { function update_period() external returns (uint); function check() external view returns(bool); function period() external view returns(uint); function active_period() external view returns(uint); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IPair { function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1); function claimFees() external returns (uint, uint); function tokens() external view returns (address, address); function token0() external view returns (address); function token1() external view returns (address); function transferFrom(address src, address dst, uint amount) external returns (bool); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function burn(address to) external returns (uint amount0, uint amount1); function mint(address to) external returns (uint liquidity); function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast); function getAmountOut(uint, address) external view returns (uint); function name() external view returns(string memory); function symbol() external view returns(string memory); function totalSupply() external view returns (uint); function decimals() external view returns (uint8); function claimable0(address _user) external view returns (uint); function claimable1(address _user) external view returns (uint); function isStable() external view returns(bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IPairFactory { function allPairsLength() external view returns (uint); function isPair(address pair) external view returns (bool); function allPairs(uint index) external view returns (address); function pairCodeHash() external pure returns (bytes32); function getPair(address tokenA, address token, bool stable) external view returns (address); function createPair(address tokenA, address tokenB, bool stable) external returns (address pair); function MAX_REFERRAL_FEE() external view returns(uint); function dibs() external view returns(address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IPairInfo { function token0() external view returns(address); function reserve0() external view returns(uint); function decimals0() external view returns(uint); function token1() external view returns(address); function reserve1() external view returns(uint); function decimals1() external view returns(uint); function isPair(address _pair) external view returns(bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IPermissionsRegistry { function emergencyCouncil() external view returns(address); function lynexTeamMultisig() external view returns(address); function hasRole(bytes memory role, address caller) external view returns(bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library DelegateCallLib { /** * @dev Handles the result of a delegatecall and reverts with the revert reason if the call failed. * @param success The success flag returned by the delegatecall. * @param result The result bytes returned by the delegatecall. * @return The result bytes if the delegatecall was successful. */ function handleDelegateCallResult(bool success, bytes memory result) internal pure returns (bytes memory) { if (success) { return result; } else { // If the result length is less than 68, then the transaction failed silently (without a revert reason) if (result.length < 68) revert("delegatecall failed without a revert reason"); assembly { // Slice the sighash to remove the function selector result := add(result, 0x04) } // All that remains is the revert string revert(abi.decode(result, (string))); } } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.7.0; interface IDynamicTwapOracle { /** * @notice Get the address of the pool * @return The address of the pool */ function pool() external view returns (address); /** * @notice Get the address of the first token in the pool * @return The address of the first token */ function token0() external view returns (address); /** * @notice Get the address of the second token in the pool * @return The address of the second token */ function token1() external view returns (address); /** * @notice Estimate the output amount of a trade * @param tokenIn The address of the input token * @param amountIn The amount of the input token * @param secondsAgo The number of seconds ago to start the TWAP * @return amountOut The estimated output amount */ function estimateAmountOut( address tokenIn, uint128 amountIn, uint32 secondsAgo ) external view returns (uint amountOut); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.13; interface IOptionFeeDistributor { function distribute(address token, uint256 amount) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.13; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {IDynamicTwapOracle} from "./DynamicTwapOracle/IDynamicTwapOracle.sol"; import {IOptionFeeDistributor} from "./IOptionFeeDistributor.sol"; import {IPair} from "../interfaces/IPair.sol"; interface IOptionTokenV3 is IERC20, IAccessControl { function ADMIN_ROLE() external view returns (bytes32); function MINTER_ROLE() external view returns (bytes32); function PAUSER_ROLE() external view returns (bytes32); function paymentToken() external view returns (IERC20); function UNDERLYING_TOKEN() external view returns (IERC20); function voter() external view returns (address); function mint(address _to, uint256 _amount) external; function getDiscountedPrice(uint256 _amount) external view returns (uint256); function getDiscountedPrice(uint256 _amount, uint256 _discount) external view returns (uint256); function getLockDurationForLpDiscount(uint256 _amount) external view returns (uint256); function getPaymentTokenAmountForExerciseLp( uint256 _amount, uint256 _discount ) external view returns (uint256, uint256); function getSlopeInterceptForLpDiscount() external view returns (int256, int256); function getTimeWeightedAveragePrice(uint256 _amount) external view returns (uint256); function setTwapOracleAndPaymentToken(IDynamicTwapOracle _twapOracle, address _paymentToken) external; function setPairAndPaymentToken(IPair _pair, address _paymentToken) external; function setFeeDistributor(IOptionFeeDistributor _feeDistributor) external; function setDiscount(uint256 _discount) external; function setVeDiscount(uint256 _veDiscount) external; function setMinLPDiscount(uint256 _lpMinDiscount) external; function setMaxLPDiscount(uint256 _lpMaxDiscount) external; function setLockDurationForMaxLpDiscount(uint256 _duration) external; function setLockDurationForMinLpDiscount(uint256 _duration) external; function setTwapSeconds(uint32 _twapSeconds) external; function burn(uint256 _amount) external; function updateGauge() external; function setGauge(address _gauge) external; function setRouter(address _router) external; function unPause() external; function pause() external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IBribe { function deposit(uint amount, address account) external; function withdraw(uint amount, address account) external; function getRewardForOwner(uint tokenId, address[] memory tokens) external; function getRewardForAddress(address _owner, address[] memory tokens) external; function notifyRewardAmount(address token, uint amount) external; function addRewardToken(address _rewardsToken) external; function addRewardTokens(address[] memory _rewardsToken) external; function setVoter(address _Voter) external; function setMinter(address _Voter) external; function setOwner(address _Voter) external; function emergencyRecoverERC20(address tokenAddress, uint256 tokenAmount) external; function recoverERC20AndUpdateData(address tokenAddress, uint256 tokenAmount) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {IERC20} from "../interfaces/IERC20.sol"; import {IAlgebraFactory} from "@cryptoalgebra/v1-core/contracts/interfaces/IAlgebraFactory.sol"; import {IBribeFactory} from "../interfaces/IBribeFactory.sol"; import {IGaugeFactory} from "../interfaces/IGaugeFactory.sol"; import {IPermissionsRegistry} from "../interfaces/IPermissionsRegistry.sol"; import {IHypervisor} from "../interfaces/IHypervisor.sol"; import {IPairFactory} from "../interfaces/IPairFactory.sol"; import {IPairInfo} from "../interfaces/IPairInfo.sol"; import {VoterV5_Storage} from "./VoterV5_Storage.sol"; interface IVoterV5_GaugeLogic { function createGauge( address _pool, uint256 _gaugeType ) external returns (address _gauge, address _internal_bribe, address _external_bribe); } /// @title VoterV5_GaugeLogic /// @notice This contract contains the logic for creating gauges in the VoterV4 system. It is used to save contract /// size in VoterV4 by separating out expensive logic. /// @dev This contract MUST be called from VoterV4 through delegatecall(). contract VoterV5_GaugeLogic is IVoterV5_GaugeLogic, VoterV5_Storage { /// @notice create a gauge /// @param _pool LP address /// @param _gaugeType the type of the gauge you want to create /// @dev gaugeType = (Make sure to use the correct gaugeType or it will fail) /// - 0: (Options) Stable/Volatile pair /// - 1: (Options) Concentrated liquidity function createGauge( address _pool, uint256 _gaugeType ) external override returns (address _gauge, address _internal_bribe, address _external_bribe) { require(_gaugeType < _factories.length, "gaugetype"); require(gauges[_pool] == address(0x0), "!exists"); require(_pool.code.length > 0, "!contract"); bool isPair = false; address _factory = _factories[_gaugeType]; address _gaugeFactory = _gaugeFactories[_gaugeType]; require(_factory != address(0), "addr0"); require(_gaugeFactory != address(0), "addr0"); address tokenA = address(0); address tokenB = address(0); (tokenA) = IPairInfo(_pool).token0(); (tokenB) = IPairInfo(_pool).token1(); if (_gaugeType == 0) { isPair = IPairFactory(_factory).isPair(_pool); } if (_gaugeType == 1) { require(isWhitelistedPool[_pool], "Only whitelisted strategies"); address _pool_factory = IAlgebraFactory(_factory).poolByPair(tokenA, tokenB); address _pool_hyper = IHypervisor(_pool).pool(); require(_pool_hyper == _pool_factory, "wrong tokens"); isPair = true; } else { //update //isPair = false; } // gov can create for any pool, even non-lynex pairs if (!IPermissionsRegistry(permissionRegistry).hasRole("GOVERNANCE", msg.sender)) { require(isPair, "!_pool"); require(isWhitelisted[tokenA] && isWhitelisted[tokenB], "!whitelisted"); require(tokenA != address(0) && tokenB != address(0), "!pair.tokens"); } // create internal and external bribe address _owner = IPermissionsRegistry(permissionRegistry).lynexTeamMultisig(); string memory _type = string.concat("Lynex LP Fees: ", IERC20(_pool).symbol()); _internal_bribe = IBribeFactory(bribefactory).createBribe(_owner, tokenA, tokenB, _type); _type = string.concat("Lynex Bribes: ", IERC20(_pool).symbol()); _external_bribe = IBribeFactory(bribefactory).createBribe(_owner, tokenA, tokenB, _type); // creating bribe from at least four possible gauge types _gauge = IGaugeFactory(_gaugeFactory).createGaugeV2( oLynx != address(0) ? oLynx : base, _ve, _pool, address(this), _internal_bribe, _external_bribe, isPair ); // approve spending for $lynx, this is set back to zero if gauge is killed if (oLynx != address(0)) IERC20(oLynx).approve(_gauge, type(uint256).max); else IERC20(base).approve(_gauge, type(uint256).max); // save data internal_bribes[_gauge] = _internal_bribe; external_bribes[_gauge] = _external_bribe; gauges[_pool] = _gauge; poolForGauge[_gauge] = _pool; isGauge[_gauge] = true; isAlive[_gauge] = true; pools.push(_pool); // update index supplyIndex[_gauge] = index; // new gauges are set to the default global state return (_gauge, _internal_bribe, _external_bribe); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {IVoterV5_GaugeLogic} from "./VoterV5_GaugeLogic.sol"; /// @title VoterV4_Storage /// @notice This contract contains the storage variables for VoterV4. /// @dev This contract is used to ensure both VoterV4 and VoterV4_GaugeLogic have access to the same storage variables /// in the correct slots. They MUST both extend this. contract VoterV5_Storage { bool internal initflag; address public _ve; // lynx ve token that governs these contracts address[] internal _factories; // Array with all the pair factories address public base; // $lynx token address public oLynx; // $lynx token address[] internal _gaugeFactories; // array with all the gauge factories address public bribefactory; // bribe factory (internal and external) address public minter; // minter mints $lynx each epoch address public permissionRegistry; // registry to check accesses address[] public pools; // all pools viable for incentives uint256 internal index; // gauge index uint256 internal DURATION; // rewards are released over 1 epoch uint256 public VOTE_DELAY; // delay between votes in seconds uint256 public MAX_VOTE_DELAY; // Max vote delay allowed mapping(address => uint256) internal supplyIndex; // gauge => index mapping(address => uint256) public claimable; // gauge => claimable $lynx mapping(address => address) public gauges; // pool => gauge mapping(address => uint256) public gaugesDistributionTimestamp; // gauge => last Distribution Time mapping(address => address) public poolForGauge; // gauge => pool mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees) mapping(address => address) public external_bribes; // gauge => external bribe (real bribes) mapping(address => mapping(address => uint256)) public votes; // nft => pool => votes mapping(address => address[]) public poolVote; // nft => pools mapping(uint256 => mapping(address => uint256)) internal weightsPerEpoch; // timestamp => pool => weights mapping(uint256 => uint256) internal totalWeightsPerEpoch; // timestamp => total weights mapping(address => uint256) public lastVoted; // nft => timestamp of last vote mapping(address => bool) public isGauge; // gauge => boolean [is a gauge?] mapping(address => bool) public isWhitelisted; // token => boolean [is an allowed token?] mapping(address => bool) public isWhitelistedPool; // token => boolean [is an allowed token?] mapping(address => bool) public isAlive; // gauge => boolean [is the gauge alive?] mapping(address => uint8) public isFactory; // factory => boolean [the pair factory exists?] mapping(address => bool) public isGaugeFactory; // g.factory=> boolean [the gauge factory exists?] mapping(address => bool) public isGaugeDepositor; // g.factory=> boolean [the gauge factory exists?] IVoterV5_GaugeLogic public gaugeLogic; // gauge logic contract // Reserved space for future state variables uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {IERC5805} from "@openzeppelin/contracts/interfaces/IERC5805.sol"; import {Checkpoints} from "../libraries/Checkpoints.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC721Enumerable} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol"; interface IVotingEscrowV2 is IERC5805, IERC721Enumerable { struct LockDetails { uint256 amount; /// @dev amount of tokens locked uint256 startTime; /// @dev when locking started uint256 endTime; /// @dev when locking ends bool isPermanent; /// @dev if its a permanent lock } /// ----------------------------------------------------------------------- /// Events /// ----------------------------------------------------------------------- event SupplyUpdated(uint256 oldSupply, uint256 newSupply); /// @notice Lock events event LockCreated(uint256 indexed tokenId, address indexed to, uint256 value, uint256 unlockTime, bool isPermanent); event LockUpdated(uint256 indexed tokenId, uint256 value, uint256 unlockTime, bool isPermanent); event LockMerged( uint256 indexed fromTokenId, uint256 indexed toTokenId, uint256 totalValue, uint256 unlockTime, bool isPermanent ); event LockSplit(uint256[] splitWeights, uint256 indexed _tokenId); event LockDurationExtended(uint256 indexed tokenId, uint256 newUnlockTime, bool isPermanent); event LockAmountIncreased(uint256 indexed tokenId, uint256 value); event UnlockPermanent(uint256 indexed tokenId, address indexed sender, uint256 unlockTime); /// @notice Delegate events event LockDelegateChanged( uint256 indexed tokenId, address indexed delegator, address fromDelegate, address indexed toDelegate ); /// ----------------------------------------------------------------------- /// Errors /// ----------------------------------------------------------------------- error AlreadyVoted(); error InvalidNonce(); error InvalidDelegatee(); error InvalidSignature(); error InvalidSignatureS(); error LockDurationNotInFuture(); error LockDurationTooLong(); error LockExpired(); error LockNotExpired(); error NoLockFound(); error NotPermanentLock(); error PermanentLock(); error SameNFT(); error SignatureExpired(); error ZeroAmount(); function supply() external view returns (uint); function token() external view returns (IERC20); function balanceOfNFT(uint256 _tokenId) external view returns (uint256); function balanceOfNFTAt(uint256 _tokenId, uint256 _timestamp) external view returns (uint256); function delegates(uint256 tokenId, uint48 timestamp) external view returns (address); function lockDetails(uint256 tokenId) external view returns (LockDetails calldata); function isApprovedOrOwner(address user, uint tokenId) external view returns (bool); function getPastEscrowPoint( uint256 _tokenId, uint256 _timePoint ) external view returns (Checkpoints.Point memory, uint48); function getFirstEscrowPoint(uint256 _tokenId) external view returns (Checkpoints.Point memory, uint48); function checkpoint() external; function increaseAmount(uint256 _tokenId, uint256 _value) external; function createLockFor(uint256 _value, uint256 _lockDuration, address _to, bool _permanent) external returns (uint256); function decimals() external view returns(uint8); }
// SPDX-License-Identifier: MIT // This file was derived from OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/Checkpoints.sol) pragma solidity 0.8.13; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; /** * @dev This library defines the `Trace*` struct, for checkpointing values as they change at different points in * time, and later looking up past values by block number. See {Votes} as an example. * * To create a history of checkpoints define a variable type `Checkpoints.Trace*` in your contract, and store a new * checkpoint for the current transaction block using the {push} function. */ library Checkpoints { struct Trace { Checkpoint[] _checkpoints; } /** * @dev Struct to keep track of the voting power over time. */ struct Point { /// @dev The voting power at a specific time /// - MUST never be negative. int128 bias; /// @dev The rate at which the voting power decreases over time. int128 slope; /// @dev The value of tokens which do not decrease over time, representing permanent voting power /// - MUST never be negative. int128 permanent; } struct Checkpoint { uint48 _key; Point _value; } /** * @dev A value was attempted to be inserted on a past checkpoint. */ error CheckpointUnorderedInsertions(); /** * @dev Pushes a (`key`, `value`) pair into a Trace so that it is stored as the checkpoint. * * Returns previous value and new value. * * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint48).max` key set will disable the * library. */ function push(Trace storage self, uint48 key, Point memory value) internal returns (Point memory, Point memory) { return _insert(self._checkpoints, key, value); } /** * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if * there is none. */ function lowerLookup(Trace storage self, uint48 key) internal view returns (Point memory) { uint256 len = self._checkpoints.length; uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); return pos == len ? blankPoint() : _unsafeAccess(self._checkpoints, pos)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. */ function upperLookup( Trace storage self, uint48 key ) internal view returns (bool exists, uint48 _key, Point memory _value) { uint256 len = self._checkpoints.length; uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); exists = pos != 0; _value = exists ? _unsafeAccess(self._checkpoints, pos - 1)._value : blankPoint(); _key = exists ? _unsafeAccess(self._checkpoints, pos - 1)._key : 0; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. * * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high * keys). */ function upperLookupRecent( Trace storage self, uint48 key ) internal view returns (bool exists, uint48 _key, Point memory _value) { uint256 len = self._checkpoints.length; uint256 low = 0; uint256 high = len; if (len > 5) { uint256 mid = len - Math.sqrt(len); if (key < _unsafeAccess(self._checkpoints, mid)._key) { high = mid; } else { low = mid + 1; } } uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); exists = pos != 0; _value = exists ? _unsafeAccess(self._checkpoints, pos - 1)._value : blankPoint(); _key = exists ? _unsafeAccess(self._checkpoints, pos - 1)._key : 0; } /** * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. */ function latest(Trace storage self) internal view returns (Point memory) { uint256 pos = self._checkpoints.length; return pos == 0 ? blankPoint() : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value * in the most recent checkpoint. */ function latestCheckpoint( Trace storage self ) internal view returns (bool exists, uint48 _key, Point memory _value) { uint256 pos = self._checkpoints.length; if (pos == 0) { return (false, 0, blankPoint()); } else { Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, pos - 1); return (true, ckpt._key, ckpt._value); } } /** * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value * in the most recent checkpoint. */ function firstCheckpoint( Trace storage self ) internal view returns (bool exists, uint48 _key, Point memory _value) { uint256 pos = self._checkpoints.length; if (pos == 0) { return (false, 0, blankPoint()); } else { Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, 0); return (true, ckpt._key, ckpt._value); } } /** * @dev Returns the number of checkpoint. */ function length(Trace storage self) internal view returns (uint256) { return self._checkpoints.length; } /** * @dev Returns checkpoint at given position. */ function at(Trace storage self, uint48 pos) internal view returns (Checkpoint memory) { return self._checkpoints[pos]; } /** * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, * or by updating the last one. */ function _insert( Checkpoint[] storage self, uint48 key, Point memory value ) private returns (Point memory, Point memory) { uint256 pos = self.length; if (pos > 0) { // Copying to memory is important here. Checkpoint memory last = _unsafeAccess(self, pos - 1); // Checkpoint keys must be non-decreasing. if (last._key > key) { revert CheckpointUnorderedInsertions(); } // Update or push new checkpoint if (last._key == key) { _unsafeAccess(self, pos - 1)._value = value; } else { self.push(Checkpoint({_key: key, _value: value})); } return (last._value, value); } else { self.push(Checkpoint({_key: key, _value: value})); return (blankPoint(), value); } } /** * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive * `high`. * * WARNING: `high` should not be greater than the array's length. */ function _upperBinaryLookup( Checkpoint[] storage self, uint48 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key > key) { high = mid; } else { low = mid + 1; } } return high; } /** * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or * `high` if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and * exclusive `high`. * * WARNING: `high` should not be greater than the array's length. */ function _lowerBinaryLookup( Checkpoint[] storage self, uint48 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key < key) { low = mid + 1; } else { high = mid; } } return high; } /** * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. */ function _unsafeAccess(Checkpoint[] storage self, uint256 pos) private view returns (Checkpoint storage result) { return self[pos]; } /** * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. */ function _realUnsafeAccess( Checkpoint[] storage self, uint256 pos ) private pure returns (Checkpoint storage result) { assembly { mstore(0, self.slot) result.slot := add(keccak256(0, 0x20), pos) } } function blankPoint() internal pure returns (Point memory) { return Point({bias: 0, slope: 0, permanent: 0}); } struct TraceAddress { CheckpointAddress[] _checkpoints; } struct CheckpointAddress { uint48 _key; address _value; } /** * @dev Pushes a (`key`, `value`) pair into a TraceAddress so that it is stored as the checkpoint. * * Returns previous value and new value. * * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint48).max` key set will disable the * library. */ function push(TraceAddress storage self, uint48 key, address value) internal returns (address, address) { return _insert(self._checkpoints, key, value); } /** * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if * there is none. */ function lowerLookup(TraceAddress storage self, uint48 key) internal view returns (address) { uint256 len = self._checkpoints.length; uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); return pos == len ? address(0) : _unsafeAccess(self._checkpoints, pos)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. */ function upperLookup(TraceAddress storage self, uint48 key) internal view returns (address) { uint256 len = self._checkpoints.length; uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); return pos == 0 ? address(0) : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. * * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high * keys). */ function upperLookupRecent(TraceAddress storage self, uint48 key) internal view returns (address) { uint256 len = self._checkpoints.length; uint256 low = 0; uint256 high = len; if (len > 5) { uint256 mid = len - Math.sqrt(len); if (key < _unsafeAccess(self._checkpoints, mid)._key) { high = mid; } else { low = mid + 1; } } uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); return pos == 0 ? address(0) : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. */ function latest(TraceAddress storage self) internal view returns (address) { uint256 pos = self._checkpoints.length; return pos == 0 ? address(0) : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value * in the most recent checkpoint. */ function latestCheckpoint( TraceAddress storage self ) internal view returns (bool exists, uint48 _key, address _value) { uint256 pos = self._checkpoints.length; if (pos == 0) { return (false, 0, address(0)); } else { CheckpointAddress memory ckpt = _unsafeAccess(self._checkpoints, pos - 1); return (true, ckpt._key, ckpt._value); } } /** * @dev Returns the number of checkpoint. */ function length(TraceAddress storage self) internal view returns (uint256) { return self._checkpoints.length; } /** * @dev Returns checkpoint at given position. */ function at(TraceAddress storage self, uint48 pos) internal view returns (CheckpointAddress memory) { return self._checkpoints[pos]; } /** * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, * or by updating the last one. */ function _insert(CheckpointAddress[] storage self, uint48 key, address value) private returns (address, address) { uint256 pos = self.length; if (pos > 0) { // Copying to memory is important here. CheckpointAddress memory last = _unsafeAccess(self, pos - 1); // Checkpoint keys must be non-decreasing. if (last._key > key) { revert CheckpointUnorderedInsertions(); } // Update or push new checkpoint if (last._key == key) { _unsafeAccess(self, pos - 1)._value = value; } else { self.push(CheckpointAddress({_key: key, _value: value})); } return (last._value, value); } else { self.push(CheckpointAddress({_key: key, _value: value})); return (address(0), value); } } /** * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive * `high`. * * WARNING: `high` should not be greater than the array's length. */ function _upperBinaryLookup( CheckpointAddress[] storage self, uint48 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key > key) { high = mid; } else { low = mid + 1; } } return high; } /** * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or * `high` if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and * exclusive `high`. * * WARNING: `high` should not be greater than the array's length. */ function _lowerBinaryLookup( CheckpointAddress[] storage self, uint48 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key < key) { low = mid + 1; } else { high = mid; } } return high; } /** * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. */ function _unsafeAccess( CheckpointAddress[] storage self, uint256 pos ) private pure returns (CheckpointAddress storage result) { assembly { mstore(0, self.slot) result.slot := add(keccak256(0, 0x20), pos) } } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InsufficientVotingPower","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"Abstained","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pairfactory","type":"address"},{"indexed":true,"internalType":"address","name":"gaugefactory","type":"address"}],"name":"AddFactories","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Attach","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"blacklister","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"Blacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Detach","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":"DistributeReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"address","name":"internal_bribe","type":"address"},{"indexed":true,"internalType":"address","name":"external_bribe","type":"address"},{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"GaugeCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeKilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeRevived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","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":"NotifyReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"latest","type":"address"}],"name":"SetBribeFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isInternal","type":"bool"},{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"latest","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"SetBribeFor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"SetDepositor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"latest","type":"address"}],"name":"SetGaugeFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"latest","type":"address"}],"name":"SetMinter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"latest","type":"address"}],"name":"SetOptions","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"latest","type":"address"}],"name":"SetPairFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"latest","type":"address"}],"name":"SetPermissionRegistry","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"old","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"latest","type":"uint256"}],"name":"SetVoteDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"Voted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"whitelister","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"Whitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"whitelister","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"WhitelistedPool","type":"event"},{"inputs":[],"name":"MAX_VOTE_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOTE_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_epochTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address","name":"_permissionsRegistry","type":"address"},{"internalType":"address","name":"_minter","type":"address"},{"internalType":"address","name":"_oLynx","type":"address"}],"name":"_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pairFactory","type":"address"},{"internalType":"address","name":"_gaugeFactory","type":"address"}],"name":"addFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"base","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_token","type":"address[]"}],"name":"blacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bribefactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_bribes","type":"address[]"},{"internalType":"address[][]","name":"_tokens","type":"address[][]"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"claimBribes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_bribes","type":"address[]"},{"internalType":"address[][]","name":"_tokens","type":"address[][]"}],"name":"claimBribes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_fees","type":"address[]"},{"internalType":"address[][]","name":"_tokens","type":"address[][]"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_bribes","type":"address[]"},{"internalType":"address[][]","name":"_tokens","type":"address[][]"}],"name":"claimFees","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":"_pool","type":"address"},{"internalType":"uint256","name":"_gaugeType","type":"uint256"}],"name":"createGauge","outputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_internal_bribe","type":"address"},{"internalType":"address","name":"_external_bribe","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pool","type":"address[]"},{"internalType":"uint256[]","name":"_gaugeTypes","type":"uint256[]"}],"name":"createGauges","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauges","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":[],"name":"distributeAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauges","type":"address[]"}],"name":"distributeFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"external_bribes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factories","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gaugeFactories","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gaugeFactoriesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gaugeLogic","outputs":[{"internalType":"contract IVoterV5_GaugeLogic","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":[{"internalType":"address","name":"","type":"address"}],"name":"gaugesDistributionTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"__ve","type":"address"},{"internalType":"address","name":"_pairFactory","type":"address"},{"internalType":"address","name":"_gaugeFactory","type":"address"},{"internalType":"address","name":"_bribes","type":"address"},{"internalType":"address","name":"_gaugeLogic","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"internal_bribes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"isFactory","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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":"","type":"address"}],"name":"isGaugeDepositor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGaugeFactory","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isWhitelistedPool","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":"oLynx","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permissionRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolForGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolVote","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"poolVoteLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pools","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"finish","type":"uint256"},{"internalType":"address","name":"_oldOtoken","type":"address"}],"name":"refreshApprovals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pos","type":"uint256"}],"name":"removeFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pairFactory","type":"address"},{"internalType":"address","name":"_gaugeFactory","type":"address"},{"internalType":"uint256","name":"_pos","type":"uint256"}],"name":"replaceFactory","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":[{"internalType":"address","name":"_bribeFactory","type":"address"}],"name":"setBribeFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_external","type":"address"}],"name":"setExternalBribeFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setGaugeDepositor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_internal","type":"address"}],"name":"setInternalBribeFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"setMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_internal","type":"address"},{"internalType":"address","name":"_external","type":"address"}],"name":"setNewBribes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oToken","type":"address"}],"name":"setOptionsToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_permissionRegistry","type":"address"}],"name":"setPermissionsRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setVoteDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_time","type":"uint256"}],"name":"totalWeightAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_poolVote","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":"_pool","type":"address"}],"name":"weights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_time","type":"uint256"}],"name":"weightsAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_token","type":"address[]"}],"name":"whitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pool","type":"address[]"}],"name":"whitelistPool","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50615d5f80620000216000396000f3fe608060405234801561001057600080fd5b50600436106104c35760003560e01c806396c82e5711610286578063c48f5af41161016b578063dcd9e47a116100e3578063f8803bb611610097578063fca3b5aa1161007c578063fca3b5aa14610b50578063fe5b38e414610b63578063ffe5195b14610b6b57600080fd5b8063f8803bb614610b35578063f9f031df14610b3d57600080fd5b8063e6da0457116100c8578063e6da045714610ac9578063eae40f2614610ae9578063f2312ab014610b1257600080fd5b8063dcd9e47a14610a79578063df7ae62e14610ab657600080fd5b8063cdcaa13b1161013a578063d4857bfd1161011f578063d4857bfd14610a4b578063d826f88f14610a5e578063daa168bd14610a6657600080fd5b8063cdcaa13b14610a25578063d1a8e08c14610a3857600080fd5b8063c48f5af4146109c1578063c527ee1f146109d4578063c991866d146109e7578063cad1b906146109fa57600080fd5b8063ae21c4cb116101fe578063b55a5c1c116101cd578063b9a09fd5116101b2578063b9a09fd514610972578063bd8aa7801461099b578063c2b79e98146109ae57600080fd5b8063b55a5c1c1461094c578063b7c89f9c1461095f57600080fd5b8063ae21c4cb146108f5578063ae9c9e3f1461091e578063b0f5027814610931578063b52a31511461094457600080fd5b80639f06247b11610255578063a9b5aa7e1161023a578063a9b5aa7e146108ac578063aa79979b146108bf578063ac4afa38146108e257600080fd5b80639f06247b14610886578063a7cac8461461089957600080fd5b806396c82e5714610838578063992a7933146108405780639a61df89146108535780639a83ed3b1461087357600080fd5b80635001f3b5116103ac5780636c4f2e38116103245780638657c745116102f35780638daeaa5a116102d85780638daeaa5a146107e25780638dd598fb1461080b57806390e934161461082357600080fd5b80638657c745146107bc5780638b6fc247146107cf57600080fd5b80636c4f2e381461077a5780636f816a20146107835780637625391a146107965780637715ee75146107a957600080fd5b80636138889b1161037b5780636566afad116103605780636566afad14610731578063657021fb14610744578063666256aa1461076757600080fd5b80636138889b1461070b578063636056f21461071e57600080fd5b80635001f3b5146106a257806353be568d146106b557806355f168d5146106d5578063577387b5146106f857600080fd5b806327e5c8231161043f5780633c6b16ab1161040e578063436596c4116103f3578063436596c414610670578063470f4985146106785780634d68ce441461068057600080fd5b80633c6b16ab1461063d578063402914f51461065057600080fd5b806327e5c823146105e157806333832a6a146105f457806338752a9d146106075780633af32abf1461061a57600080fd5b80631459457a11610496578063181783581161047b57806318178358146105b15780631f7b6d32146105b95780631f850716146105cb57600080fd5b80631459457a1461056b5780631703e5f91461057e57600080fd5b8063041f173f146104c857806306d6a1b2146104dd57806307546172146105235780630f04ba6714610536575b600080fd5b6104db6104d6366004615341565b610b74565b005b6105066104eb366004615376565b6011602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600654610506906001600160a01b031681565b610559610544366004615376565b601d6020526000908152604090205460ff1681565b60405160ff909116815260200161051a565b6104db61057936600461539a565b610bc0565b6105a161058c366004615376565b601c6020526000908152604090205460ff1681565b604051901515815260200161051a565b6104db610eb5565b6008545b60405190815260200161051a565b60005461010090046001600160a01b0316610506565b6104db6105ef36600461540b565b611062565b6104db610602366004615376565b611342565b600554610506906001600160a01b031681565b6105a1610628366004615376565b601a6020526000908152604090205460ff1681565b6104db61064b36600461544c565b61142a565b6105bd61065e366004615376565b600e6020526000908152604090205481565b6104db611548565b6001546105bd565b61069361068e366004615465565b611641565b60405161051a93929190615564565b600254610506906001600160a01b031681565b6105bd6106c336600461544c565b60009081526017602052604090205490565b6105a16106e3366004615376565b601b6020526000908152604090205460ff1681565b6104db61070636600461544c565b6118a2565b6104db610719366004615341565b611af5565b6105bd61072c3660046155a7565b611bc5565b6104db61073f3660046155d3565b611bef565b6105a1610752366004615376565b601e6020526000908152604090205460ff1681565b6104db61077536600461568c565b611e7a565b6105bd600c5481565b6104db610791366004615745565b612045565b6104db6107a43660046157b1565b612140565b6104db6107b736600461568c565b612203565b600354610506906001600160a01b031681565b6104db6107dd36600461544c565b6123c8565b6105bd6107f0366004615376565b6001600160a01b031660009081526015602052604090205490565b6000546105069061010090046001600160a01b031681565b61082b6124b4565b60405161051a91906157d3565b6105bd612516565b6104db61084e366004615376565b612536565b6105bd610861366004615376565b60186020526000908152604090205481565b6104db6108813660046157e6565b6127ad565b6104db610894366004615376565b612834565b6105bd6108a7366004615376565b612a53565b6104db6108ba366004615376565b612a8a565b6105a16108cd366004615376565b60196020526000908152604090205460ff1681565b6105066108f036600461544c565b612b72565b610506610903366004615376565b6013602052600090815260409020546001600160a01b031681565b602054610506906001600160a01b031681565b6104db61093f36600461581f565b612b9c565b6004546105bd565b600754610506906001600160a01b031681565b6104db61096d3660046155d3565b612c4f565b610506610980366004615376565b600f602052600090815260409020546001600160a01b031681565b6104db6109a9366004615341565b612cb2565b6104db6109bc36600461585f565b612cfa565b6105066109cf3660046155a7565b612dfc565b6104db6109e2366004615341565b612e34565b6104db6109f536600461585f565b612f58565b6105bd610a083660046155d3565b601460209081526000928352604080842090915290825290205481565b6104db610a333660046158d1565b61305a565b6104db610a46366004615376565b6130c1565b6104db610a59366004615341565b6132ce565b6104db613316565b6104db610a743660046155d3565b613368565b610a8c610a873660046155a7565b6133cb565b604080516001600160a01b039485168152928416602084015292169181019190915260600161051a565b6104db610ac43660046158ff565b6133f3565b6105bd610ad7366004615376565b60106020526000908152604090205481565b610506610af7366004615376565b6012602052600090815260409020546001600160a01b031681565b6105a1610b20366004615376565b601f6020526000908152604090205460ff1681565b6105bd6135c0565b6104db610b4b366004615341565b61364c565b6104db610b5e366004615376565b6136fb565b61082b6137e3565b6105bd600b5481565b610b7c613843565b60005b8151811015610bbc57610baa828281518110610b9d57610b9d615974565b60200260200101516138d0565b80610bb4816159a0565b915050610b7f565b5050565b605354610100900460ff1615808015610be05750605354600160ff909116105b80610bfa5750303b158015610bfa575060535460ff166001145b610c715760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6053805460ff191660011790558015610c94576053805461ff0019166101001790555b610c9c613982565b85600060016101000a8154816001600160a01b0302191690836001600160a01b03160217905550856001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2591906159b9565b600280546001600160a01b039283166001600160a01b031991821617909155600180548082019091557fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601805492881692909116821790556000908152601d60205260408120805460ff1691610d9a836159d6565b82546101009290920a60ff818102199093169190921691909102179055506004805460018181019092557f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03199081166001600160a01b038881169182179093556000908152601e602090815260408220805460ff199081169096179055600580548416898616179055600680543390851681179091556007805485169091179055600b82905562093a80600a819055600c55815490941690558254169084161790558015610ead576053805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610ebd6139f5565b33610ec781613a4e565b6001600160a01b038116600090815260156020908152604080832080548251818502810185019093528083529192909190830182828015610f3157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f13575b5050505050905060008151905060008167ffffffffffffffff811115610f5957610f5961524d565b604051908082528060200260200182016040528015610f82578160200160208202803683370190505b50905060005b82811015611017576001600160a01b03851660009081526014602052604081208551909190869084908110610fbf57610fbf615974565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610ffa57610ffa615974565b60209081029190910101528061100f816159a0565b915050610f88565b50611023848483613ad4565b61102b6135c0565b6110369060016159f5565b6001600160a01b03909416600090815260186020526040902093909355506110609150613fbb9050565b565b61106a613fc2565b6001600160a01b0383166110a85760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6001600160a01b0382166110e65760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6001600160a01b0382166000908152601e602052604090205460ff166111375760405162461bcd60e51b81526020600482015260066024820152650859d19858dd60d21b6044820152606401610c68565b60006001828154811061114c5761114c615974565b6000918252602082200154600480546001600160a01b039092169350908490811061117957611179615974565b60009182526020808320909101546001600160a01b038581168452601d90925260408320805492909116935060ff909116916111b483615a0d565b825460ff9182166101009390930a9283029190920219909116179055506001600160a01b0381166000908152601e60205260409020805460ff19169055600180548691908590811061120857611208615974565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550836004848154811061124a5761124a615974565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790559187168152601d90915260408120805460ff169161128f836159d6565b825460ff9182166101009390930a9283029190920219909116179055506001600160a01b038085166000818152601e6020526040808220805460ff191660011790555191928416917fa1bb19b5d754d8c6479f7761797294f0786b22f6fe2fd51b0b81e56f4136cd939190a3846001600160a01b0316826001600160a01b03167fa01124614129d8b1fb8a4fd2f718422cb3d34c92ff59026e1fb316871a2b9c3960405160405180910390a35050505050565b61134a613fc2565b6000816001600160a01b03163b116113905760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b0381166113ce5760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6007546040516001600160a01b038084169216907f19fff1a4baaea69caec27e064bdfc0cb61d642370694fffdc0d38a568eb89b7390600090a3600780546001600160a01b0319166001600160a01b0392909216919091179055565b6006546001600160a01b031633146114845760405162461bcd60e51b815260206004820152600760248201527f216d696e746572000000000000000000000000000000000000000000000000006044820152606401610c68565b60025461149c906001600160a01b031633308461404f565b60006114b762093a806114ad6135c0565b6106c39190615a2a565b9050600081156114e157816114d484670de0b6b3a7640000615a41565b6114de9190615a60565b90505b80156114ff5780600960008282546114f991906159f5565b90915550505b6002546040518481526001600160a01b039091169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a3505050565b6115506139f5565b600660009054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af11580156115a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c99190615a82565b506008546000905b8082101561163557611623600f6000600885815481106115f3576115f3615974565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416614100565b8161162d816159a0565b9250506115d1565b50506110606001605455565b606080606061164e6139f5565b835185511461169f5760405162461bcd60e51b815260206004820152600c60248201527f6c656e206d69736d6174636800000000000000000000000000000000000000006044820152606401610c68565b600a855111156116f15760405162461bcd60e51b815260206004820152600660248201527f6d617820313000000000000000000000000000000000000000000000000000006044820152606401610c68565b6000855167ffffffffffffffff81111561170d5761170d61524d565b604051908082528060200260200182016040528015611736578160200160208202803683370190505b5090506000865167ffffffffffffffff8111156117555761175561524d565b60405190808252806020026020018201604052801561177e578160200160208202803683370190505b5090506000875167ffffffffffffffff81111561179d5761179d61524d565b6040519080825280602002602001820160405280156117c6578160200160208202803683370190505b50905060005b8851811015611889576118118982815181106117ea576117ea615974565b602002602001015189838151811061180457611804615974565b6020026020010151614341565b86848151811061182357611823615974565b6020026020010186858151811061183c5761183c615974565b6020026020010186868151811061185557611855615974565b6001600160a01b03948516602091820292909201015292821690925291909116905280611881816159a0565b9150506117cc565b509194509250905061189b6001605455565b9250925092565b6118aa613fc2565b6000600182815481106118bf576118bf615974565b6000918252602082200154600480546001600160a01b03909216935090849081106118ec576118ec615974565b60009182526020808320909101546001600160a01b038581168452601d9092526040909220549116915060ff166119655760405162461bcd60e51b815260206004820152600560248201527f21666163740000000000000000000000000000000000000000000000000000006044820152606401610c68565b6001600160a01b0381166000908152601e602052604090205460ff166119b65760405162461bcd60e51b81526020600482015260066024820152650859d19858dd60d21b6044820152606401610c68565b6000600184815481106119cb576119cb615974565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600060048481548110611a0e57611a0e615974565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790559184168152601d90915260408120805460ff1691611a5383615a0d565b825460ff9182166101009390930a9283029190920219909116179055506001600160a01b0381166000818152601e6020526040808220805460ff19169055519091907fa1bb19b5d754d8c6479f7761797294f0786b22f6fe2fd51b0b81e56f4136cd93908390a36040516000906001600160a01b038416907fa01124614129d8b1fb8a4fd2f718422cb3d34c92ff59026e1fb316871a2b9c39908390a3505050565b611afd6139f5565b600660009054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611b52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b769190615a82565b5060005b8151811015611bb757611ba5828281518110611b9857611b98615974565b6020026020010151614100565b80611baf816159a0565b915050611b7a565b50611bc26001605455565b50565b60008181526016602090815260408083206001600160a01b03861684529091529020545b92915050565b611bf7613fc2565b6001600160a01b038216611c355760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6001600160a01b038116611c735760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6001600160a01b0381166000908152601e602052604090205460ff1615611cdc5760405162461bcd60e51b815260206004820152600560248201527f67466163740000000000000000000000000000000000000000000000000000006044820152606401610c68565b6000826001600160a01b03163b11611d225760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6000816001600160a01b03163b11611d685760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001805480820182557fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03199081166001600160a01b038681169182179093556004805494850190557f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b90930180549091169184169190911790556000908152601d60205260408120805460ff1691611e0a836159d6565b825460ff9182166101009390930a9283029190920219909116179055506001600160a01b038082166000818152601e6020526040808220805460ff191660011790555191928516917f8bad2b894999c82738dc185dbb158d846fce35d7edbcc0661b1b97d9aacba69d9190a35050565b60005460405163430c208160e01b8152336004820152602481018390526101009091046001600160a01b03169063430c208190604401602060405180830381865afa158015611ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef19190615a9b565b611f3d5760405162461bcd60e51b815260206004820152600f60248201527f21617070726f7665642f4f776e657200000000000000000000000000000000006044820152606401610c68565b8151835114611f8e5760405162461bcd60e51b815260206004820152601460248201527f4665652f546f6b656e73206c656e67746820213d0000000000000000000000006044820152606401610c68565b60005b835181101561203f57838181518110611fac57611fac615974565b60200260200101516001600160a01b031663a7852afa83858481518110611fd557611fd5615974565b60200260200101516040518363ffffffff1660e01b8152600401611ffa929190615ab8565b600060405180830381600087803b15801561201457600080fd5b505af1158015612028573d6000803e3d6000fd5b505050508080612037906159a0565b915050611f91565b50505050565b61204d6139f5565b61205633613a4e565b8281146120a55760405162461bcd60e51b815260206004820152601660248201527f506f6f6c2f57656967687473206c656e67746820213d000000000000000000006044820152606401610c68565b6121133385858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250613ad492505050565b61211b6135c0565b6121269060016159f5565b3360009081526018602052604090205561203f6001605455565b6121486139f5565b600660009054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af115801561219d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c19190615a82565b50815b818110156121f8576121e6600f6000600884815481106115f3576115f3615974565b806121f0816159a0565b9150506121c4565b50610bbc6001605455565b60005460405163430c208160e01b8152336004820152602481018390526101009091046001600160a01b03169063430c208190604401602060405180830381865afa158015612256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227a9190615a9b565b6122c65760405162461bcd60e51b815260206004820152600f60248201527f21617070726f7665642f4f776e657200000000000000000000000000000000006044820152606401610c68565b81518351146123175760405162461bcd60e51b815260206004820152601760248201527f4272696265732f546f6b656e73206c656e67746820213d0000000000000000006044820152606401610c68565b60005b835181101561203f5783818151811061233557612335615974565b60200260200101516001600160a01b031663a7852afa8385848151811061235e5761235e615974565b60200260200101516040518363ffffffff1660e01b8152600401612383929190615ab8565b600060405180830381600087803b15801561239d57600080fd5b505af11580156123b1573d6000803e3d6000fd5b5050505080806123c0906159a0565b91505061231a565b6123d0613fc2565b600b5481036124215760405162461bcd60e51b815260206004820152600b60248201527f616c7265616479207365740000000000000000000000000000000000000000006044820152606401610c68565b600c548111156124735760405162461bcd60e51b815260206004820152600960248201527f6d61782064656c617900000000000000000000000000000000000000000000006044820152606401610c68565b600b5460408051918252602082018390527f17fb843f25faf2431510bc4a71e4898ccc1a28a3e985450e509670d14be2eaa1910160405180910390a1600b55565b6060600480548060200260200160405190810160405280929190818152602001828054801561250c57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116124ee575b5050505050905090565b6000806125216135c0565b60009081526017602052604090205492915050565b61253e613843565b6001600160a01b0381166000908152601c602052604090205460ff166125a65760405162461bcd60e51b815260206004820152600660248201527f6b696c6c656400000000000000000000000000000000000000000000000000006044820152606401610c68565b60025460405163095ea7b360e01b81526001600160a01b038381166004830152600060248301529091169063095ea7b3906044016020604051808303816000875af11580156125f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261d9190615a9b565b5060035460405163095ea7b360e01b81526001600160a01b038381166004830152600060248301529091169063095ea7b3906044016020604051808303816000875af1158015612671573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126959190615a9b565b506001600160a01b0381166000908152600e602052604090205480156126ec576006546002546126d2916001600160a01b0391821691168361449c565b6001600160a01b0382166000908152600e60205260408120555b6001600160a01b0382166000908152601c60209081526040808320805460ff19169055600e90915281208190556127216135c0565b60008181526016602090815260408083206001600160a01b0380891685526011845282852054168452825280832054848452601790925282208054939450909290919061276f908490615a2a565b90915550506040516001600160a01b038416907f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba790600090a2505050565b6127b56139f5565b6127bd613fc2565b825b8281101561282457612812600f6000600884815481106127e1576127e1615974565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416836144e5565b8061281c816159a0565b9150506127bf565b5061282f6001605455565b505050565b61283c613843565b6001600160a01b0381166000908152601c602052604090205460ff16156128a55760405162461bcd60e51b815260206004820152600560248201527f616c6976650000000000000000000000000000000000000000000000000000006044820152606401610c68565b6001600160a01b03811660009081526019602052604090205460ff1661290d5760405162461bcd60e51b815260206004820152600b60248201527f6e6f7420612067617567650000000000000000000000000000000000000000006044820152606401610c68565b6001600160a01b038181166000818152601c602052604090819020805460ff19166001179055600254905163095ea7b360e01b8152600481019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af115801561297e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a29190615a9b565b5060035460405163095ea7b360e01b81526001600160a01b03838116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156129f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a1b9190615a9b565b506040516001600160a01b038216907fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa90600090a250565b600080612a5e6135c0565b60009081526016602090815260408083206001600160a01b039096168352949052929092205492915050565b612a92613fc2565b6000816001600160a01b03163b11612ad85760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b038116612b165760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6005546040516001600160a01b038084169216907f03ab94e51ce1ec8483c05c7425f6ebc27289fbd4a9c8b6ba0c2fe3b8b01765d490600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b60088181548110612b8257600080fd5b6000918252602090912001546001600160a01b0316905081565b612ba4613fc2565b6001600160a01b03831660009081526019602052604090205460ff16612bf55760405162461bcd60e51b815260206004820152600660248201526521676175676560d01b6044820152606401610c68565b6000836001600160a01b03163b11612c3b5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b612c4583836146a4565b61282f8382614770565b612c57613fc2565b6001600160a01b03821660009081526019602052604090205460ff16612ca85760405162461bcd60e51b815260206004820152600660248201526521676175676560d01b6044820152606401610c68565b610bbc82826146a4565b612cba613843565b60005b8151811015610bbc57612ce8828281518110612cdb57612cdb615974565b6020026020010151614839565b80612cf2816159a0565b915050612cbd565b8051825114612d4b5760405162461bcd60e51b815260206004820152601760248201527f4272696265732f546f6b656e73206c656e67746820213d0000000000000000006044820152606401610c68565b60005b825181101561282f57828181518110612d6957612d69615974565b60200260200101516001600160a01b031663db0ea98433848481518110612d9257612d92615974565b60200260200101516040518363ffffffff1660e01b8152600401612db7929190615ad1565b600060405180830381600087803b158015612dd157600080fd5b505af1158015612de5573d6000803e3d6000fd5b505050508080612df4906159a0565b915050612d4e565b60156020528160005260406000208181548110612e1857600080fd5b6000918252602090912001546001600160a01b03169150829050565b60005b8151811015610bbc5760196000838381518110612e5657612e56615974565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff168015612ec25750601c6000838381518110612e9a57612e9a615974565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff165b15612f4657818181518110612ed957612ed9615974565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f439190615af3565b50505b80612f50816159a0565b915050612e37565b8051825114612fa95760405162461bcd60e51b815260206004820152601460248201527f4665652f546f6b656e73206c656e67746820213d0000000000000000000000006044820152606401610c68565b60005b825181101561282f57828181518110612fc757612fc7615974565b60200260200101516001600160a01b031663db0ea98433848481518110612ff057612ff0615974565b60200260200101516040518363ffffffff1660e01b8152600401613015929190615ad1565b600060405180830381600087803b15801561302f57600080fd5b505af1158015613043573d6000803e3d6000fd5b505050508080613052906159a0565b915050612fac565b613062613fc2565b6001600160a01b0382166000818152601f6020908152604091829020805460ff191685151590811790915591519182527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a9910160405180910390a25050565b6130c9613fc2565b6000816001600160a01b03163b1161310f5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6003546040516001600160a01b038084169216907fa078441d4124bc8d06fb66724c308c14f635a5a0d2bb1f422400e094b5cac40c90600090a36003546001600160a01b031680156131d45760025460405163095ea7b360e01b81526001600160a01b038381166004830152600060248301529091169063095ea7b3906044016020604051808303816000875af11580156131ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d29190615a9b565b505b6001600160a01b038181166000908152601f602052604090819020805460ff19169055600380546001600160a01b031916858416908117909155600254915163095ea7b360e01b81526004810191909152600019602482015291169063095ea7b3906044016020604051808303816000875af1158015613258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327c9190615a9b565b506003546001600160a01b03166000908152601f60205260408120805460ff191660011790556008546064116132b35760646132b7565b6008545b6008549091501561282f5761282f600082846127ad565b6132d6613843565b60005b8151811015610bbc576133048282815181106132f7576132f7615974565b602002602001015161491a565b8061330e816159a0565b9150506132d9565b61331e6139f5565b3361332881613a4e565b613331816149fb565b6133396135c0565b6133449060016159f5565b6001600160a01b039091166000908152601860205260409020556110606001605455565b613370613fc2565b6001600160a01b03821660009081526019602052604090205460ff166133c15760405162461bcd60e51b815260206004820152600660248201526521676175676560d01b6044820152606401610c68565b610bbc8282614770565b60008060006133d86139f5565b6133e28585614341565b9194509250905061189b6001605455565b6006546001600160a01b03163314806134785750600754604051634448e1eb60e01b81526001600160a01b0390911690634448e1eb90613437903390600401615b17565b602060405180830381865afa158015613454573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134789190615a9b565b61348157600080fd5b60005460ff161561349157600080fd5b60005b84518110156134c4576134b2858281518110612cdb57612cdb615974565b806134bc816159a0565b915050613494565b50600680546001600160a01b038085166001600160a01b03199283161790925560078054868416921691909117905581161561358b57600380546001600160a01b0319166001600160a01b0383811691821790925560025460405163095ea7b360e01b8152600481019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015613565573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135899190615a9b565b505b50506003546001600160a01b03166000908152601f602052604081208054600160ff1991821681179092558254161790555050565b600654604080517fd139960800000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163d13996089160048083019260209291908290030181865afa158015613623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136479190615a82565b905090565b60005b8151811015610bbc5781818151811061366a5761366a615974565b60209081029190910101516040517fc00007b00000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b039091169063c00007b090602401600060405180830381600087803b1580156136d057600080fd5b505af11580156136e4573d6000803e3d6000fd5b5050505080806136f3906159a0565b91505061364f565b613703613fc2565b6001600160a01b0381166137415760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6000816001600160a01b03163b116137875760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6006546040516001600160a01b038084169216907fe490d3138e32f1f66ef3971a3c73c7f7704ba0c1d1000f1e2c3df6fc0376610b90600090a3600680546001600160a01b0319166001600160a01b0392909216919091179055565b6060600180548060200260200160405190810160405280929190818152602001828054801561250c576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116124ee575050505050905090565b600754604051634448e1eb60e01b81526001600160a01b0390911690634448e1eb90613873903390600401615b59565b602060405180830381865afa158015613890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138b49190615a9b565b6110605760405162461bcd60e51b8152600401610c6890615b83565b6001600160a01b0381166000908152601a602052604090205460ff166139385760405162461bcd60e51b815260206004820152600360248201527f6f757400000000000000000000000000000000000000000000000000000000006044820152606401610c68565b6001600160a01b0381166000818152601a6020526040808220805460ff191690555133917fd36871fdf6981136f3ac0564927005901eda06f7a9dff1e8b2a1d7846b8ebb5091a350565b605354610100900460ff166139ed5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610c68565b611060614d14565b600260545403613a475760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c68565b6002605455565b600b546001600160a01b038216600090815260186020526040902054613a7491906159f5565b42118015613a885750613a856135c0565b42115b611bc25760405162461bcd60e51b815260206004820152600f60248201527f4552523a20564f54455f44454c415900000000000000000000000000000000006044820152606401610c68565b613add836149fb565b81516000613ae96135c0565b600080546040517f3a46b1a80000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301526024820185905293945091926101009091041690633a46b1a890604401602060405180830381865afa158015613b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b819190615a82565b90506000806000805b86811015613c2957601c6000600f60008c8581518110613bac57613bac615974565b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120549093168452830193909352910190205460ff1615613c1757878181518110613c0157613c01615974565b602002602001015184613c1491906159f5565b93505b80613c21816159a0565b915050613b8a565b5060005b86811015613f8c576000898281518110613c4957613c49615974565b6020908102919091018101516001600160a01b038082166000908152600f84526040808220549092168082526019909452205490925060ff168015613ca657506001600160a01b0381166000908152601c602052604090205460ff165b15613f7757600086888c8681518110613cc157613cc1615974565b6020026020010151613cd39190615a41565b613cdd9190615a60565b6001600160a01b03808f1660009081526014602090815260408083209388168352929052205490915015613d1057600080fd5b80600003613d4a576040517fcabeb65500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038d8116600090815260156020908152604080832080546001810182559084528284200180546001600160a01b03191694881694851790558c8352601682528083209383529290529081208054839290613dac9084906159f5565b90915550506001600160a01b03808e16600090815260146020908152604080832093871683529290529081208054839290613de89084906159f5565b90915550506001600160a01b03808316600090815260126020526040908190205490517f6e553f65000000000000000000000000000000000000000000000000000000008152600481018490528f83166024820152911690636e553f6590604401600060405180830381600087803b158015613e6357600080fd5b505af1158015613e77573d6000803e3d6000fd5b5050505060136000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b0316636e553f65828f6040518363ffffffff1660e01b8152600401613ef39291909182526001600160a01b0316602082015260400190565b600060405180830381600087803b158015613f0d57600080fd5b505af1158015613f21573d6000803e3d6000fd5b505050508085613f3191906159f5565b9450613f3d81876159f5565b60405182815290965033907f4d99b957a2bc29a30ebd96a7be8e68fe50a3c701db28a91436490b7d53870ca49060200160405180910390a2505b50508080613f84906159a0565b915050613c2d565b5060008581526017602052604081208054849290613fab9084906159f5565b9091555050505050505050505050565b6001605455565b600754604051634448e1eb60e01b81526001600160a01b0390911690634448e1eb90613ff2903390600401615b17565b602060405180830381865afa15801561400f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140339190615a9b565b6110605760405162461bcd60e51b8152600401610c6890615bad565b6040516001600160a01b038085166024830152831660448201526064810182905261203f9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614d7f565b6001600160a01b038116600090815260106020526040812054906141226135c0565b90508082101561282f5761413583614e67565b6001600160a01b0383166000908152600e6020526040902054801580159061417557506001600160a01b0384166000908152601c602052604090205460ff165b1561203f576001600160a01b038085166000908152600e60209081526040808320839055601090915290208390556003541615614294576003546040517f40c10f19000000000000000000000000000000000000000000000000000000008152306004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b15801561421157600080fd5b505af1158015614225573d6000803e3d6000fd5b505060035460405163b66503cf60e01b81526001600160a01b03918216600482015260248101859052908716925063b66503cf9150604401600060405180830381600087803b15801561427757600080fd5b505af115801561428b573d6000803e3d6000fd5b505050506142fb565b60025460405163b66503cf60e01b81526001600160a01b039182166004820152602481018390529085169063b66503cf90604401600060405180830381600087803b1580156142e257600080fd5b505af11580156142f6573d6000803e3d6000fd5b505050505b6040518181526001600160a01b0385169033907f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a350505050565b60208054604080516001600160a01b0386811660248301526044808301879052835180840390910181526064909201835293810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fdcd9e47a0000000000000000000000000000000000000000000000000000000017905290516000938493849384938493909216916143d49190615c04565b600060405180830381855af49150503d806000811461440f576040519150601f19603f3d011682016040523d82523d6000602084013e614414565b606091505b509150915060006144258383614fba565b90508080602001905181019061443b9190615c20565b604080513381526001600160a01b038085166020830152949a50929850909650828b169280881692908a16917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a45050509250925092565b6040516001600160a01b03831660248201526044810182905261282f9084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161409c565b6001600160a01b038116156145695760405163095ea7b360e01b81526001600160a01b0383811660048301526000602483015282169063095ea7b3906044016020604051808303816000875af1158015614543573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145679190615a9b565b505b6003546001600160a01b03166145f25760025460405163095ea7b360e01b81526001600160a01b03848116600483015260001960248301529091169063095ea7b3906044015b6020604051808303816000875af11580156145ce573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282f9190615a9b565b60035460405163095ea7b360e01b81526001600160a01b03848116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015614646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061466a9190615a9b565b5060025460405163095ea7b360e01b81526001600160a01b038481166004830152600060248301529091169063095ea7b3906044016145af565b6000816001600160a01b03163b116146ea5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b03828116600081815260126020908152604091829020549151600181529293858116939216917fddf0ec8cba6dad18edc75774c452fa4201ff17ec1761486329f3321936ce66d0910160405180910390a46001600160a01b03918216600090815260126020526040902080546001600160a01b03191691909216179055565b6000816001600160a01b03163b116147b65760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b03828116600081815260126020908152604080832054905192835292938581169316917fddf0ec8cba6dad18edc75774c452fa4201ff17ec1761486329f3321936ce66d0910160405180910390a46001600160a01b03918216600090815260136020526040902080546001600160a01b03191691909216179055565b6001600160a01b0381166000908152601a602052604090205460ff16156148875760405162461bcd60e51b815260206004820152600260248201526134b760f11b6044820152606401610c68565b6000816001600160a01b03163b116148cd5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b0381166000818152601a6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b0381166000908152601b602052604090205460ff16156149685760405162461bcd60e51b815260206004820152600260248201526134b760f11b6044820152606401610c68565b6000816001600160a01b03163b116149ae5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b0381166000818152601b6020526040808220805460ff191660011790555133917f88e52751b2db8161caf8700d6127c81ae036b0c7bd22fdbcfeff5d7f79cdcae591a350565b6001600160a01b03811660009081526015602052604081208054909180614a206135c0565b6001600160a01b038616600090815260186020526040812054919250908210905b84811015614caa576000868281548110614a5d57614a5d615974565b60009182526020808320909101546001600160a01b038b81168452601483526040808520919092168085529252909120549091508015614c95578315614ad55760008581526016602090815260408083206001600160a01b038616845290915281208054839290614acf908490615a2a565b90915550505b6001600160a01b03808a16600090815260146020908152604080832093861683529290529081208054839290614b0c908490615a2a565b90915550506001600160a01b038281166000908152600f602090815260408083205484168352601290915290819020549051627b8a6760e11b8152600481018490528b8316602482015291169062f714ce90604401600060405180830381600087803b158015614b7b57600080fd5b505af1158015614b8f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600f602090815260408083205484168352601390915290819020549051627b8a6760e11b8152600481018490528b8316602482015291169062f714ce90604401600060405180830381600087803b158015614bfd57600080fd5b505af1158015614c11573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600f60209081526040808320549093168252601c9052205460ff1615614c5257614c4f81876159f5565b95505b604080516001600160a01b038b168152602081018390527f433fa8b9e8e2cb00bd714503252e8bfd144f0f318459a2ea8b39c1ae25361717910160405180910390a15b50508080614ca2906159a0565b915050614a41565b506001600160a01b038616600090815260186020526040902054821115614cd057600092505b60008281526017602052604081208054859290614cee908490615a2a565b90915550506001600160a01b0386166000908152601560205260408120610ead9161521b565b605354610100900460ff16613fbb5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610c68565b6000614dd4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166150749092919063ffffffff16565b9050805160001480614df5575080806020019051810190614df59190615a9b565b61282f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610c68565b6001600160a01b038082166000908152601160205260408120549091169062093a80614e916135c0565b614e9b9190615a2a565b60008181526016602090815260408083206001600160a01b03871684529091529020549091508015614f98576001600160a01b0384166000908152600d6020526040812080546009549182905591614ef38383615a2a565b90508015614f90576000670de0b6b3a7640000614f108387615a41565b614f1a9190615a60565b6001600160a01b0389166000908152601c602052604090205490915060ff1615614f71576001600160a01b0388166000908152600e602052604081208054839290614f669084906159f5565b90915550614f8e9050565b600654600254614f8e916001600160a01b0391821691168361449c565b505b50505061203f565b6009546001600160a01b0385166000908152600d602052604090205550505050565b60608215614fc9575080611be9565b6044825110156150415760405162461bcd60e51b815260206004820152602b60248201527f64656c656761746563616c6c206661696c656420776974686f7574206120726560448201527f7665727420726561736f6e0000000000000000000000000000000000000000006064820152608401610c68565b6004820191508180602001905181019061505b9190615c62565b60405162461bcd60e51b8152600401610c689190615cf6565b6060615083848460008561508b565b949350505050565b6060824710156151035760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610c68565b600080866001600160a01b0316858760405161511f9190615c04565b60006040518083038185875af1925050503d806000811461515c576040519150601f19603f3d011682016040523d82523d6000602084013e615161565b606091505b50915091506151728783838761517d565b979650505050505050565b606083156151ec5782516000036151e5576001600160a01b0385163b6151e55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c68565b5081615083565b61508383838151156152015781518083602001fd5b8060405162461bcd60e51b8152600401610c689190615cf6565b5080546000825590600052602060002090810190611bc291905b808211156152495760008155600101615235565b5090565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561528c5761528c61524d565b604052919050565b600067ffffffffffffffff8211156152ae576152ae61524d565b5060051b60200190565b6001600160a01b0381168114611bc257600080fd5b600082601f8301126152de57600080fd5b813560206152f36152ee83615294565b615263565b82815260059290921b8401810191818101908684111561531257600080fd5b8286015b84811015615336578035615329816152b8565b8352918301918301615316565b509695505050505050565b60006020828403121561535357600080fd5b813567ffffffffffffffff81111561536a57600080fd5b615083848285016152cd565b60006020828403121561538857600080fd5b8135615393816152b8565b9392505050565b600080600080600060a086880312156153b257600080fd5b85356153bd816152b8565b945060208601356153cd816152b8565b935060408601356153dd816152b8565b925060608601356153ed816152b8565b915060808601356153fd816152b8565b809150509295509295909350565b60008060006060848603121561542057600080fd5b833561542b816152b8565b9250602084013561543b816152b8565b929592945050506040919091013590565b60006020828403121561545e57600080fd5b5035919050565b6000806040838503121561547857600080fd5b823567ffffffffffffffff8082111561549057600080fd5b61549c868387016152cd565b93506020915081850135818111156154b357600080fd5b85019050601f810186136154c657600080fd5b80356154d46152ee82615294565b81815260059190911b820183019083810190888311156154f357600080fd5b928401925b82841015615511578335825292840192908401906154f8565b80955050505050509250929050565b600081518084526020808501945080840160005b838110156155595781516001600160a01b031687529582019590820190600101615534565b509495945050505050565b6060815260006155776060830186615520565b82810360208401526155898186615520565b9050828103604084015261559d8185615520565b9695505050505050565b600080604083850312156155ba57600080fd5b82356155c5816152b8565b946020939093013593505050565b600080604083850312156155e657600080fd5b82356155f1816152b8565b91506020830135615601816152b8565b809150509250929050565b600082601f83011261561d57600080fd5b8135602061562d6152ee83615294565b82815260059290921b8401810191818101908684111561564c57600080fd5b8286015b8481101561533657803567ffffffffffffffff8111156156705760008081fd5b61567e8986838b01016152cd565b845250918301918301615650565b6000806000606084860312156156a157600080fd5b833567ffffffffffffffff808211156156b957600080fd5b6156c5878388016152cd565b945060208601359150808211156156db57600080fd5b506156e88682870161560c565b925050604084013590509250925092565b60008083601f84011261570b57600080fd5b50813567ffffffffffffffff81111561572357600080fd5b6020830191508360208260051b850101111561573e57600080fd5b9250929050565b6000806000806040858703121561575b57600080fd5b843567ffffffffffffffff8082111561577357600080fd5b61577f888389016156f9565b9096509450602087013591508082111561579857600080fd5b506157a5878288016156f9565b95989497509550505050565b600080604083850312156157c457600080fd5b50508035926020909101359150565b6020815260006153936020830184615520565b6000806000606084860312156157fb57600080fd5b83359250602084013591506040840135615814816152b8565b809150509250925092565b60008060006060848603121561583457600080fd5b833561583f816152b8565b9250602084013561584f816152b8565b91506040840135615814816152b8565b6000806040838503121561587257600080fd5b823567ffffffffffffffff8082111561588a57600080fd5b615896868387016152cd565b935060208501359150808211156158ac57600080fd5b506158b98582860161560c565b9150509250929050565b8015158114611bc257600080fd5b600080604083850312156158e457600080fd5b82356158ef816152b8565b91506020830135615601816158c3565b6000806000806080858703121561591557600080fd5b843567ffffffffffffffff81111561592c57600080fd5b615938878288016152cd565b9450506020850135615949816152b8565b92506040850135615959816152b8565b91506060850135615969816152b8565b939692955090935050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016159b2576159b261598a565b5060010190565b6000602082840312156159cb57600080fd5b8151615393816152b8565b600060ff821660ff81036159ec576159ec61598a565b60010192915050565b60008219821115615a0857615a0861598a565b500190565b600060ff821680615a2057615a2061598a565b6000190192915050565b600082821015615a3c57615a3c61598a565b500390565b6000816000190483118215151615615a5b57615a5b61598a565b500290565b600082615a7d57634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215615a9457600080fd5b5051919050565b600060208284031215615aad57600080fd5b8151615393816158c3565b8281526040602082015260006150836040830184615520565b6001600160a01b03831681526040602082015260006150836040830184615520565b60008060408385031215615b0657600080fd5b505080516020909101519092909150565b604081526000615b4260408301600b81526a2b27aa22a92fa0a226a4a760a91b602082015260400190565b90506001600160a01b038316602083015292915050565b604081526000615b4260408301600a815269474f5645524e414e434560b01b602082015260400190565b602081526000611be960208301600a815269474f5645524e414e434560b01b602082015260400190565b602081526000611be960208301600b81526a2b27aa22a92fa0a226a4a760a91b602082015260400190565b60005b83811015615bf3578181015183820152602001615bdb565b8381111561203f5750506000910152565b60008251615c16818460208701615bd8565b9190910192915050565b600080600060608486031215615c3557600080fd5b8351615c40816152b8565b6020850151909350615c51816152b8565b6040850151909250615814816152b8565b600060208284031215615c7457600080fd5b815167ffffffffffffffff80821115615c8c57600080fd5b818401915084601f830112615ca057600080fd5b815181811115615cb257615cb261524d565b615cc5601f8201601f1916602001615263565b9150808252856020828501011115615cdc57600080fd5b615ced816020840160208601615bd8565b50949350505050565b6020815260008251806020840152615d15816040850160208701615bd8565b601f01601f1916919091016040019291505056fea26469706673582212201eaec667eb32deb1a1dd2f5226855fef39a099053a3eb0406fd23169d0b37f8964736f6c634300080d0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104c35760003560e01c806396c82e5711610286578063c48f5af41161016b578063dcd9e47a116100e3578063f8803bb611610097578063fca3b5aa1161007c578063fca3b5aa14610b50578063fe5b38e414610b63578063ffe5195b14610b6b57600080fd5b8063f8803bb614610b35578063f9f031df14610b3d57600080fd5b8063e6da0457116100c8578063e6da045714610ac9578063eae40f2614610ae9578063f2312ab014610b1257600080fd5b8063dcd9e47a14610a79578063df7ae62e14610ab657600080fd5b8063cdcaa13b1161013a578063d4857bfd1161011f578063d4857bfd14610a4b578063d826f88f14610a5e578063daa168bd14610a6657600080fd5b8063cdcaa13b14610a25578063d1a8e08c14610a3857600080fd5b8063c48f5af4146109c1578063c527ee1f146109d4578063c991866d146109e7578063cad1b906146109fa57600080fd5b8063ae21c4cb116101fe578063b55a5c1c116101cd578063b9a09fd5116101b2578063b9a09fd514610972578063bd8aa7801461099b578063c2b79e98146109ae57600080fd5b8063b55a5c1c1461094c578063b7c89f9c1461095f57600080fd5b8063ae21c4cb146108f5578063ae9c9e3f1461091e578063b0f5027814610931578063b52a31511461094457600080fd5b80639f06247b11610255578063a9b5aa7e1161023a578063a9b5aa7e146108ac578063aa79979b146108bf578063ac4afa38146108e257600080fd5b80639f06247b14610886578063a7cac8461461089957600080fd5b806396c82e5714610838578063992a7933146108405780639a61df89146108535780639a83ed3b1461087357600080fd5b80635001f3b5116103ac5780636c4f2e38116103245780638657c745116102f35780638daeaa5a116102d85780638daeaa5a146107e25780638dd598fb1461080b57806390e934161461082357600080fd5b80638657c745146107bc5780638b6fc247146107cf57600080fd5b80636c4f2e381461077a5780636f816a20146107835780637625391a146107965780637715ee75146107a957600080fd5b80636138889b1161037b5780636566afad116103605780636566afad14610731578063657021fb14610744578063666256aa1461076757600080fd5b80636138889b1461070b578063636056f21461071e57600080fd5b80635001f3b5146106a257806353be568d146106b557806355f168d5146106d5578063577387b5146106f857600080fd5b806327e5c8231161043f5780633c6b16ab1161040e578063436596c4116103f3578063436596c414610670578063470f4985146106785780634d68ce441461068057600080fd5b80633c6b16ab1461063d578063402914f51461065057600080fd5b806327e5c823146105e157806333832a6a146105f457806338752a9d146106075780633af32abf1461061a57600080fd5b80631459457a11610496578063181783581161047b57806318178358146105b15780631f7b6d32146105b95780631f850716146105cb57600080fd5b80631459457a1461056b5780631703e5f91461057e57600080fd5b8063041f173f146104c857806306d6a1b2146104dd57806307546172146105235780630f04ba6714610536575b600080fd5b6104db6104d6366004615341565b610b74565b005b6105066104eb366004615376565b6011602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600654610506906001600160a01b031681565b610559610544366004615376565b601d6020526000908152604090205460ff1681565b60405160ff909116815260200161051a565b6104db61057936600461539a565b610bc0565b6105a161058c366004615376565b601c6020526000908152604090205460ff1681565b604051901515815260200161051a565b6104db610eb5565b6008545b60405190815260200161051a565b60005461010090046001600160a01b0316610506565b6104db6105ef36600461540b565b611062565b6104db610602366004615376565b611342565b600554610506906001600160a01b031681565b6105a1610628366004615376565b601a6020526000908152604090205460ff1681565b6104db61064b36600461544c565b61142a565b6105bd61065e366004615376565b600e6020526000908152604090205481565b6104db611548565b6001546105bd565b61069361068e366004615465565b611641565b60405161051a93929190615564565b600254610506906001600160a01b031681565b6105bd6106c336600461544c565b60009081526017602052604090205490565b6105a16106e3366004615376565b601b6020526000908152604090205460ff1681565b6104db61070636600461544c565b6118a2565b6104db610719366004615341565b611af5565b6105bd61072c3660046155a7565b611bc5565b6104db61073f3660046155d3565b611bef565b6105a1610752366004615376565b601e6020526000908152604090205460ff1681565b6104db61077536600461568c565b611e7a565b6105bd600c5481565b6104db610791366004615745565b612045565b6104db6107a43660046157b1565b612140565b6104db6107b736600461568c565b612203565b600354610506906001600160a01b031681565b6104db6107dd36600461544c565b6123c8565b6105bd6107f0366004615376565b6001600160a01b031660009081526015602052604090205490565b6000546105069061010090046001600160a01b031681565b61082b6124b4565b60405161051a91906157d3565b6105bd612516565b6104db61084e366004615376565b612536565b6105bd610861366004615376565b60186020526000908152604090205481565b6104db6108813660046157e6565b6127ad565b6104db610894366004615376565b612834565b6105bd6108a7366004615376565b612a53565b6104db6108ba366004615376565b612a8a565b6105a16108cd366004615376565b60196020526000908152604090205460ff1681565b6105066108f036600461544c565b612b72565b610506610903366004615376565b6013602052600090815260409020546001600160a01b031681565b602054610506906001600160a01b031681565b6104db61093f36600461581f565b612b9c565b6004546105bd565b600754610506906001600160a01b031681565b6104db61096d3660046155d3565b612c4f565b610506610980366004615376565b600f602052600090815260409020546001600160a01b031681565b6104db6109a9366004615341565b612cb2565b6104db6109bc36600461585f565b612cfa565b6105066109cf3660046155a7565b612dfc565b6104db6109e2366004615341565b612e34565b6104db6109f536600461585f565b612f58565b6105bd610a083660046155d3565b601460209081526000928352604080842090915290825290205481565b6104db610a333660046158d1565b61305a565b6104db610a46366004615376565b6130c1565b6104db610a59366004615341565b6132ce565b6104db613316565b6104db610a743660046155d3565b613368565b610a8c610a873660046155a7565b6133cb565b604080516001600160a01b039485168152928416602084015292169181019190915260600161051a565b6104db610ac43660046158ff565b6133f3565b6105bd610ad7366004615376565b60106020526000908152604090205481565b610506610af7366004615376565b6012602052600090815260409020546001600160a01b031681565b6105a1610b20366004615376565b601f6020526000908152604090205460ff1681565b6105bd6135c0565b6104db610b4b366004615341565b61364c565b6104db610b5e366004615376565b6136fb565b61082b6137e3565b6105bd600b5481565b610b7c613843565b60005b8151811015610bbc57610baa828281518110610b9d57610b9d615974565b60200260200101516138d0565b80610bb4816159a0565b915050610b7f565b5050565b605354610100900460ff1615808015610be05750605354600160ff909116105b80610bfa5750303b158015610bfa575060535460ff166001145b610c715760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6053805460ff191660011790558015610c94576053805461ff0019166101001790555b610c9c613982565b85600060016101000a8154816001600160a01b0302191690836001600160a01b03160217905550856001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2591906159b9565b600280546001600160a01b039283166001600160a01b031991821617909155600180548082019091557fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601805492881692909116821790556000908152601d60205260408120805460ff1691610d9a836159d6565b82546101009290920a60ff818102199093169190921691909102179055506004805460018181019092557f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03199081166001600160a01b038881169182179093556000908152601e602090815260408220805460ff199081169096179055600580548416898616179055600680543390851681179091556007805485169091179055600b82905562093a80600a819055600c55815490941690558254169084161790558015610ead576053805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610ebd6139f5565b33610ec781613a4e565b6001600160a01b038116600090815260156020908152604080832080548251818502810185019093528083529192909190830182828015610f3157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f13575b5050505050905060008151905060008167ffffffffffffffff811115610f5957610f5961524d565b604051908082528060200260200182016040528015610f82578160200160208202803683370190505b50905060005b82811015611017576001600160a01b03851660009081526014602052604081208551909190869084908110610fbf57610fbf615974565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610ffa57610ffa615974565b60209081029190910101528061100f816159a0565b915050610f88565b50611023848483613ad4565b61102b6135c0565b6110369060016159f5565b6001600160a01b03909416600090815260186020526040902093909355506110609150613fbb9050565b565b61106a613fc2565b6001600160a01b0383166110a85760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6001600160a01b0382166110e65760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6001600160a01b0382166000908152601e602052604090205460ff166111375760405162461bcd60e51b81526020600482015260066024820152650859d19858dd60d21b6044820152606401610c68565b60006001828154811061114c5761114c615974565b6000918252602082200154600480546001600160a01b039092169350908490811061117957611179615974565b60009182526020808320909101546001600160a01b038581168452601d90925260408320805492909116935060ff909116916111b483615a0d565b825460ff9182166101009390930a9283029190920219909116179055506001600160a01b0381166000908152601e60205260409020805460ff19169055600180548691908590811061120857611208615974565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550836004848154811061124a5761124a615974565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790559187168152601d90915260408120805460ff169161128f836159d6565b825460ff9182166101009390930a9283029190920219909116179055506001600160a01b038085166000818152601e6020526040808220805460ff191660011790555191928416917fa1bb19b5d754d8c6479f7761797294f0786b22f6fe2fd51b0b81e56f4136cd939190a3846001600160a01b0316826001600160a01b03167fa01124614129d8b1fb8a4fd2f718422cb3d34c92ff59026e1fb316871a2b9c3960405160405180910390a35050505050565b61134a613fc2565b6000816001600160a01b03163b116113905760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b0381166113ce5760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6007546040516001600160a01b038084169216907f19fff1a4baaea69caec27e064bdfc0cb61d642370694fffdc0d38a568eb89b7390600090a3600780546001600160a01b0319166001600160a01b0392909216919091179055565b6006546001600160a01b031633146114845760405162461bcd60e51b815260206004820152600760248201527f216d696e746572000000000000000000000000000000000000000000000000006044820152606401610c68565b60025461149c906001600160a01b031633308461404f565b60006114b762093a806114ad6135c0565b6106c39190615a2a565b9050600081156114e157816114d484670de0b6b3a7640000615a41565b6114de9190615a60565b90505b80156114ff5780600960008282546114f991906159f5565b90915550505b6002546040518481526001600160a01b039091169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a3505050565b6115506139f5565b600660009054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af11580156115a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c99190615a82565b506008546000905b8082101561163557611623600f6000600885815481106115f3576115f3615974565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416614100565b8161162d816159a0565b9250506115d1565b50506110606001605455565b606080606061164e6139f5565b835185511461169f5760405162461bcd60e51b815260206004820152600c60248201527f6c656e206d69736d6174636800000000000000000000000000000000000000006044820152606401610c68565b600a855111156116f15760405162461bcd60e51b815260206004820152600660248201527f6d617820313000000000000000000000000000000000000000000000000000006044820152606401610c68565b6000855167ffffffffffffffff81111561170d5761170d61524d565b604051908082528060200260200182016040528015611736578160200160208202803683370190505b5090506000865167ffffffffffffffff8111156117555761175561524d565b60405190808252806020026020018201604052801561177e578160200160208202803683370190505b5090506000875167ffffffffffffffff81111561179d5761179d61524d565b6040519080825280602002602001820160405280156117c6578160200160208202803683370190505b50905060005b8851811015611889576118118982815181106117ea576117ea615974565b602002602001015189838151811061180457611804615974565b6020026020010151614341565b86848151811061182357611823615974565b6020026020010186858151811061183c5761183c615974565b6020026020010186868151811061185557611855615974565b6001600160a01b03948516602091820292909201015292821690925291909116905280611881816159a0565b9150506117cc565b509194509250905061189b6001605455565b9250925092565b6118aa613fc2565b6000600182815481106118bf576118bf615974565b6000918252602082200154600480546001600160a01b03909216935090849081106118ec576118ec615974565b60009182526020808320909101546001600160a01b038581168452601d9092526040909220549116915060ff166119655760405162461bcd60e51b815260206004820152600560248201527f21666163740000000000000000000000000000000000000000000000000000006044820152606401610c68565b6001600160a01b0381166000908152601e602052604090205460ff166119b65760405162461bcd60e51b81526020600482015260066024820152650859d19858dd60d21b6044820152606401610c68565b6000600184815481106119cb576119cb615974565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600060048481548110611a0e57611a0e615974565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790559184168152601d90915260408120805460ff1691611a5383615a0d565b825460ff9182166101009390930a9283029190920219909116179055506001600160a01b0381166000818152601e6020526040808220805460ff19169055519091907fa1bb19b5d754d8c6479f7761797294f0786b22f6fe2fd51b0b81e56f4136cd93908390a36040516000906001600160a01b038416907fa01124614129d8b1fb8a4fd2f718422cb3d34c92ff59026e1fb316871a2b9c39908390a3505050565b611afd6139f5565b600660009054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611b52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b769190615a82565b5060005b8151811015611bb757611ba5828281518110611b9857611b98615974565b6020026020010151614100565b80611baf816159a0565b915050611b7a565b50611bc26001605455565b50565b60008181526016602090815260408083206001600160a01b03861684529091529020545b92915050565b611bf7613fc2565b6001600160a01b038216611c355760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6001600160a01b038116611c735760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6001600160a01b0381166000908152601e602052604090205460ff1615611cdc5760405162461bcd60e51b815260206004820152600560248201527f67466163740000000000000000000000000000000000000000000000000000006044820152606401610c68565b6000826001600160a01b03163b11611d225760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6000816001600160a01b03163b11611d685760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001805480820182557fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03199081166001600160a01b038681169182179093556004805494850190557f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b90930180549091169184169190911790556000908152601d60205260408120805460ff1691611e0a836159d6565b825460ff9182166101009390930a9283029190920219909116179055506001600160a01b038082166000818152601e6020526040808220805460ff191660011790555191928516917f8bad2b894999c82738dc185dbb158d846fce35d7edbcc0661b1b97d9aacba69d9190a35050565b60005460405163430c208160e01b8152336004820152602481018390526101009091046001600160a01b03169063430c208190604401602060405180830381865afa158015611ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef19190615a9b565b611f3d5760405162461bcd60e51b815260206004820152600f60248201527f21617070726f7665642f4f776e657200000000000000000000000000000000006044820152606401610c68565b8151835114611f8e5760405162461bcd60e51b815260206004820152601460248201527f4665652f546f6b656e73206c656e67746820213d0000000000000000000000006044820152606401610c68565b60005b835181101561203f57838181518110611fac57611fac615974565b60200260200101516001600160a01b031663a7852afa83858481518110611fd557611fd5615974565b60200260200101516040518363ffffffff1660e01b8152600401611ffa929190615ab8565b600060405180830381600087803b15801561201457600080fd5b505af1158015612028573d6000803e3d6000fd5b505050508080612037906159a0565b915050611f91565b50505050565b61204d6139f5565b61205633613a4e565b8281146120a55760405162461bcd60e51b815260206004820152601660248201527f506f6f6c2f57656967687473206c656e67746820213d000000000000000000006044820152606401610c68565b6121133385858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250613ad492505050565b61211b6135c0565b6121269060016159f5565b3360009081526018602052604090205561203f6001605455565b6121486139f5565b600660009054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af115801561219d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c19190615a82565b50815b818110156121f8576121e6600f6000600884815481106115f3576115f3615974565b806121f0816159a0565b9150506121c4565b50610bbc6001605455565b60005460405163430c208160e01b8152336004820152602481018390526101009091046001600160a01b03169063430c208190604401602060405180830381865afa158015612256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227a9190615a9b565b6122c65760405162461bcd60e51b815260206004820152600f60248201527f21617070726f7665642f4f776e657200000000000000000000000000000000006044820152606401610c68565b81518351146123175760405162461bcd60e51b815260206004820152601760248201527f4272696265732f546f6b656e73206c656e67746820213d0000000000000000006044820152606401610c68565b60005b835181101561203f5783818151811061233557612335615974565b60200260200101516001600160a01b031663a7852afa8385848151811061235e5761235e615974565b60200260200101516040518363ffffffff1660e01b8152600401612383929190615ab8565b600060405180830381600087803b15801561239d57600080fd5b505af11580156123b1573d6000803e3d6000fd5b5050505080806123c0906159a0565b91505061231a565b6123d0613fc2565b600b5481036124215760405162461bcd60e51b815260206004820152600b60248201527f616c7265616479207365740000000000000000000000000000000000000000006044820152606401610c68565b600c548111156124735760405162461bcd60e51b815260206004820152600960248201527f6d61782064656c617900000000000000000000000000000000000000000000006044820152606401610c68565b600b5460408051918252602082018390527f17fb843f25faf2431510bc4a71e4898ccc1a28a3e985450e509670d14be2eaa1910160405180910390a1600b55565b6060600480548060200260200160405190810160405280929190818152602001828054801561250c57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116124ee575b5050505050905090565b6000806125216135c0565b60009081526017602052604090205492915050565b61253e613843565b6001600160a01b0381166000908152601c602052604090205460ff166125a65760405162461bcd60e51b815260206004820152600660248201527f6b696c6c656400000000000000000000000000000000000000000000000000006044820152606401610c68565b60025460405163095ea7b360e01b81526001600160a01b038381166004830152600060248301529091169063095ea7b3906044016020604051808303816000875af11580156125f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261d9190615a9b565b5060035460405163095ea7b360e01b81526001600160a01b038381166004830152600060248301529091169063095ea7b3906044016020604051808303816000875af1158015612671573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126959190615a9b565b506001600160a01b0381166000908152600e602052604090205480156126ec576006546002546126d2916001600160a01b0391821691168361449c565b6001600160a01b0382166000908152600e60205260408120555b6001600160a01b0382166000908152601c60209081526040808320805460ff19169055600e90915281208190556127216135c0565b60008181526016602090815260408083206001600160a01b0380891685526011845282852054168452825280832054848452601790925282208054939450909290919061276f908490615a2a565b90915550506040516001600160a01b038416907f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba790600090a2505050565b6127b56139f5565b6127bd613fc2565b825b8281101561282457612812600f6000600884815481106127e1576127e1615974565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416836144e5565b8061281c816159a0565b9150506127bf565b5061282f6001605455565b505050565b61283c613843565b6001600160a01b0381166000908152601c602052604090205460ff16156128a55760405162461bcd60e51b815260206004820152600560248201527f616c6976650000000000000000000000000000000000000000000000000000006044820152606401610c68565b6001600160a01b03811660009081526019602052604090205460ff1661290d5760405162461bcd60e51b815260206004820152600b60248201527f6e6f7420612067617567650000000000000000000000000000000000000000006044820152606401610c68565b6001600160a01b038181166000818152601c602052604090819020805460ff19166001179055600254905163095ea7b360e01b8152600481019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af115801561297e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a29190615a9b565b5060035460405163095ea7b360e01b81526001600160a01b03838116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156129f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a1b9190615a9b565b506040516001600160a01b038216907fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa90600090a250565b600080612a5e6135c0565b60009081526016602090815260408083206001600160a01b039096168352949052929092205492915050565b612a92613fc2565b6000816001600160a01b03163b11612ad85760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b038116612b165760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6005546040516001600160a01b038084169216907f03ab94e51ce1ec8483c05c7425f6ebc27289fbd4a9c8b6ba0c2fe3b8b01765d490600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b60088181548110612b8257600080fd5b6000918252602090912001546001600160a01b0316905081565b612ba4613fc2565b6001600160a01b03831660009081526019602052604090205460ff16612bf55760405162461bcd60e51b815260206004820152600660248201526521676175676560d01b6044820152606401610c68565b6000836001600160a01b03163b11612c3b5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b612c4583836146a4565b61282f8382614770565b612c57613fc2565b6001600160a01b03821660009081526019602052604090205460ff16612ca85760405162461bcd60e51b815260206004820152600660248201526521676175676560d01b6044820152606401610c68565b610bbc82826146a4565b612cba613843565b60005b8151811015610bbc57612ce8828281518110612cdb57612cdb615974565b6020026020010151614839565b80612cf2816159a0565b915050612cbd565b8051825114612d4b5760405162461bcd60e51b815260206004820152601760248201527f4272696265732f546f6b656e73206c656e67746820213d0000000000000000006044820152606401610c68565b60005b825181101561282f57828181518110612d6957612d69615974565b60200260200101516001600160a01b031663db0ea98433848481518110612d9257612d92615974565b60200260200101516040518363ffffffff1660e01b8152600401612db7929190615ad1565b600060405180830381600087803b158015612dd157600080fd5b505af1158015612de5573d6000803e3d6000fd5b505050508080612df4906159a0565b915050612d4e565b60156020528160005260406000208181548110612e1857600080fd5b6000918252602090912001546001600160a01b03169150829050565b60005b8151811015610bbc5760196000838381518110612e5657612e56615974565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff168015612ec25750601c6000838381518110612e9a57612e9a615974565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff165b15612f4657818181518110612ed957612ed9615974565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f439190615af3565b50505b80612f50816159a0565b915050612e37565b8051825114612fa95760405162461bcd60e51b815260206004820152601460248201527f4665652f546f6b656e73206c656e67746820213d0000000000000000000000006044820152606401610c68565b60005b825181101561282f57828181518110612fc757612fc7615974565b60200260200101516001600160a01b031663db0ea98433848481518110612ff057612ff0615974565b60200260200101516040518363ffffffff1660e01b8152600401613015929190615ad1565b600060405180830381600087803b15801561302f57600080fd5b505af1158015613043573d6000803e3d6000fd5b505050508080613052906159a0565b915050612fac565b613062613fc2565b6001600160a01b0382166000818152601f6020908152604091829020805460ff191685151590811790915591519182527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a9910160405180910390a25050565b6130c9613fc2565b6000816001600160a01b03163b1161310f5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6003546040516001600160a01b038084169216907fa078441d4124bc8d06fb66724c308c14f635a5a0d2bb1f422400e094b5cac40c90600090a36003546001600160a01b031680156131d45760025460405163095ea7b360e01b81526001600160a01b038381166004830152600060248301529091169063095ea7b3906044016020604051808303816000875af11580156131ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d29190615a9b565b505b6001600160a01b038181166000908152601f602052604090819020805460ff19169055600380546001600160a01b031916858416908117909155600254915163095ea7b360e01b81526004810191909152600019602482015291169063095ea7b3906044016020604051808303816000875af1158015613258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327c9190615a9b565b506003546001600160a01b03166000908152601f60205260408120805460ff191660011790556008546064116132b35760646132b7565b6008545b6008549091501561282f5761282f600082846127ad565b6132d6613843565b60005b8151811015610bbc576133048282815181106132f7576132f7615974565b602002602001015161491a565b8061330e816159a0565b9150506132d9565b61331e6139f5565b3361332881613a4e565b613331816149fb565b6133396135c0565b6133449060016159f5565b6001600160a01b039091166000908152601860205260409020556110606001605455565b613370613fc2565b6001600160a01b03821660009081526019602052604090205460ff166133c15760405162461bcd60e51b815260206004820152600660248201526521676175676560d01b6044820152606401610c68565b610bbc8282614770565b60008060006133d86139f5565b6133e28585614341565b9194509250905061189b6001605455565b6006546001600160a01b03163314806134785750600754604051634448e1eb60e01b81526001600160a01b0390911690634448e1eb90613437903390600401615b17565b602060405180830381865afa158015613454573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134789190615a9b565b61348157600080fd5b60005460ff161561349157600080fd5b60005b84518110156134c4576134b2858281518110612cdb57612cdb615974565b806134bc816159a0565b915050613494565b50600680546001600160a01b038085166001600160a01b03199283161790925560078054868416921691909117905581161561358b57600380546001600160a01b0319166001600160a01b0383811691821790925560025460405163095ea7b360e01b8152600481019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015613565573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135899190615a9b565b505b50506003546001600160a01b03166000908152601f602052604081208054600160ff1991821681179092558254161790555050565b600654604080517fd139960800000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163d13996089160048083019260209291908290030181865afa158015613623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136479190615a82565b905090565b60005b8151811015610bbc5781818151811061366a5761366a615974565b60209081029190910101516040517fc00007b00000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b039091169063c00007b090602401600060405180830381600087803b1580156136d057600080fd5b505af11580156136e4573d6000803e3d6000fd5b5050505080806136f3906159a0565b91505061364f565b613703613fc2565b6001600160a01b0381166137415760405162461bcd60e51b8152602060048201526005602482015264061646472360dc1b6044820152606401610c68565b6000816001600160a01b03163b116137875760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6006546040516001600160a01b038084169216907fe490d3138e32f1f66ef3971a3c73c7f7704ba0c1d1000f1e2c3df6fc0376610b90600090a3600680546001600160a01b0319166001600160a01b0392909216919091179055565b6060600180548060200260200160405190810160405280929190818152602001828054801561250c576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116124ee575050505050905090565b600754604051634448e1eb60e01b81526001600160a01b0390911690634448e1eb90613873903390600401615b59565b602060405180830381865afa158015613890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138b49190615a9b565b6110605760405162461bcd60e51b8152600401610c6890615b83565b6001600160a01b0381166000908152601a602052604090205460ff166139385760405162461bcd60e51b815260206004820152600360248201527f6f757400000000000000000000000000000000000000000000000000000000006044820152606401610c68565b6001600160a01b0381166000818152601a6020526040808220805460ff191690555133917fd36871fdf6981136f3ac0564927005901eda06f7a9dff1e8b2a1d7846b8ebb5091a350565b605354610100900460ff166139ed5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610c68565b611060614d14565b600260545403613a475760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c68565b6002605455565b600b546001600160a01b038216600090815260186020526040902054613a7491906159f5565b42118015613a885750613a856135c0565b42115b611bc25760405162461bcd60e51b815260206004820152600f60248201527f4552523a20564f54455f44454c415900000000000000000000000000000000006044820152606401610c68565b613add836149fb565b81516000613ae96135c0565b600080546040517f3a46b1a80000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301526024820185905293945091926101009091041690633a46b1a890604401602060405180830381865afa158015613b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b819190615a82565b90506000806000805b86811015613c2957601c6000600f60008c8581518110613bac57613bac615974565b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120549093168452830193909352910190205460ff1615613c1757878181518110613c0157613c01615974565b602002602001015184613c1491906159f5565b93505b80613c21816159a0565b915050613b8a565b5060005b86811015613f8c576000898281518110613c4957613c49615974565b6020908102919091018101516001600160a01b038082166000908152600f84526040808220549092168082526019909452205490925060ff168015613ca657506001600160a01b0381166000908152601c602052604090205460ff165b15613f7757600086888c8681518110613cc157613cc1615974565b6020026020010151613cd39190615a41565b613cdd9190615a60565b6001600160a01b03808f1660009081526014602090815260408083209388168352929052205490915015613d1057600080fd5b80600003613d4a576040517fcabeb65500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038d8116600090815260156020908152604080832080546001810182559084528284200180546001600160a01b03191694881694851790558c8352601682528083209383529290529081208054839290613dac9084906159f5565b90915550506001600160a01b03808e16600090815260146020908152604080832093871683529290529081208054839290613de89084906159f5565b90915550506001600160a01b03808316600090815260126020526040908190205490517f6e553f65000000000000000000000000000000000000000000000000000000008152600481018490528f83166024820152911690636e553f6590604401600060405180830381600087803b158015613e6357600080fd5b505af1158015613e77573d6000803e3d6000fd5b5050505060136000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b0316636e553f65828f6040518363ffffffff1660e01b8152600401613ef39291909182526001600160a01b0316602082015260400190565b600060405180830381600087803b158015613f0d57600080fd5b505af1158015613f21573d6000803e3d6000fd5b505050508085613f3191906159f5565b9450613f3d81876159f5565b60405182815290965033907f4d99b957a2bc29a30ebd96a7be8e68fe50a3c701db28a91436490b7d53870ca49060200160405180910390a2505b50508080613f84906159a0565b915050613c2d565b5060008581526017602052604081208054849290613fab9084906159f5565b9091555050505050505050505050565b6001605455565b600754604051634448e1eb60e01b81526001600160a01b0390911690634448e1eb90613ff2903390600401615b17565b602060405180830381865afa15801561400f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140339190615a9b565b6110605760405162461bcd60e51b8152600401610c6890615bad565b6040516001600160a01b038085166024830152831660448201526064810182905261203f9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614d7f565b6001600160a01b038116600090815260106020526040812054906141226135c0565b90508082101561282f5761413583614e67565b6001600160a01b0383166000908152600e6020526040902054801580159061417557506001600160a01b0384166000908152601c602052604090205460ff165b1561203f576001600160a01b038085166000908152600e60209081526040808320839055601090915290208390556003541615614294576003546040517f40c10f19000000000000000000000000000000000000000000000000000000008152306004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b15801561421157600080fd5b505af1158015614225573d6000803e3d6000fd5b505060035460405163b66503cf60e01b81526001600160a01b03918216600482015260248101859052908716925063b66503cf9150604401600060405180830381600087803b15801561427757600080fd5b505af115801561428b573d6000803e3d6000fd5b505050506142fb565b60025460405163b66503cf60e01b81526001600160a01b039182166004820152602481018390529085169063b66503cf90604401600060405180830381600087803b1580156142e257600080fd5b505af11580156142f6573d6000803e3d6000fd5b505050505b6040518181526001600160a01b0385169033907f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a350505050565b60208054604080516001600160a01b0386811660248301526044808301879052835180840390910181526064909201835293810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fdcd9e47a0000000000000000000000000000000000000000000000000000000017905290516000938493849384938493909216916143d49190615c04565b600060405180830381855af49150503d806000811461440f576040519150601f19603f3d011682016040523d82523d6000602084013e614414565b606091505b509150915060006144258383614fba565b90508080602001905181019061443b9190615c20565b604080513381526001600160a01b038085166020830152949a50929850909650828b169280881692908a16917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a45050509250925092565b6040516001600160a01b03831660248201526044810182905261282f9084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161409c565b6001600160a01b038116156145695760405163095ea7b360e01b81526001600160a01b0383811660048301526000602483015282169063095ea7b3906044016020604051808303816000875af1158015614543573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145679190615a9b565b505b6003546001600160a01b03166145f25760025460405163095ea7b360e01b81526001600160a01b03848116600483015260001960248301529091169063095ea7b3906044015b6020604051808303816000875af11580156145ce573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282f9190615a9b565b60035460405163095ea7b360e01b81526001600160a01b03848116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015614646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061466a9190615a9b565b5060025460405163095ea7b360e01b81526001600160a01b038481166004830152600060248301529091169063095ea7b3906044016145af565b6000816001600160a01b03163b116146ea5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b03828116600081815260126020908152604091829020549151600181529293858116939216917fddf0ec8cba6dad18edc75774c452fa4201ff17ec1761486329f3321936ce66d0910160405180910390a46001600160a01b03918216600090815260126020526040902080546001600160a01b03191691909216179055565b6000816001600160a01b03163b116147b65760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b03828116600081815260126020908152604080832054905192835292938581169316917fddf0ec8cba6dad18edc75774c452fa4201ff17ec1761486329f3321936ce66d0910160405180910390a46001600160a01b03918216600090815260136020526040902080546001600160a01b03191691909216179055565b6001600160a01b0381166000908152601a602052604090205460ff16156148875760405162461bcd60e51b815260206004820152600260248201526134b760f11b6044820152606401610c68565b6000816001600160a01b03163b116148cd5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b0381166000818152601a6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b0381166000908152601b602052604090205460ff16156149685760405162461bcd60e51b815260206004820152600260248201526134b760f11b6044820152606401610c68565b6000816001600160a01b03163b116149ae5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610c68565b6001600160a01b0381166000818152601b6020526040808220805460ff191660011790555133917f88e52751b2db8161caf8700d6127c81ae036b0c7bd22fdbcfeff5d7f79cdcae591a350565b6001600160a01b03811660009081526015602052604081208054909180614a206135c0565b6001600160a01b038616600090815260186020526040812054919250908210905b84811015614caa576000868281548110614a5d57614a5d615974565b60009182526020808320909101546001600160a01b038b81168452601483526040808520919092168085529252909120549091508015614c95578315614ad55760008581526016602090815260408083206001600160a01b038616845290915281208054839290614acf908490615a2a565b90915550505b6001600160a01b03808a16600090815260146020908152604080832093861683529290529081208054839290614b0c908490615a2a565b90915550506001600160a01b038281166000908152600f602090815260408083205484168352601290915290819020549051627b8a6760e11b8152600481018490528b8316602482015291169062f714ce90604401600060405180830381600087803b158015614b7b57600080fd5b505af1158015614b8f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600f602090815260408083205484168352601390915290819020549051627b8a6760e11b8152600481018490528b8316602482015291169062f714ce90604401600060405180830381600087803b158015614bfd57600080fd5b505af1158015614c11573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600f60209081526040808320549093168252601c9052205460ff1615614c5257614c4f81876159f5565b95505b604080516001600160a01b038b168152602081018390527f433fa8b9e8e2cb00bd714503252e8bfd144f0f318459a2ea8b39c1ae25361717910160405180910390a15b50508080614ca2906159a0565b915050614a41565b506001600160a01b038616600090815260186020526040902054821115614cd057600092505b60008281526017602052604081208054859290614cee908490615a2a565b90915550506001600160a01b0386166000908152601560205260408120610ead9161521b565b605354610100900460ff16613fbb5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610c68565b6000614dd4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166150749092919063ffffffff16565b9050805160001480614df5575080806020019051810190614df59190615a9b565b61282f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610c68565b6001600160a01b038082166000908152601160205260408120549091169062093a80614e916135c0565b614e9b9190615a2a565b60008181526016602090815260408083206001600160a01b03871684529091529020549091508015614f98576001600160a01b0384166000908152600d6020526040812080546009549182905591614ef38383615a2a565b90508015614f90576000670de0b6b3a7640000614f108387615a41565b614f1a9190615a60565b6001600160a01b0389166000908152601c602052604090205490915060ff1615614f71576001600160a01b0388166000908152600e602052604081208054839290614f669084906159f5565b90915550614f8e9050565b600654600254614f8e916001600160a01b0391821691168361449c565b505b50505061203f565b6009546001600160a01b0385166000908152600d602052604090205550505050565b60608215614fc9575080611be9565b6044825110156150415760405162461bcd60e51b815260206004820152602b60248201527f64656c656761746563616c6c206661696c656420776974686f7574206120726560448201527f7665727420726561736f6e0000000000000000000000000000000000000000006064820152608401610c68565b6004820191508180602001905181019061505b9190615c62565b60405162461bcd60e51b8152600401610c689190615cf6565b6060615083848460008561508b565b949350505050565b6060824710156151035760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610c68565b600080866001600160a01b0316858760405161511f9190615c04565b60006040518083038185875af1925050503d806000811461515c576040519150601f19603f3d011682016040523d82523d6000602084013e615161565b606091505b50915091506151728783838761517d565b979650505050505050565b606083156151ec5782516000036151e5576001600160a01b0385163b6151e55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c68565b5081615083565b61508383838151156152015781518083602001fd5b8060405162461bcd60e51b8152600401610c689190615cf6565b5080546000825590600052602060002090810190611bc291905b808211156152495760008155600101615235565b5090565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561528c5761528c61524d565b604052919050565b600067ffffffffffffffff8211156152ae576152ae61524d565b5060051b60200190565b6001600160a01b0381168114611bc257600080fd5b600082601f8301126152de57600080fd5b813560206152f36152ee83615294565b615263565b82815260059290921b8401810191818101908684111561531257600080fd5b8286015b84811015615336578035615329816152b8565b8352918301918301615316565b509695505050505050565b60006020828403121561535357600080fd5b813567ffffffffffffffff81111561536a57600080fd5b615083848285016152cd565b60006020828403121561538857600080fd5b8135615393816152b8565b9392505050565b600080600080600060a086880312156153b257600080fd5b85356153bd816152b8565b945060208601356153cd816152b8565b935060408601356153dd816152b8565b925060608601356153ed816152b8565b915060808601356153fd816152b8565b809150509295509295909350565b60008060006060848603121561542057600080fd5b833561542b816152b8565b9250602084013561543b816152b8565b929592945050506040919091013590565b60006020828403121561545e57600080fd5b5035919050565b6000806040838503121561547857600080fd5b823567ffffffffffffffff8082111561549057600080fd5b61549c868387016152cd565b93506020915081850135818111156154b357600080fd5b85019050601f810186136154c657600080fd5b80356154d46152ee82615294565b81815260059190911b820183019083810190888311156154f357600080fd5b928401925b82841015615511578335825292840192908401906154f8565b80955050505050509250929050565b600081518084526020808501945080840160005b838110156155595781516001600160a01b031687529582019590820190600101615534565b509495945050505050565b6060815260006155776060830186615520565b82810360208401526155898186615520565b9050828103604084015261559d8185615520565b9695505050505050565b600080604083850312156155ba57600080fd5b82356155c5816152b8565b946020939093013593505050565b600080604083850312156155e657600080fd5b82356155f1816152b8565b91506020830135615601816152b8565b809150509250929050565b600082601f83011261561d57600080fd5b8135602061562d6152ee83615294565b82815260059290921b8401810191818101908684111561564c57600080fd5b8286015b8481101561533657803567ffffffffffffffff8111156156705760008081fd5b61567e8986838b01016152cd565b845250918301918301615650565b6000806000606084860312156156a157600080fd5b833567ffffffffffffffff808211156156b957600080fd5b6156c5878388016152cd565b945060208601359150808211156156db57600080fd5b506156e88682870161560c565b925050604084013590509250925092565b60008083601f84011261570b57600080fd5b50813567ffffffffffffffff81111561572357600080fd5b6020830191508360208260051b850101111561573e57600080fd5b9250929050565b6000806000806040858703121561575b57600080fd5b843567ffffffffffffffff8082111561577357600080fd5b61577f888389016156f9565b9096509450602087013591508082111561579857600080fd5b506157a5878288016156f9565b95989497509550505050565b600080604083850312156157c457600080fd5b50508035926020909101359150565b6020815260006153936020830184615520565b6000806000606084860312156157fb57600080fd5b83359250602084013591506040840135615814816152b8565b809150509250925092565b60008060006060848603121561583457600080fd5b833561583f816152b8565b9250602084013561584f816152b8565b91506040840135615814816152b8565b6000806040838503121561587257600080fd5b823567ffffffffffffffff8082111561588a57600080fd5b615896868387016152cd565b935060208501359150808211156158ac57600080fd5b506158b98582860161560c565b9150509250929050565b8015158114611bc257600080fd5b600080604083850312156158e457600080fd5b82356158ef816152b8565b91506020830135615601816158c3565b6000806000806080858703121561591557600080fd5b843567ffffffffffffffff81111561592c57600080fd5b615938878288016152cd565b9450506020850135615949816152b8565b92506040850135615959816152b8565b91506060850135615969816152b8565b939692955090935050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016159b2576159b261598a565b5060010190565b6000602082840312156159cb57600080fd5b8151615393816152b8565b600060ff821660ff81036159ec576159ec61598a565b60010192915050565b60008219821115615a0857615a0861598a565b500190565b600060ff821680615a2057615a2061598a565b6000190192915050565b600082821015615a3c57615a3c61598a565b500390565b6000816000190483118215151615615a5b57615a5b61598a565b500290565b600082615a7d57634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215615a9457600080fd5b5051919050565b600060208284031215615aad57600080fd5b8151615393816158c3565b8281526040602082015260006150836040830184615520565b6001600160a01b03831681526040602082015260006150836040830184615520565b60008060408385031215615b0657600080fd5b505080516020909101519092909150565b604081526000615b4260408301600b81526a2b27aa22a92fa0a226a4a760a91b602082015260400190565b90506001600160a01b038316602083015292915050565b604081526000615b4260408301600a815269474f5645524e414e434560b01b602082015260400190565b602081526000611be960208301600a815269474f5645524e414e434560b01b602082015260400190565b602081526000611be960208301600b81526a2b27aa22a92fa0a226a4a760a91b602082015260400190565b60005b83811015615bf3578181015183820152602001615bdb565b8381111561203f5750506000910152565b60008251615c16818460208701615bd8565b9190910192915050565b600080600060608486031215615c3557600080fd5b8351615c40816152b8565b6020850151909350615c51816152b8565b6040850151909250615814816152b8565b600060208284031215615c7457600080fd5b815167ffffffffffffffff80821115615c8c57600080fd5b818401915084601f830112615ca057600080fd5b815181811115615cb257615cb261524d565b615cc5601f8201601f1916602001615263565b9150808252856020828501011115615cdc57600080fd5b615ced816020840160208601615bd8565b50949350505050565b6020815260008251806020840152615d15816040850160208701615bd8565b601f01601f1916919091016040019291505056fea26469706673582212201eaec667eb32deb1a1dd2f5226855fef39a099053a3eb0406fd23169d0b37f8964736f6c634300080d0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.