Contract 0x549855586afc1283e90295088ba5eb51e7236ae8 12
Contract Overview
My Name Tag:
Not Available
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x0322CEbACF1f235913bE3FCE407F9F81632ede8B The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Gauge
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "../../interface/IGauge.sol"; import "../../interface/IPair.sol"; import "../../interface/IVoter.sol"; import "../../interface/IBribe.sol"; import "../../interface/IERC721.sol"; import "../../interface/IVe.sol"; import "./MultiRewardsPoolBase.sol"; /// @title Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens contract Gauge is IGauge, MultiRewardsPoolBase { using SafeERC20 for IERC20; /// @dev The ve token used for gauges address public immutable ve; address public immutable bribe; address public immutable voter; mapping(address => uint) public tokenIds; uint public fees0; uint public fees1; event ClaimFees(address indexed from, uint claimed0, uint claimed1); event VeTokenLocked(address indexed account, uint tokenId); event VeTokenUnlocked(address indexed account, uint tokenId); constructor( address _stake, address _bribe, address _ve, address _voter, address[] memory _allowedRewardTokens ) MultiRewardsPoolBase( _stake, _voter, _allowedRewardTokens ) { bribe = _bribe; ve = _ve; voter = _voter; } function claimFees() external lock override returns (uint claimed0, uint claimed1) { return _claimFees(); } function _claimFees() internal returns (uint claimed0, uint claimed1) { address _underlying = underlying; (claimed0, claimed1) = IPair(_underlying).claimFees(); if (claimed0 > 0 || claimed1 > 0) { uint _fees0 = fees0 + claimed0; uint _fees1 = fees1 + claimed1; (address _token0, address _token1) = IPair(_underlying).tokens(); if (_fees0 > IMultiRewardsPool(bribe).left(_token0)) { fees0 = 0; IERC20(_token0).safeIncreaseAllowance(bribe, _fees0); IBribe(bribe).notifyRewardAmount(_token0, _fees0); } else { fees0 = _fees0; } if (_fees1 > IMultiRewardsPool(bribe).left(_token1)) { fees1 = 0; IERC20(_token1).safeIncreaseAllowance(bribe, _fees1); IBribe(bribe).notifyRewardAmount(_token1, _fees1); } else { fees1 = _fees1; } emit ClaimFees(msg.sender, claimed0, claimed1); } } function getReward(address account, address[] memory tokens) external override { require(msg.sender == account || msg.sender == voter, "Forbidden"); IVoter(voter).distribute(address(this)); _getReward(account, tokens, account); } function depositAll(uint tokenId) external { deposit(IERC20(underlying).balanceOf(msg.sender), tokenId); } function deposit(uint amount, uint tokenId) public { if (tokenId > 0) { _lockVeToken(msg.sender, tokenId); } _deposit(amount); IVoter(voter).emitDeposit(tokenId, msg.sender, amount); } function withdrawAll() external { withdraw(balanceOf[msg.sender]); } function withdraw(uint amount) public { uint tokenId = 0; if (amount == balanceOf[msg.sender]) { tokenId = tokenIds[msg.sender]; } withdrawToken(amount, tokenId); IVoter(voter).emitWithdraw(tokenId, msg.sender, amount); } function withdrawToken(uint amount, uint tokenId) public { if (tokenId > 0) { _unlockVeToken(msg.sender, tokenId); } _withdraw(amount); } /// @dev Balance should be recalculated after the lock /// For locking a new ve token withdraw all funds and deposit again function _lockVeToken(address account, uint tokenId) internal { require(IERC721(ve).ownerOf(tokenId) == account, "Not ve token owner"); if (tokenIds[account] == 0) { tokenIds[account] = tokenId; IVoter(voter).attachTokenToGauge(tokenId, account); } require(tokenIds[account] == tokenId, "Wrong token"); emit VeTokenLocked(account, tokenId); } /// @dev Balance should be recalculated after the unlock function _unlockVeToken(address account, uint tokenId) internal { require(tokenId == tokenIds[account], "Wrong token"); tokenIds[account] = 0; IVoter(voter).detachTokenFromGauge(tokenId, account); emit VeTokenUnlocked(account, tokenId); } /// @dev Similar to Curve https://resources.curve.fi/reward-gauges/boosting-your-crv-rewards#formula function _derivedBalance(address account) internal override view returns (uint) { uint _tokenId = tokenIds[account]; uint _balance = balanceOf[account]; uint _derived = _balance * 40 / 100; uint _adjusted = 0; uint _supply = IERC20(ve).totalSupply(); if (account == IERC721(ve).ownerOf(_tokenId) && _supply > 0) { _adjusted = (totalSupply * IVe(ve).balanceOfNFT(_tokenId) / _supply) * 60 / 100; } return Math.min((_derived + _adjusted), _balance); } function notifyRewardAmount(address token, uint amount) external { // claim rewards should not ruin distribution process try Gauge(address(this)).claimFees() {} catch {} _notifyRewardAmount(token, amount); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IGauge { function notifyRewardAmount(address token, uint amount) external; function getReward(address account, address[] memory tokens) external; function claimFees() external returns (uint claimed0, uint claimed1); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IPair { // Structure to capture time period obervations every 30 minutes, used for local oracles struct Observation { uint timestamp; uint reserve0Cumulative; uint reserve1Cumulative; } 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 (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast); function getAmountOut(uint, address) external view returns (uint); 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 stable() external view returns (bool); function metadata() external view returns ( uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1 ); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IVoter { function ve() external view returns (address); function attachTokenToGauge(uint _tokenId, address account) external; function detachTokenFromGauge(uint _tokenId, address account) external; function emitDeposit(uint _tokenId, address account, uint amount) external; function emitWithdraw(uint _tokenId, address account, uint amount) external; function distribute(address _gauge) external; function notifyRewardAmount(uint amount) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IBribe { function notifyRewardAmount(address token, uint amount) external; function _deposit(uint amount, uint tokenId) external; function _withdraw(uint amount, uint tokenId) external; function getRewardForOwner(uint tokenId, address[] memory tokens) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "./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`, 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 be 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: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * 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 Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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 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); /** * @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; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IVe { enum DepositType { DEPOSIT_FOR_TYPE, CREATE_LOCK_TYPE, INCREASE_LOCK_AMOUNT, INCREASE_UNLOCK_TIME, MERGE_TYPE } struct Point { int128 bias; int128 slope; // # -dweight / dt uint ts; uint blk; // block } /* We cannot really do block numbers per se b/c slope is per time, not per block * and per block could be fairly bad b/c Ethereum changes blocktimes. * What we can do is to extrapolate ***At functions */ struct LockedBalance { int128 amount; uint end; } function token() external view returns (address); function balanceOfNFT(uint) external view returns (uint); function isApprovedOrOwner(address, uint) external view returns (bool); function createLockFor(uint, uint, address) external returns (uint); function userPointEpoch(uint tokenId) external view returns (uint); function epoch() external view returns (uint); function userPointHistory(uint tokenId, uint loc) external view returns (Point memory); function pointHistory(uint loc) external view returns (Point memory); function checkpoint() external; function depositFor(uint tokenId, uint value) external; function attachToken(uint tokenId) external; function detachToken(uint tokenId) external; function voting(uint tokenId) external; function abstain(uint tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "../../interface/IERC20.sol"; import "../../interface/IMultiRewardsPool.sol"; import "../../lib/Math.sol"; import "../../lib/SafeERC20.sol"; import "../../lib/CheckpointLib.sol"; import "../Reentrancy.sol"; abstract contract MultiRewardsPoolBase is Reentrancy, IMultiRewardsPool { using SafeERC20 for IERC20; using CheckpointLib for mapping(uint => CheckpointLib.Checkpoint); /// @dev Operator can add/remove reward tokens address public operator; /// @dev The LP token that needs to be staked for rewards address public immutable override underlying; uint public override derivedSupply; mapping(address => uint) public override derivedBalances; /// @dev Rewards are released over 7 days uint internal constant DURATION = 7 days; uint internal constant PRECISION = 10 ** 18; uint internal constant MAX_REWARD_TOKENS = 10; /// Default snx staking contract implementation /// https://github.com/Synthetixio/synthetix/blob/develop/contracts/StakingRewards.sol /// @dev Reward rate with precision 1e18 mapping(address => uint) public rewardRate; mapping(address => uint) public periodFinish; mapping(address => uint) public lastUpdateTime; mapping(address => uint) public rewardPerTokenStored; mapping(address => mapping(address => uint)) public lastEarn; mapping(address => mapping(address => uint)) public userRewardPerTokenStored; uint public override totalSupply; mapping(address => uint) public override balanceOf; address[] public override rewardTokens; mapping(address => bool) public override isRewardToken; /// @notice A record of balance checkpoints for each account, by index mapping(address => mapping(uint => CheckpointLib.Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account mapping(address => uint) public numCheckpoints; /// @notice A record of balance checkpoints for each token, by index mapping(uint => CheckpointLib.Checkpoint) public supplyCheckpoints; /// @notice The number of checkpoints uint public supplyNumCheckpoints; /// @notice A record of balance checkpoints for each token, by index mapping(address => mapping(uint => CheckpointLib.Checkpoint)) public rewardPerTokenCheckpoints; /// @notice The number of checkpoints for each token mapping(address => uint) public rewardPerTokenNumCheckpoints; event Deposit(address indexed from, uint amount); event Withdraw(address indexed from, uint amount); event NotifyReward(address indexed from, address indexed reward, uint amount); event ClaimRewards(address indexed from, address indexed reward, uint amount, address recepient); constructor(address _stake, address _operator, address[] memory _allowedRewardTokens) { underlying = _stake; operator = _operator; for (uint i; i < _allowedRewardTokens.length; i++) { if (_allowedRewardTokens[i] != address(0)) { _registerRewardToken(_allowedRewardTokens[i]); } } } modifier onlyOperator() { require(msg.sender == operator, "Not operator"); _; } //************************************************************************** //************************ VIEWS ******************************************* //************************************************************************** function rewardTokensLength() external view override returns (uint) { return rewardTokens.length; } function rewardPerToken(address token) external view returns (uint) { return _rewardPerToken(token); } function _rewardPerToken(address token) internal view returns (uint) { if (derivedSupply == 0) { return rewardPerTokenStored[token]; } return rewardPerTokenStored[token] + ( (_lastTimeRewardApplicable(token) - Math.min(lastUpdateTime[token], periodFinish[token])) * rewardRate[token] / derivedSupply ); } function derivedBalance(address account) external view override returns (uint) { return _derivedBalance(account); } function left(address token) external view override returns (uint) { if (block.timestamp >= periodFinish[token]) return 0; uint _remaining = periodFinish[token] - block.timestamp; return _remaining * rewardRate[token] / PRECISION; } function earned(address token, address account) external view override returns (uint) { return _earned(token, account); } //************************************************************************** //************************ OPERATOR ACTIONS ******************************** //************************************************************************** function registerRewardToken(address token) external onlyOperator { _registerRewardToken(token); } function _registerRewardToken(address token) internal { require(rewardTokens.length < MAX_REWARD_TOKENS, "Too many reward tokens"); require(!isRewardToken[token], "Already registered"); isRewardToken[token] = true; rewardTokens.push(token); } function removeRewardToken(address token) external onlyOperator { require(periodFinish[token] < block.timestamp, "Rewards not ended"); require(isRewardToken[token], "Not reward token"); isRewardToken[token] = false; uint length = rewardTokens.length; require(length > 3, "First 3 tokens should not be removed"); // keep 3 tokens as guarantee against malicious actions // assume it will be LIZARD + pool tokens uint i = 3; bool found = false; for (; i < length; i++) { address t = rewardTokens[i]; if (t == token) { found = true; break; } } require(found, "First tokens forbidden to remove"); rewardTokens[i] = rewardTokens[length - 1]; rewardTokens.pop(); } //************************************************************************** //************************ USER ACTIONS ************************************ //************************************************************************** function _deposit(uint amount) internal virtual lock { require(amount > 0, "Zero amount"); _increaseBalance(msg.sender, amount); IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount); emit Deposit(msg.sender, amount); } function _increaseBalance(address account, uint amount) internal virtual { _updateRewardForAllTokens(); totalSupply += amount; balanceOf[account] += amount; _updateDerivedBalanceAndWriteCheckpoints(account); } function _withdraw(uint amount) internal lock virtual { _decreaseBalance(msg.sender, amount); IERC20(underlying).safeTransfer(msg.sender, amount); emit Withdraw(msg.sender, amount); } function _decreaseBalance(address account, uint amount) internal virtual { _updateRewardForAllTokens(); totalSupply -= amount; balanceOf[account] -= amount; _updateDerivedBalanceAndWriteCheckpoints(account); } /// @dev Implement restriction checks! function _getReward(address account, address[] memory tokens, address recipient) internal lock virtual { for (uint i = 0; i < tokens.length; i++) { (rewardPerTokenStored[tokens[i]], lastUpdateTime[tokens[i]]) = _updateRewardPerToken(tokens[i], type(uint).max, true); uint _reward = _earned(tokens[i], account); lastEarn[tokens[i]][account] = block.timestamp; userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[tokens[i]]; if (_reward > 0) { IERC20(tokens[i]).safeTransfer(recipient, _reward); } emit ClaimRewards(msg.sender, tokens[i], _reward, recipient); } _updateDerivedBalanceAndWriteCheckpoints(account); } function _updateDerivedBalanceAndWriteCheckpoints(address account) internal { uint __derivedBalance = derivedBalances[account]; derivedSupply -= __derivedBalance; __derivedBalance = _derivedBalance(account); derivedBalances[account] = __derivedBalance; derivedSupply += __derivedBalance; _writeCheckpoint(account, __derivedBalance); _writeSupplyCheckpoint(); } //************************************************************************** //************************ REWARDS CALCULATIONS **************************** //************************************************************************** // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run function _earned(address token, address account) internal view returns (uint) { // zero checkpoints means zero deposits if (numCheckpoints[account] == 0) { return 0; } // last claim rewards time uint _startTimestamp = Math.max(lastEarn[token][account], rewardPerTokenCheckpoints[token][0].timestamp); // find an index of the balance that the user had on the last claim uint _startIndex = _getPriorBalanceIndex(account, _startTimestamp); uint _endIndex = numCheckpoints[account] - 1; uint reward = 0; // calculate previous snapshots if exist if (_endIndex > 0) { for (uint i = _startIndex; i <= _endIndex - 1; i++) { CheckpointLib.Checkpoint memory cp0 = checkpoints[account][i]; CheckpointLib.Checkpoint memory cp1 = checkpoints[account][i + 1]; (uint _rewardPerTokenStored0,) = _getPriorRewardPerToken(token, cp0.timestamp); (uint _rewardPerTokenStored1,) = _getPriorRewardPerToken(token, cp1.timestamp); reward += cp0.value * (_rewardPerTokenStored1 - _rewardPerTokenStored0) / PRECISION; } } CheckpointLib.Checkpoint memory cp = checkpoints[account][_endIndex]; (uint _rewardPerTokenStored,) = _getPriorRewardPerToken(token, cp.timestamp); reward += cp.value * (_rewardPerToken(token) - Math.max(_rewardPerTokenStored, userRewardPerTokenStored[token][account])) / PRECISION; return reward; } function _derivedBalance(address account) internal virtual view returns (uint) { // supposed to be implemented in a parent contract return balanceOf[account]; } /// @dev Update stored rewardPerToken values without the last one snapshot /// If the contract will get "out of gas" error on users actions this will be helpful function batchUpdateRewardPerToken(address token, uint maxRuns) external { (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, maxRuns, false); } function _updateRewardForAllTokens() internal { uint length = rewardTokens.length; for (uint i; i < length; i++) { address token = rewardTokens[i]; (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true); } } /// @dev Should be called only with properly updated snapshots, or with actualLast=false function _updateRewardPerToken(address token, uint maxRuns, bool actualLast) internal returns (uint, uint) { uint _startTimestamp = lastUpdateTime[token]; uint reward = rewardPerTokenStored[token]; if (supplyNumCheckpoints == 0) { return (reward, _startTimestamp); } if (rewardRate[token] == 0) { return (reward, block.timestamp); } uint _startIndex = _getPriorSupplyIndex(_startTimestamp); uint _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns); if (_endIndex > 0) { for (uint i = _startIndex; i <= _endIndex - 1; i++) { CheckpointLib.Checkpoint memory sp0 = supplyCheckpoints[i]; if (sp0.value > 0) { CheckpointLib.Checkpoint memory sp1 = supplyCheckpoints[i + 1]; (uint _reward, uint _endTime) = _calcRewardPerToken( token, sp1.timestamp, sp0.timestamp, sp0.value, _startTimestamp ); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, _endTime); _startTimestamp = _endTime; } } } // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions if (actualLast) { CheckpointLib.Checkpoint memory sp = supplyCheckpoints[_endIndex]; if (sp.value > 0) { (uint _reward,) = _calcRewardPerToken(token, _lastTimeRewardApplicable(token), Math.max(sp.timestamp, _startTimestamp), sp.value, _startTimestamp); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, block.timestamp); _startTimestamp = block.timestamp; } } return (reward, _startTimestamp); } function _calcRewardPerToken( address token, uint lastSupplyTs1, uint lastSupplyTs0, uint supply, uint startTimestamp ) internal view returns (uint, uint) { uint endTime = Math.max(lastSupplyTs1, startTimestamp); uint _periodFinish = periodFinish[token]; return ( (Math.min(endTime, _periodFinish) - Math.min(Math.max(lastSupplyTs0, startTimestamp), _periodFinish)) * rewardRate[token] / supply , endTime); } /// @dev Returns the last time the reward was modified or periodFinish if the reward has ended function _lastTimeRewardApplicable(address token) internal view returns (uint) { return Math.min(block.timestamp, periodFinish[token]); } //************************************************************************** //************************ NOTIFY ****************************************** //************************************************************************** function _notifyRewardAmount(address token, uint amount) internal lock virtual { require(token != underlying, "Wrong token for rewards"); require(amount > 0, "Zero amount"); require(isRewardToken[token], "Token not allowed"); if (rewardRate[token] == 0) { _writeRewardPerTokenCheckpoint(token, 0, block.timestamp); } (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true); if (block.timestamp >= periodFinish[token]) { IERC20(token).safeTransferFrom(msg.sender, address(this), amount); rewardRate[token] = amount * PRECISION / DURATION; } else { uint _remaining = periodFinish[token] - block.timestamp; uint _left = _remaining * rewardRate[token]; // not sure what the reason was in the original solidly implementation for this restriction // however, by design probably it is a good idea against human errors require(amount > _left / PRECISION, "Amount should be higher than remaining rewards"); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); rewardRate[token] = (amount * PRECISION + _left) / DURATION; } periodFinish[token] = block.timestamp + DURATION; emit NotifyReward(msg.sender, token, amount); } //************************************************************************** //************************ CHECKPOINTS ************************************* //************************************************************************** function getPriorBalanceIndex(address account, uint timestamp) external view returns (uint) { return _getPriorBalanceIndex(account, timestamp); } /// @notice Determine the prior balance for an account as of a block number /// @dev Block number must be a finalized block or else this function will revert to prevent misinformation. /// @param account The address of the account to check /// @param timestamp The timestamp to get the balance at /// @return The balance the account had as of the given block function _getPriorBalanceIndex(address account, uint timestamp) internal view returns (uint) { uint nCheckpoints = numCheckpoints[account]; if (nCheckpoints == 0) { return 0; } return checkpoints[account].findLowerIndex(nCheckpoints, timestamp); } function getPriorSupplyIndex(uint timestamp) external view returns (uint) { return _getPriorSupplyIndex(timestamp); } function _getPriorSupplyIndex(uint timestamp) internal view returns (uint) { uint nCheckpoints = supplyNumCheckpoints; if (nCheckpoints == 0) { return 0; } return supplyCheckpoints.findLowerIndex(nCheckpoints, timestamp); } function getPriorRewardPerToken(address token, uint timestamp) external view returns (uint, uint) { return _getPriorRewardPerToken(token, timestamp); } function _getPriorRewardPerToken(address token, uint timestamp) internal view returns (uint, uint) { uint nCheckpoints = rewardPerTokenNumCheckpoints[token]; if (nCheckpoints == 0) { return (0, 0); } mapping(uint => CheckpointLib.Checkpoint) storage cps = rewardPerTokenCheckpoints[token]; uint lower = cps.findLowerIndex(nCheckpoints, timestamp); CheckpointLib.Checkpoint memory cp = cps[lower]; return (cp.value, cp.timestamp); } function _writeCheckpoint(address account, uint balance) internal { uint _timestamp = block.timestamp; uint _nCheckPoints = numCheckpoints[account]; if (_nCheckPoints > 0 && checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp) { checkpoints[account][_nCheckPoints - 1].value = balance; } else { checkpoints[account][_nCheckPoints] = CheckpointLib.Checkpoint(_timestamp, balance); numCheckpoints[account] = _nCheckPoints + 1; } } function _writeRewardPerTokenCheckpoint(address token, uint reward, uint timestamp) internal { uint _nCheckPoints = rewardPerTokenNumCheckpoints[token]; if (_nCheckPoints > 0 && rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == timestamp) { rewardPerTokenCheckpoints[token][_nCheckPoints - 1].value = reward; } else { rewardPerTokenCheckpoints[token][_nCheckPoints] = CheckpointLib.Checkpoint(timestamp, reward); rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1; } } function _writeSupplyCheckpoint() internal { uint _nCheckPoints = supplyNumCheckpoints; uint _timestamp = block.timestamp; if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) { supplyCheckpoints[_nCheckPoints - 1].value = derivedSupply; } else { supplyCheckpoints[_nCheckPoints] = CheckpointLib.Checkpoint(_timestamp, derivedSupply); supplyNumCheckpoints = _nCheckPoints + 1; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; /** * @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 pragma solidity 0.8.15; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount ) external returns (bool); /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IMultiRewardsPool { function underlying() external view returns (address); function derivedSupply() external view returns (uint); function derivedBalances(address account) external view returns (uint); function totalSupply() external view returns (uint); function balanceOf(address account) external view returns (uint); function rewardTokens(uint id) external view returns (address); function isRewardToken(address token) external view returns (bool); function rewardTokensLength() external view returns (uint); function derivedBalance(address account) external view returns (uint); function left(address token) external view returns (uint); function earned(address token, address account) external view returns (uint); function registerRewardToken(address token) external; function removeRewardToken(address token) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; library Math { function max(uint a, uint b) internal pure returns (uint) { return a >= b ? a : b; } function min(uint a, uint b) internal pure returns (uint) { return a < b ? a : b; } function positiveInt128(int128 value) internal pure returns (int128) { return value < 0 ? int128(0) : value; } function closeTo(uint a, uint b, uint target) internal pure returns (bool) { if (a > b) { if (a - b <= target) { return true; } } else { if (b - a <= target) { return true; } } return false; } function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity 0.8.15; import "../interface/IERC20.sol"; import "./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; function safeTransfer( IERC20 token, address to, uint value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint value ) internal { uint newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @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"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; library CheckpointLib { /// @notice A checkpoint for uint value struct Checkpoint { uint timestamp; uint value; } function findLowerIndex(mapping(uint => Checkpoint) storage checkpoints, uint size, uint timestamp) internal view returns (uint) { require(size != 0, "Empty checkpoints"); // First check most recent value if (checkpoints[size - 1].timestamp <= timestamp) { return (size - 1); } // Next check implicit zero value if (checkpoints[0].timestamp > timestamp) { return 0; } uint lower = 0; uint upper = size - 1; while (upper > lower) { // ceil, avoiding overflow uint center = upper - (upper - lower) / 2; Checkpoint memory cp = checkpoints[center]; if (cp.timestamp == timestamp) { return center; } else if (cp.timestamp < timestamp) { lower = center; } else { upper = center - 1; } } return lower; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; abstract contract Reentrancy { /// @dev simple re-entrancy check uint internal _unlocked = 1; modifier lock() { require(_unlocked == 1, "Reentrant call"); _unlocked = 2; _; _unlocked = 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity 0.8.15; /** * @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 * ==== * * [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; } function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_stake","type":"address"},{"internalType":"address","name":"_bribe","type":"address"},{"internalType":"address","name":"_ve","type":"address"},{"internalType":"address","name":"_voter","type":"address"},{"internalType":"address[]","name":"_allowedRewardTokens","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimed0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimed1","type":"uint256"}],"name":"ClaimFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recepient","type":"address"}],"name":"ClaimRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","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":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"VeTokenLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"VeTokenUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"maxRuns","type":"uint256"}],"name":"batchUpdateRewardPerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bribe","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"checkpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[{"internalType":"uint256","name":"claimed0","type":"uint256"},{"internalType":"uint256","name":"claimed1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"derivedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"derivedBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"derivedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorBalanceIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorRewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorSupplyIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isRewardToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"lastEarn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"left","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"registerRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardPerTokenCheckpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardPerTokenNumCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardTokensLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supplyCheckpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyNumCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061027f5760003560e01c80637bb7bed11161015c578063d294f093116100ce578063e8111a1211610087578063e8111a12146106a8578063f1229777146106b1578063f7412baf146106c4578063fc97a303146106eb578063fd3140981461070b578063fdb483c71461071e57600080fd5b8063d294f0931461063e578063d35e254414610646578063d7da4bb014610659578063da09d19d14610662578063e2bbb15814610682578063e46dbc981461069557600080fd5b8063a495e5b511610120578063a495e5b514610592578063aa479652146105bd578063b5fd73f8146105dd578063b66503cf14610610578063bf199e6214610623578063c6f678bd1461062b57600080fd5b80637bb7bed11461053b578063853828b61461054e57806393f1c4421461055657806399bcc0521461055f5780639ce43f901461057257600080fd5b80633ca068b6116101f557806363fb415b116101b957806363fb415b1461048e57806368fcee1a146104ae5780636f307dc3146104c15780636fcfff45146104e857806370a082311461050857806376f4be361461052857600080fd5b80633ca068b61461040d5780633d509c971461043857806346c96aac1461044b5780634c02a21c14610472578063570ca7351461047b57600080fd5b8063211dc32d11610247578063211dc32d1461036b578063221ca18c1461037e5780632ce9aead1461039e5780632e1a7d4d146103be57806331279d3d146103d357806337d0208c146103e657600080fd5b806301316ddf146102845780630cdfebfa146102d0578063115c6f391461030257806318160ddd146103235780631f8507161461032c575b600080fd5b6102b66102923660046131db565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b6102b66102de3660046131db565b600e6020908152600092835260408084209091529082529020805460019091015482565b6103156103103660046131db565b610731565b6040519081526020016102c7565b610315600a5481565b6103537f00000000000000000000000029d3622c78615a1e7459e4be434d816b7de293e481565b6040516001600160a01b0390911681526020016102c7565b610315610379366004613207565b610746565b61031561038c366004613240565b60046020526000908152604090205481565b6103156103ac366004613240565b60066020526000908152604090205481565b6103d16103cc36600461325d565b610752565b005b6103d16103e136600461328c565b610810565b6103537f000000000000000000000000bc5d11490dacecde548f6d145b66b1f8cec0959981565b61031561041b366004613207565b600960209081526000928352604080842090915290825290205481565b6103d1610446366004613240565b610914565b6103537f00000000000000000000000098a1de08715800801e9764349f5a71cbe63f99cc81565b61031560165481565b600154610353906001600160a01b031681565b61031561049c366004613240565b60036020526000908152604090205481565b6103d16104bc3660046131db565b610bef565b6103537f000000000000000000000000751f3b8ca139bc1f3482b193297485f14208826a81565b6103156104f6366004613240565b600f6020526000908152604090205481565b610315610516366004613240565b600b6020526000908152604090205481565b61031561053636600461325d565b610c29565b61035361054936600461325d565b610c34565b6103d1610c5e565b61031560155481565b61031561056d366004613240565b610c79565b610315610580366004613240565b60076020526000908152604090205481565b6103156105a0366004613207565b600860209081526000928352604080842090915290825290205481565b6103156105cb366004613240565b60136020526000908152604090205481565b6106006105eb366004613240565b600d6020526000908152604090205460ff1681565b60405190151581526020016102c7565b6103d161061e3660046131db565b610d05565b600c54610315565b6103d161063936600461325d565b610d72565b6102b6610e07565b610315610654366004613240565b610e46565b61031560025481565b610315610670366004613240565b60056020526000908152604090205481565b6103d1610690366004613366565b610e51565b6103d16106a3366004613240565b610ec4565b61031560115481565b6103156106bf366004613240565b610f16565b6102b66106d236600461325d565b6010602052600090815260409020805460019091015482565b6103156106f9366004613240565b60146020526000908152604090205481565b6102b66107193660046131db565b610f21565b6103d161072c366004613366565b610f3a565b600061073d8383610f53565b90505b92915050565b600061073d8383610fa8565b336000908152600b6020526040812054820361077a5750336000908152601460205260409020545b6107848282610f3a565b604051633aa53b9160e21b815260048101829052336024820152604481018390527f00000000000000000000000098a1de08715800801e9764349f5a71cbe63f99cc6001600160a01b03169063ea94ee44906064015b600060405180830381600087803b1580156107f457600080fd5b505af1158015610808573d6000803e3d6000fd5b505050505050565b336001600160a01b038316148061084f5750336001600160a01b037f00000000000000000000000098a1de08715800801e9764349f5a71cbe63f99cc16145b61088c5760405162461bcd60e51b81526020600482015260096024820152682337b93134b23232b760b91b60448201526064015b60405180910390fd5b6040516363453ae160e01b81523060048201527f00000000000000000000000098a1de08715800801e9764349f5a71cbe63f99cc6001600160a01b0316906363453ae190602401600060405180830381600087803b1580156108ed57600080fd5b505af1158015610901573d6000803e3d6000fd5b50505050610910828284611229565b5050565b6001546001600160a01b0316331461095d5760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b6044820152606401610883565b6001600160a01b03811660009081526005602052604090205442116109b85760405162461bcd60e51b815260206004820152601160248201527014995dd85c991cc81b9bdd08195b991959607a1b6044820152606401610883565b6001600160a01b0381166000908152600d602052604090205460ff16610a135760405162461bcd60e51b815260206004820152601060248201526f2737ba103932bbb0b932103a37b5b2b760811b6044820152606401610883565b6001600160a01b0381166000908152600d60205260409020805460ff19169055600c5460038111610a925760405162461bcd60e51b8152602060048201526024808201527f4669727374203320746f6b656e732073686f756c64206e6f742062652072656d6044820152631bdd995960e21b6064820152608401610883565b600360005b82821015610af2576000600c8381548110610ab457610ab4613388565b6000918252602090912001546001600160a01b03908116915085168103610adf576001915050610af2565b5081610aea816133b4565b925050610a97565b80610b3f5760405162461bcd60e51b815260206004820181905260248201527f466972737420746f6b656e7320666f7262696464656e20746f2072656d6f76656044820152606401610883565b600c610b4c6001856133cd565b81548110610b5c57610b5c613388565b600091825260209091200154600c80546001600160a01b039092169184908110610b8857610b88613388565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600c805480610bc757610bc76133e4565b600082815260209020810160001990810180546001600160a01b031916905501905550505050565b610bfb82826000611502565b6001600160a01b03909316600090815260076020908152604080832060069092529091209390935590915550565b6000610740826116f2565b600c8181548110610c4457600080fd5b6000918252602090912001546001600160a01b0316905081565b336000908152600b6020526040902054610c7790610752565b565b6001600160a01b0381166000908152600560205260408120544210610ca057506000919050565b6001600160a01b038216600090815260056020526040812054610cc49042906133cd565b6001600160a01b038416600090815260046020526040902054909150670de0b6b3a764000090610cf490836133fa565b610cfe9190613419565b9392505050565b306001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1925050508015610d60575060408051601f3d908101601f19168201909252610d5d9181019061343b565b60015b15610d685750505b6109108282611714565b6040516370a0823160e01b8152336004820152610e04907f000000000000000000000000751f3b8ca139bc1f3482b193297485f14208826a6001600160a01b0316906370a0823190602401602060405180830381865afa158015610dda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfe919061345f565b82610e51565b50565b600080600054600114610e2c5760405162461bcd60e51b815260040161088390613478565b6002600055610e39611aa2565b9150915060016000559091565b600061074082611ec8565b8015610e6157610e613382612117565b610e6a8261234f565b60405163530e389d60e11b815260048101829052336024820152604481018390527f00000000000000000000000098a1de08715800801e9764349f5a71cbe63f99cc6001600160a01b03169063a61c713a906064016107da565b6001546001600160a01b03163314610f0d5760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b6044820152606401610883565b610e048161242e565b60006107408261253d565b600080610f2e84846125e8565b915091505b9250929050565b8015610f4a57610f4a3382612672565b6109108261279a565b6001600160a01b0382166000908152600f6020526040812054808203610f7d576000915050610740565b6001600160a01b0384166000908152600e60205260409020610fa0908285612831565b949350505050565b6001600160a01b0381166000908152600f60205260408120548103610fcf57506000610740565b6001600160a01b038084166000818152600860209081526040808320948716835293815283822054928252601281528382208280529052918220546110149190612977565b905060006110228483610f53565b6001600160a01b0385166000908152600f60205260408120549192509061104b906001906133cd565b90506000811561115d57825b6110626001846133cd565b811161115b576001600160a01b0387166000818152600e6020818152604080842086855280835281852082518084019093528054835260019081015483850152958552929091529282906110b79086906134a0565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050905060006110f68b84600001516125e8565b50905060006111098c84600001516125e8565b509050670de0b6b3a764000061111f83836133cd565b856020015161112e91906133fa565b6111389190613419565b61114290876134a0565b9550505050508080611153906133b4565b915050611057565b505b6001600160a01b0386166000908152600e602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906111a7908a906125e8565b506001600160a01b03808b166000908152600960209081526040808320938d1683529290522054909150670de0b6b3a7640000906111e6908390612977565b6111ef8b61253d565b6111f991906133cd565b836020015161120891906133fa565b6112129190613419565b61121c90846134a0565b9998505050505050505050565b60005460011461124b5760405162461bcd60e51b815260040161088390613478565b600260009081555b82518110156114ee5761128383828151811061127157611271613388565b60200260200101516000196001611502565b6007600086858151811061129957611299613388565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000600660008887815181106112d9576112d9613388565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000849190505583919050555050600061133484838151811061132657611326613388565b602002602001015186610fa8565b9050426008600086858151811061134d5761134d613388565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000876001600160a01b03166001600160a01b0316815260200190815260200160002081905550600760008584815181106113b2576113b2613388565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054600960008685815181106113f1576113f1613388565b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120938a168152929052902055801561146357611463838286858151811061144357611443613388565b60200260200101516001600160a01b031661298e9092919063ffffffff16565b83828151811061147557611475613388565b60200260200101516001600160a01b0316336001600160a01b03167fe4394b3c25e336e9d6b7fcefab7e3234f1c6b373f13655dc3920664b080b098d83866040516114d39291909182526001600160a01b0316602082015260400190565b60405180910390a350806114e6816133b4565b915050611253565b506114f8836129f6565b5050600160005550565b6001600160a01b038316600090815260066020908152604080832054600790925282205460115483929190830361153c57925090506116ea565b6001600160a01b03871660009081526004602052604081205490036115675792504291506116ea9050565b6000611572836116f2565b9050600061158e600160115461158891906133cd565b89612a7b565b9050801561166757815b6115a36001836133cd565b81116116655760008181526010602090815260409182902082518084019093528054835260010154908201819052156116525760006010816115e68560016134a0565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806116318e8460000151866000015187602001518d612a8a565b909250905061164082896134a0565b975061164d8e8983612b0e565b975050505b508061165d816133b4565b915050611598565b505b86156116e15760008181526010602090815260409182902082518084019093528054835260010154908201819052156116df5760006116c08b6116a98d612c17565b84516116b5908a612977565b85602001518a612a8a565b5090506116cd81866134a0565b94506116da8b8642612b0e565b429550505b505b50909350909150505b935093915050565b6011546000908082036117085750600092915050565b610cfe60108285612831565b6000546001146117365760405162461bcd60e51b815260040161088390613478565b60026000556001600160a01b037f000000000000000000000000751f3b8ca139bc1f3482b193297485f14208826a8116908316036117b65760405162461bcd60e51b815260206004820152601760248201527f57726f6e6720746f6b656e20666f7220726577617264730000000000000000006044820152606401610883565b600081116117f45760405162461bcd60e51b815260206004820152600b60248201526a16995c9bc8185b5bdd5b9d60aa1b6044820152606401610883565b6001600160a01b0382166000908152600d602052604090205460ff166118505760405162461bcd60e51b8152602060048201526011602482015270151bdad95b881b9bdd08185b1b1bddd959607a1b6044820152606401610883565b6001600160a01b038216600090815260046020526040812054900361187b5761187b82600042612b0e565b611889826000196001611502565b6001600160a01b0384166000908152600760209081526040808320600683528184209490945593909255600590915220544210611913576118d56001600160a01b038316333084612c3b565b62093a806118eb670de0b6b3a7640000836133fa565b6118f59190613419565b6001600160a01b038316600090815260046020526040902055611a33565b6001600160a01b0382166000908152600560205260408120546119379042906133cd565b6001600160a01b0384166000908152600460205260408120549192509061195e90836133fa565b9050611972670de0b6b3a764000082613419565b83116119d75760405162461bcd60e51b815260206004820152602e60248201527f416d6f756e742073686f756c6420626520686967686572207468616e2072656d60448201526d61696e696e67207265776172647360901b6064820152608401610883565b6119ec6001600160a01b038516333086612c3b565b62093a8081611a03670de0b6b3a7640000866133fa565b611a0d91906134a0565b611a179190613419565b6001600160a01b03851660009081526004602052604090205550505b611a4062093a80426134a0565b6001600160a01b0383166000818152600560205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf5082690611a919085815260200190565b60405180910390a350506001600055565b60008060007f000000000000000000000000751f3b8ca139bc1f3482b193297485f14208826a9050806001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015611b09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2d919061343b565b909350915082151580611b405750600082115b15611ec357600083601554611b5591906134a0565b9050600083601654611b6791906134a0565b9050600080846001600160a01b0316639d63848a6040518163ffffffff1660e01b81526004016040805180830381865afa158015611ba9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcd91906134b8565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f000000000000000000000000bc5d11490dacecde548f6d145b66b1f8cec09599909116906399bcc05290602401602060405180830381865afa158015611c3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5f919061345f565b841115611d26576000601555611c9f6001600160a01b0383167f000000000000000000000000bc5d11490dacecde548f6d145b66b1f8cec0959986612c73565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f000000000000000000000000bc5d11490dacecde548f6d145b66b1f8cec09599169063b66503cf90604401600060405180830381600087803b158015611d0957600080fd5b505af1158015611d1d573d6000803e3d6000fd5b50505050611d2c565b60158490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000bc5d11490dacecde548f6d145b66b1f8cec0959916906399bcc05290602401602060405180830381865afa158015611d92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db6919061345f565b831115611e7d576000601655611df66001600160a01b0382167f000000000000000000000000bc5d11490dacecde548f6d145b66b1f8cec0959985612c73565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f000000000000000000000000bc5d11490dacecde548f6d145b66b1f8cec09599169063b66503cf90604401600060405180830381600087803b158015611e6057600080fd5b505af1158015611e74573d6000803e3d6000fd5b50505050611e83565b60168390555b604080518881526020810188905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b509091565b6001600160a01b038116600090815260146020908152604080832054600b909252822054826064611efa8360286133fa565b611f049190613419565b90506000807f00000000000000000000000029d3622c78615a1e7459e4be434d816b7de293e46001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8b919061345f565b6040516331a9108f60e11b8152600481018790529091507f00000000000000000000000029d3622c78615a1e7459e4be434d816b7de293e46001600160a01b031690636352211e90602401602060405180830381865afa158015611ff3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201791906134e7565b6001600160a01b0316876001600160a01b03161480156120375750600081115b156120f9576040516339f890b560e21b81526004810186905260649082906001600160a01b037f00000000000000000000000029d3622c78615a1e7459e4be434d816b7de293e4169063e7e242d490602401602060405180830381865afa1580156120a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ca919061345f565b600a546120d791906133fa565b6120e19190613419565b6120ec90603c6133fa565b6120f69190613419565b91505b61210c61210683856134a0565b85612a7b565b979650505050505050565b816001600160a01b03167f00000000000000000000000029d3622c78615a1e7459e4be434d816b7de293e46001600160a01b0316636352211e836040518263ffffffff1660e01b815260040161216f91815260200190565b602060405180830381865afa15801561218c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b091906134e7565b6001600160a01b0316146121fb5760405162461bcd60e51b81526020600482015260126024820152712737ba103b32903a37b5b2b71037bbb732b960711b6044820152606401610883565b6001600160a01b03821660009081526014602052604081205490036122b3576001600160a01b03828116600081815260146020526040908190208490555163698473e360e01b81526004810184905260248101919091527f00000000000000000000000098a1de08715800801e9764349f5a71cbe63f99cc9091169063698473e390604401600060405180830381600087803b15801561229a57600080fd5b505af11580156122ae573d6000803e3d6000fd5b505050505b6001600160a01b03821660009081526014602052604090205481146123085760405162461bcd60e51b815260206004820152600b60248201526a2bb937b733903a37b5b2b760a91b6044820152606401610883565b816001600160a01b03167fa88ad287ee039276852a62661add3a03e736aca1a2987ceaebcf4ecfd018ae3f8260405161234391815260200190565b60405180910390a25050565b6000546001146123715760405162461bcd60e51b815260040161088390613478565b6002600055806123b15760405162461bcd60e51b815260206004820152600b60248201526a16995c9bc8185b5bdd5b9d60aa1b6044820152606401610883565b6123bb3382612d25565b6123f06001600160a01b037f000000000000000000000000751f3b8ca139bc1f3482b193297485f14208826a16333084612c3b565b60405181815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c906020015b60405180910390a2506001600055565b600c54600a116124795760405162461bcd60e51b8152602060048201526016602482015275546f6f206d616e792072657761726420746f6b656e7360501b6044820152606401610883565b6001600160a01b0381166000908152600d602052604090205460ff16156124d75760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481c9959da5cdd195c995960721b6044820152606401610883565b6001600160a01b03166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b0319169091179055565b600060025460000361256557506001600160a01b031660009081526007602052604090205490565b6002546001600160a01b0383166000908152600460209081526040808320546006835281842054600590935292205461259e9190612a7b565b6125a785612c17565b6125b191906133cd565b6125bb91906133fa565b6125c59190613419565b6001600160a01b03831660009081526007602052604090205461074091906134a0565b6001600160a01b0382166000908152601360205260408120548190808203612617576000809250925050610f33565b6001600160a01b03851660009081526012602052604081209061263b828488612831565b6000908152602092835260409081902081518083019092528054808352600190910154919093018190529791965090945050505050565b6001600160a01b03821660009081526014602052604090205481146126c75760405162461bcd60e51b815260206004820152600b60248201526a2bb937b733903a37b5b2b760a91b6044820152606401610883565b6001600160a01b03828116600081815260146020526040808220919091555163411b1f7760e01b81526004810184905260248101919091527f00000000000000000000000098a1de08715800801e9764349f5a71cbe63f99cc9091169063411b1f7790604401600060405180830381600087803b15801561274757600080fd5b505af115801561275b573d6000803e3d6000fd5b50505050816001600160a01b03167f25842dad107a4bb4efa3824996f6140a5f6f3de5197debed6d780dc08bb0a0a08260405161234391815260200190565b6000546001146127bc5760405162461bcd60e51b815260040161088390613478565b60026000556127cb3382612d7b565b6127ff6001600160a01b037f000000000000000000000000751f3b8ca139bc1f3482b193297485f14208826a16338361298e565b60405181815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200161241e565b6000826000036128775760405162461bcd60e51b8152602060048201526011602482015270456d70747920636865636b706f696e747360781b6044820152606401610883565b818460006128866001876133cd565b815260200190815260200160002060000154116128af576128a86001846133cd565b9050610cfe565b6000808052602085905260409020548210156128cd57506000610cfe565b6000806128db6001866133cd565b90505b8181111561296e57600060026128f484846133cd565b6128fe9190613419565b61290890836133cd565b6000818152602089815260409182902082518084019093528054808452600190910154918301919091529192509086900361294857509250610cfe915050565b805186111561295957819350612967565b6129646001836133cd565b92505b50506128de565b50949350505050565b600081831015612987578161073d565b5090919050565b6040516001600160a01b0383166024820152604481018290526129f190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612dc2565b505050565b6001600160a01b0381166000908152600360205260408120546002805491928392612a229084906133cd565b90915550612a31905082611ec8565b6001600160a01b0383166000908152600360205260408120829055600280549293508392909190612a639084906134a0565b90915550612a7390508282612e94565b610910612f85565b6000818310612987578161073d565b6000806000612a998785612977565b6001600160a01b038916600090815260056020908152604080832054600490925290912054919250908690612ad7612ad18a89612977565b84612a7b565b612ae18585612a7b565b612aeb91906133cd565b612af591906133fa565b612aff9190613419565b99919850909650505050505050565b6001600160a01b0383166000908152601360205260409020548015801590612b6a57506001600160a01b03841660009081526012602052604081208391612b566001856133cd565b815260200190815260200160002060000154145b15612bad576001600160a01b03841660009081526012602052604081208491612b946001856133cd565b8152602081019190915260400160002060010155612c11565b60408051808201825283815260208082018681526001600160a01b038816600090815260128352848120868252909252929020905181559051600191820155612bf79082906134a0565b6001600160a01b0385166000908152601360205260409020555b50505050565b6001600160a01b038116600090815260056020526040812054610740904290612a7b565b6040516001600160a01b0380851660248301528316604482015260648101829052612c119085906323b872dd60e01b906084016129ba565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015612cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce8919061345f565b612cf291906134a0565b6040516001600160a01b038516602482015260448101829052909150612c1190859063095ea7b360e01b906064016129ba565b612d2d613029565b80600a6000828254612d3f91906134a0565b90915550506001600160a01b0382166000908152600b602052604081208054839290612d6c9084906134a0565b909155506109109050826129f6565b612d83613029565b80600a6000828254612d9591906133cd565b90915550506001600160a01b0382166000908152600b602052604081208054839290612d6c9084906133cd565b6000612e17826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130ad9092919063ffffffff16565b8051909150156129f15780806020019051810190612e359190613504565b6129f15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610883565b6001600160a01b0382166000908152600f602052604090205442908015801590612ef257506001600160a01b0384166000908152600e602052604081208391612ede6001856133cd565b815260200190815260200160002060000154145b15612f1c576001600160a01b0384166000908152600e602052604081208491612b946001856133cd565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e8352848120868252909252929020905181559051600191820155612f669082906134a0565b6001600160a01b0385166000908152600f602052604090205550505050565b601154428115801590612fb757508060106000612fa36001866133cd565b815260200190815260200160002060000154145b15612fe65760025460106000612fce6001866133cd565b81526020810191909152604001600020600101555050565b604080518082018252828152600254602080830191825260008681526010909152929092209051815590516001918201556130229083906134a0565b6011555050565b600c5460005b81811015610910576000600c828154811061304c5761304c613388565b6000918252602090912001546001600160a01b03169050613071816000196001611502565b6001600160a01b0390921660009081526007602090815260408083206006909252909120929092559055806130a5816133b4565b91505061302f565b60606001600160a01b0384163b6131065760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610883565b600080856001600160a01b0316856040516131219190613552565b6000604051808303816000865af19150503d806000811461315e576040519150601f19603f3d011682016040523d82523d6000602084013e613163565b606091505b509150915061317382828661317d565b9695505050505050565b6060831561318c575081610cfe565b82511561319c5782518084602001fd5b8160405162461bcd60e51b8152600401610883919061356e565b6001600160a01b0381168114610e0457600080fd5b80356131d6816131b6565b919050565b600080604083850312156131ee57600080fd5b82356131f9816131b6565b946020939093013593505050565b6000806040838503121561321a57600080fd5b8235613225816131b6565b91506020830135613235816131b6565b809150509250929050565b60006020828403121561325257600080fd5b8135610cfe816131b6565b60006020828403121561326f57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561329f57600080fd5b82356132aa816131b6565b915060208381013567ffffffffffffffff808211156132c857600080fd5b818601915086601f8301126132dc57600080fd5b8135818111156132ee576132ee613276565b8060051b604051601f19603f8301168101818110858211171561331357613313613276565b60405291825284820192508381018501918983111561333157600080fd5b938501935b8285101561335657613347856131cb565b84529385019392850192613336565b8096505050505050509250929050565b6000806040838503121561337957600080fd5b50508035926020909101359150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016133c6576133c661339e565b5060010190565b6000828210156133df576133df61339e565b500390565b634e487b7160e01b600052603160045260246000fd5b60008160001904831182151516156134145761341461339e565b500290565b60008261343657634e487b7160e01b600052601260045260246000fd5b500490565b6000806040838503121561344e57600080fd5b505080516020909101519092909150565b60006020828403121561347157600080fd5b5051919050565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b600082198211156134b3576134b361339e565b500190565b600080604083850312156134cb57600080fd5b82516134d6816131b6565b6020840151909250613235816131b6565b6000602082840312156134f957600080fd5b8151610cfe816131b6565b60006020828403121561351657600080fd5b81518015158114610cfe57600080fd5b60005b83811015613541578181015183820152602001613529565b83811115612c115750506000910152565b60008251613564818460208701613526565b9190910192915050565b602081526000825180602084015261358d816040850160208701613526565b601f01601f1916919091016040019291505056fea26469706673582212207a0792d1690da6f82ef24cc436965908d9f22abc48a2c8af306886a0a90a5e2464736f6c634300080f0033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.