Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 11693115 | 1274 days ago | IN | Create: IncentivisedVotingLockup | 0 ETH | 0.33209628 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
IncentivisedVotingLockup
Compiler Version
v0.6.8+commit.0bbfe453
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
/* solium-disable security/no-block-members */ pragma solidity 0.6.8; import { IBasicToken } from "../shared/IBasicToken.sol"; import { DaoGovernable } from "../governance/DaoGovernable.sol"; import { ProtocolDaoGovernable } from "../governance/ProtocolDaoGovernable.sol"; import { IIncentivisedVotingLockup } from "../interfaces/IIncentivisedVotingLockup.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import { SignedSafeMath128 } from "../shared/SignedSafeMath128.sol"; import { StableMath, SafeMath } from "../shared/StableMath.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; /** * @title IncentivisedVotingLockup * @author Voting Weight tracking & Decay * -> Curve Finance (MIT) - forked & ported to Solidity * -> https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy * osolmaz - Research & Reward distributions * alsco77 - Solidity implementation * @notice Lockup MTA, receive vMTA (voting weight that decays over time), and earn * rewards based on staticWeight * @dev Supports: * 1) Tracking MTA Locked up (LockedBalance) * 2) Pull Based Reward allocations based on Lockup (Static Balance) * 3) Decaying voting weight lookup through CheckpointedERC20 (balanceOf) * 4) Ejecting fully decayed participants from reward allocation (eject) * 5) Migration of points to v2 (used as multiplier in future) ***** (rewardsPaid) * 6) Closure of contract (expire) */ contract IncentivisedVotingLockup is IIncentivisedVotingLockup, Initializable, ReentrancyGuardUpgradeable, DaoGovernable, ProtocolDaoGovernable { using StableMath for uint256; using SafeMath for uint256; using SignedSafeMath128 for int128; using SafeERC20 for IERC20; /** Shared Events */ event Deposit(address indexed provider, uint256 value, uint256 locktime, LockAction indexed action, uint256 ts); event Withdraw(address indexed provider, uint256 value, uint256 ts); event Expired(); /** Shared Globals */ IERC20 public stakingToken; uint256 private constant WEEK = 7 days; uint256 public constant MAXTIME = 1095 days; //3 years uint256 public END; bool public expired; /** Lockup */ uint256 public globalEpoch; Point[] public pointHistory; mapping(address => Point[]) public userPointHistory; mapping(address => uint256) public userPointEpoch; mapping(uint256 => int128) public slopeChanges; mapping(address => LockedBalance) public locked; // Voting token - Checkpointed view only ERC20 string public name; string public symbol; uint256 public decimals; /** Structs */ struct Point { int128 bias; int128 slope; uint256 ts; uint256 blk; } struct LockedBalance { int128 amount; uint256 end; } enum LockAction { CREATE_LOCK, INCREASE_LOCK_AMOUNT, INCREASE_LOCK_TIME } // constructor( // address _stakingToken, // string memory _name, // string memory _symbol, // address _dao, // address _protocolDao // ) // public // DaoGovernable(_dao) // ProtocolDaoGovernable(_protocolDao) // { // _initialize(_stakingToken, _name, _symbol); // } function initialize( address _stakingToken, string calldata _name, string calldata _symbol, address _dao, address _protocolDao ) external initializer { ReentrancyGuardUpgradeable.__ReentrancyGuard_init(); DaoGovernable.__DaoGovernable_init(_dao); ProtocolDaoGovernable.__ProtocolDaoGovernable_init(_protocolDao); _initialize(_stakingToken, _name, _symbol); } function _initialize( address _stakingToken, string memory _name, string memory _symbol ) internal { stakingToken = IERC20(_stakingToken); Point memory init = Point({ bias: int128(0), slope: int128(0), ts: block.timestamp, blk: block.number}); pointHistory.push(init); decimals = IBasicToken(_stakingToken).decimals(); require(decimals <= 18, "Cannot have more than 18 decimals"); name = _name; symbol = _symbol; decimals = 18; END = block.timestamp.add(MAXTIME); expired = false; } /** @dev Modifier to ensure contract has not yet expired */ modifier contractNotExpired(){ require(!expired, "Contract is expired"); _; } /** * @dev Validates that the user has an expired lock && they still have capacity to earn * @param _addr User address to check */ modifier lockupIsOver(address _addr) { LockedBalance memory userLock = locked[_addr]; require(userLock.amount > 0 && block.timestamp >= userLock.end, "Users lock didn't expire"); // This is removed because we are using the voting weight instead of the static weight // In this case when the lock end is reached the balance will automatically be 0 // require(balanceOf(_addr) > 0, "User must have existing bias"); _; } /*************************************** LOCKUP - GETTERS ****************************************/ /** * @dev Gets the last available user point * @param _addr User address * @return bias i.e. y * @return slope i.e. linear gradient * @return ts i.e. time point was logged */ function getLastUserPoint(address _addr) override external view returns( int128 bias, int128 slope, uint256 ts ) { uint256 uepoch = userPointEpoch[_addr]; if(uepoch == 0){ return (0, 0, 0); } Point memory point = userPointHistory[_addr][uepoch]; return (point.bias, point.slope, point.ts); } /*************************************** LOCKUP ****************************************/ /** * @dev Records a checkpoint of both individual and global slope * @param _addr User address, or address(0) for only global * @param _oldLocked Old amount that user had locked, or null for global * @param _newLocked new amount that user has locked, or null for global */ function _checkpoint( address _addr, LockedBalance memory _oldLocked, LockedBalance memory _newLocked ) internal { Point memory userOldPoint; Point memory userNewPoint; int128 oldSlopeDelta = 0; int128 newSlopeDelta = 0; uint256 epoch = globalEpoch; if(_addr != address(0)){ // Calculate slopes and biases // Kept at zero when they have to if(_oldLocked.end > block.timestamp && _oldLocked.amount > 0){ userOldPoint.slope = _oldLocked.amount.div(int128(MAXTIME)); userOldPoint.bias = userOldPoint.slope.mul(int128(_oldLocked.end.sub(block.timestamp))); } if(_newLocked.end > block.timestamp && _newLocked.amount > 0){ userNewPoint.slope = _newLocked.amount.div(int128(MAXTIME)); userNewPoint.bias = userNewPoint.slope.mul(int128(_newLocked.end.sub(block.timestamp))); } // Moved from bottom final if statement to resolve stack too deep err // start { // Now handle user history uint256 uEpoch = userPointEpoch[_addr]; if(uEpoch == 0){ userPointHistory[_addr].push(userOldPoint); } userPointEpoch[_addr] = uEpoch.add(1); userNewPoint.ts = block.timestamp; userNewPoint.blk = block.number; // userPointHistory[_addr][uEpoch.add(1)] = userNewPoint; userPointHistory[_addr].push(userNewPoint); // } end // Read values of scheduled changes in the slope // oldLocked.end can be in the past and in the future // newLocked.end can ONLY by in the FUTURE unless everything expired: than zeros oldSlopeDelta = slopeChanges[_oldLocked.end]; if(_newLocked.end != 0){ if (_newLocked.end == _oldLocked.end) { newSlopeDelta = oldSlopeDelta; } else { newSlopeDelta = slopeChanges[_newLocked.end]; } } } Point memory lastPoint = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number}); if(epoch > 0){ lastPoint = pointHistory[epoch]; } uint256 lastCheckpoint = lastPoint.ts; // initialLastPoint is used for extrapolation to calculate block number // (approximately, for *At methods) and save them // as we cannot figure that out exactly from inside the contract Point memory initialLastPoint = Point({bias: 0, slope: 0, ts: lastPoint.ts, blk: lastPoint.blk}); uint256 blockSlope = 0; // dblock/dt if(block.timestamp > lastPoint.ts){ blockSlope = StableMath.scaleInteger(block.number.sub(lastPoint.blk)).div(block.timestamp.sub(lastPoint.ts)); } // If last point is already recorded in this block, slope=0 // But that's ok b/c we know the block in such case // Go over weeks to fill history and calculate what the current point is uint256 iterativeTime = _floorToWeek(lastCheckpoint); for (uint256 i = 0; i < 255; i++){ // Hopefully it won't happen that this won't get used in 5 years! // If it does, users will be able to withdraw but vote weight will be broken iterativeTime = iterativeTime.add(WEEK); int128 dSlope = 0; if(iterativeTime > block.timestamp){ iterativeTime = block.timestamp; } else { dSlope = slopeChanges[iterativeTime]; } int128 biasDelta = lastPoint.slope.mul(int128(iterativeTime.sub(lastCheckpoint))); lastPoint.bias = lastPoint.bias.sub(biasDelta); lastPoint.slope = lastPoint.slope.add(dSlope); // This can happen if(lastPoint.bias < 0){ lastPoint.bias = 0; } // This cannot happen - just in case if(lastPoint.slope < 0){ lastPoint.slope = 0; } lastCheckpoint = iterativeTime; lastPoint.ts = iterativeTime; lastPoint.blk = initialLastPoint.blk.add(blockSlope.mulTruncate(iterativeTime.sub(initialLastPoint.ts))); // when epoch is incremented, we either push here or after slopes updated below epoch = epoch.add(1); if(iterativeTime == block.timestamp) { lastPoint.blk = block.number; break; } else { // pointHistory[epoch] = lastPoint; pointHistory.push(lastPoint); } } globalEpoch = epoch; // Now pointHistory is filled until t=now if(_addr != address(0)){ // If last point was in this block, the slope change has been applied already // But in such case we have 0 slope(s) lastPoint.slope = lastPoint.slope.add(userNewPoint.slope.sub(userOldPoint.slope)); lastPoint.bias = lastPoint.bias.add(userNewPoint.bias.sub(userOldPoint.bias)); if(lastPoint.slope < 0) { lastPoint.slope = 0; } if(lastPoint.bias < 0){ lastPoint.bias = 0; } } // Record the changed point into history // pointHistory[epoch] = lastPoint; pointHistory.push(lastPoint); if(_addr != address(0)){ // Schedule the slope changes (slope is going down) // We subtract new_user_slope from [new_locked.end] // and add old_user_slope to [old_locked.end] if(_oldLocked.end > block.timestamp){ // oldSlopeDelta was <something> - userOldPoint.slope, so we cancel that oldSlopeDelta = oldSlopeDelta.add(userOldPoint.slope); if(_newLocked.end == _oldLocked.end) { oldSlopeDelta = oldSlopeDelta.sub(userNewPoint.slope); // It was a new deposit, not extension } slopeChanges[_oldLocked.end] = oldSlopeDelta; } if(_newLocked.end > block.timestamp) { if(_newLocked.end > _oldLocked.end){ newSlopeDelta = newSlopeDelta.sub(userNewPoint.slope); // old slope disappeared at this point slopeChanges[_newLocked.end] = newSlopeDelta; } // else: we recorded it already in oldSlopeDelta } } } /** * @dev Deposits or creates a stake for a given address * @param _addr User address to assign the stake * @param _value Total units of StakingToken to lockup * @param _unlockTime Time at which the stake should unlock * @param _oldLocked Previous amount staked by this user * @param _action See LockAction enum */ function _depositFor( address _addr, uint256 _value, uint256 _unlockTime, LockedBalance memory _oldLocked, LockAction _action ) internal { LockedBalance memory newLocked = LockedBalance({amount: _oldLocked.amount, end: _oldLocked.end}); // Adding to existing lock, or if a lock is expired - creating a new one newLocked.amount = newLocked.amount.add(int128(_value)); if(_unlockTime != 0){ newLocked.end = _unlockTime; } locked[_addr] = newLocked; // Possibilities: // Both _oldLocked.end could be current or expired (>/< block.timestamp) // value == 0 (extend lock) or value > 0 (add to lock or extend lock) // newLocked.end > block.timestamp (always) _checkpoint(_addr, _oldLocked, newLocked); if(_value != 0) { stakingToken.safeTransferFrom(_addr, address(this), _value); } emit Deposit(_addr, _value, newLocked.end, _action, block.timestamp); } /** * @dev Public function to trigger global checkpoint */ function checkpoint() external { LockedBalance memory empty; _checkpoint(address(0), empty, empty); } /** * @dev Creates a new lock * @param _value Total units of StakingToken to lockup * @param _unlockTime Time at which the stake should unlock */ function createLock(uint256 _value, uint256 _unlockTime) override external nonReentrant contractNotExpired { uint256 unlock_time = _floorToWeek(_unlockTime); // Locktime is rounded down to weeks LockedBalance memory locked_ = LockedBalance({amount: locked[msg.sender].amount, end: locked[msg.sender].end}); require(_value > 0, "Must stake non zero amount"); require(locked_.amount == 0, "Withdraw old tokens first"); require(unlock_time > block.timestamp, "Can only lock until time in the future"); require(unlock_time <= END, "Voting lock can be 3 years max (until recol)"); _depositFor(msg.sender, _value, unlock_time, locked_, LockAction.CREATE_LOCK); } /** * @dev Increases amount of stake thats locked up & resets decay * @param _value Additional units of StakingToken to add to exiting stake */ function increaseLockAmount(uint256 _value) override external nonReentrant contractNotExpired { LockedBalance memory locked_ = LockedBalance({amount: locked[msg.sender].amount, end: locked[msg.sender].end}); require(_value > 0, "Must stake non zero amount"); require(locked_.amount > 0, "No existing lock found"); require(locked_.end > block.timestamp, "Cannot add to expired lock. Withdraw"); _depositFor(msg.sender, _value, 0, locked_, LockAction.INCREASE_LOCK_AMOUNT); } /** * @dev Increases length of lockup & resets decay * @param _unlockTime New unlocktime for lockup */ function increaseLockLength(uint256 _unlockTime) override external nonReentrant contractNotExpired { LockedBalance memory locked_ = LockedBalance({amount: locked[msg.sender].amount, end: locked[msg.sender].end}); uint256 unlock_time = _floorToWeek(_unlockTime); // Locktime is rounded down to weeks require(locked_.amount > 0, "Nothing is locked"); require(locked_.end > block.timestamp, "Lock expired"); require(unlock_time > locked_.end, "Can only increase lock WEEK"); require(unlock_time <= END, "Voting lock can be 3 years max (until recol)"); _depositFor(msg.sender, 0, unlock_time, locked_, LockAction.INCREASE_LOCK_TIME); } /** * @dev Withdraws all the senders stake, providing lockup is over */ function withdraw() override external { _withdraw(msg.sender); } /** * @dev Withdraws a given users stake, providing the lockup has finished * @param _addr User for which to withdraw */ function _withdraw(address _addr) internal nonReentrant { LockedBalance memory oldLock = LockedBalance({ end: locked[_addr].end, amount: locked[_addr].amount }); require(block.timestamp >= oldLock.end || expired, "The lock didn't expire"); require(oldLock.amount > 0, "Must have something to withdraw"); uint256 value = uint256(oldLock.amount); LockedBalance memory currentLock = LockedBalance({end: 0, amount: 0}); locked[_addr] = currentLock; // oldLocked can have either expired <= timestamp or zero end // currentLock has only 0 end // Both can have >= 0 amount if(!expired){ _checkpoint(_addr, oldLock, currentLock); } stakingToken.safeTransfer(_addr, value); emit Withdraw(_addr, value, block.timestamp); } /** * @dev Ends the contract, unlocking all stakes. * No more staking can happen. Only withdraw and Claim. */ function expireContract() override external onlyProtocolDao contractNotExpired { expired = true; emit Expired(); } /*************************************** GETTERS ****************************************/ /** @dev Floors a timestamp to the nearest weekly increment */ function _floorToWeek(uint256 _t) internal pure returns(uint256) { return _t.div(WEEK).mul(WEEK); } /** * @dev Uses binarysearch to find the most recent point history preceeding block * @param _block Find the most recent point history before this block * @param _maxEpoch Do not search pointHistories past this index */ function _findBlockEpoch(uint256 _block, uint256 _maxEpoch) internal view returns(uint256) { // Binary search uint256 min = 0; uint256 max = _maxEpoch; // Will be always enough for 128-bit numbers for(uint256 i = 0; i < 128; i++){ if (min >= max) break; uint256 mid = (min.add(max).add(1)).div(2); if (pointHistory[mid].blk <= _block){ min = mid; } else { max = mid.sub(1); } } return min; } /** * @dev Uses binarysearch to find the most recent user point history preceeding block * @param _addr User for which to search * @param _block Find the most recent point history before this block */ function _findUserBlockEpoch(address _addr, uint256 _block) internal view returns(uint256) { uint256 min = 0; uint256 max = userPointEpoch[_addr]; for(uint256 i = 0; i < 128; i++) { if(min >= max){ break; } uint256 mid = (min.add(max).add(1)).div(2); if(userPointHistory[_addr][mid].blk <= _block){ min = mid; } else { max = mid.sub(1); } } return min; } /** * @dev Gets curent user voting weight (aka effectiveStake) * @param _owner User for which to return the balance * @return uint256 Balance of user */ function balanceOf(address _owner) override public view returns (uint256) { uint256 epoch = userPointEpoch[_owner]; if(epoch == 0){ return 0; } Point memory lastPoint = userPointHistory[_owner][epoch]; lastPoint.bias = lastPoint.bias.sub(lastPoint.slope.mul(int128(block.timestamp.sub(lastPoint.ts)))); if(lastPoint.bias < 0) { lastPoint.bias = 0; } return uint256(lastPoint.bias); } /** * @dev Gets a users votingWeight at a given blockNumber * @param _owner User for which to return the balance * @param _blockNumber Block at which to calculate balance * @return uint256 Balance of user */ function balanceOfAt(address _owner, uint256 _blockNumber) override public view returns (uint256) { require(_blockNumber <= block.number, "Must pass block number in the past"); // Get most recent user Point to block uint256 userEpoch = _findUserBlockEpoch(_owner, _blockNumber); if(userEpoch == 0){ return 0; } Point memory upoint = userPointHistory[_owner][userEpoch]; // Get most recent global Point to block uint256 maxEpoch = globalEpoch; uint256 epoch = _findBlockEpoch(_blockNumber, maxEpoch); Point memory point0 = pointHistory[epoch]; // Calculate delta (block & time) between user Point and target block // Allowing us to calculate the average seconds per block between // the two points uint256 dBlock = 0; uint256 dTime = 0; if(epoch < maxEpoch){ Point memory point1 = pointHistory[epoch.add(1)]; dBlock = point1.blk.sub(point0.blk); dTime = point1.ts.sub(point0.ts); } else { dBlock = block.number.sub(point0.blk); dTime = block.timestamp.sub(point0.ts); } // (Deterministically) Estimate the time at which block _blockNumber was mined uint256 blockTime = point0.ts; if(dBlock != 0) { // blockTime += dTime * (_blockNumber - point0.blk) / dBlock; blockTime = blockTime.add(dTime.mul(_blockNumber.sub(point0.blk)).div(dBlock)); } // Current Bias = most recent bias - (slope * time since update) upoint.bias = upoint.bias.sub(upoint.slope.mul(int128(blockTime.sub(upoint.ts)))); if(upoint.bias >= 0){ return uint256(upoint.bias); } else { return 0; } } /** * @dev Calculates total supply of votingWeight at a given time _t * @param _point Most recent point before time _t * @param _t Time at which to calculate supply * @return totalSupply at given point in time */ function _supplyAt(Point memory _point, uint256 _t) internal view returns (uint256) { Point memory lastPoint = _point; // Floor the timestamp to weekly interval uint256 iterativeTime = _floorToWeek(lastPoint.ts); // Iterate through all weeks between _point & _t to account for slope changes for(uint256 i = 0; i < 255; i++){ iterativeTime = iterativeTime.add(WEEK); int128 dSlope = 0; // If week end is after timestamp, then truncate & leave dSlope to 0 if(iterativeTime > _t){ iterativeTime = _t; } // else get most recent slope change else { dSlope = slopeChanges[iterativeTime]; } // lastPoint.bias -= lastPoint.slope * convert(iterativeTime - lastPoint.ts, int128) lastPoint.bias = lastPoint.bias.sub(lastPoint.slope.mul(int128(iterativeTime.sub(lastPoint.ts)))); if(iterativeTime == _t){ break; } lastPoint.slope = lastPoint.slope.add(dSlope); lastPoint.ts = iterativeTime; } if (lastPoint.bias < 0){ lastPoint.bias = 0; } return uint256(lastPoint.bias); } /** * @dev Calculates current total supply of votingWeight * @return totalSupply of voting token weight */ function totalSupply() override public view returns (uint256) { uint256 epoch_ = globalEpoch; Point memory lastPoint = pointHistory[epoch_]; return _supplyAt(lastPoint, block.timestamp); } /** * @dev Calculates total supply of votingWeight at a given blockNumber * @param _blockNumber Block number at which to calculate total supply * @return totalSupply of voting token weight at the given blockNumber */ function totalSupplyAt(uint256 _blockNumber) override public view returns (uint256) { require(_blockNumber <= block.number, "Must pass block number in the past"); uint256 epoch = globalEpoch; uint256 targetEpoch = _findBlockEpoch(_blockNumber, epoch); Point memory point = pointHistory[targetEpoch]; // If point.blk > _blockNumber that means we got the initial epoch & contract did not yet exist if(point.blk > _blockNumber){ return 0; } uint256 dTime = 0; if(targetEpoch < epoch){ Point memory pointNext = pointHistory[targetEpoch.add(1)]; if(point.blk != pointNext.blk) { dTime = (_blockNumber.sub(point.blk)).mul(pointNext.ts.sub(point.ts)).div(pointNext.blk.sub(point.blk)); } } else if (point.blk != block.number){ dTime = (_blockNumber.sub(point.blk)).mul(block.timestamp.sub(point.ts)).div(block.number.sub(point.blk)); } // Now dTime contains info on how far are we beyond point return _supplyAt(point, point.ts.add(dTime)); } function getDuration() external pure returns (uint256) { return WEEK; } /*************************************** ADMIN ****************************************/ /** * @dev Allows the DAO to salvage the full amount of any ERC20 tokens * from the contract by supplying the token address. * @param _token Address of the token to be salvaged */ function salvage(address _token) external onlyDao { uint256 balance = IERC20(_token).balanceOf(address(this)); require( IERC20(_token).transfer(dao(), balance) ); } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
pragma solidity 0.6.8; /** * @title DaoGovernable * @author Stability Labs Pty. Ltd. * @notice Simple contract implementing an Ownable pattern. * @dev Derives from V2.3.0 @openzeppelin/contracts/ownership/Ownable.sol * Modified to have custom name and features * - Removed `renounceOwnership` * - Changes `_owner` to `_governor` */ contract DaoGovernable { event DaoChanged(address indexed previousDao, address indexed newDao); address private _dao; /** * @dev Initializes the contract setting supplied address as the initial Dao. */ // constructor (address _newDao) internal { // _dao = _newDao; // emit DaoChanged(address(0), _dao); // } function __DaoGovernable_init(address _newDao) internal { _dao = _newDao; emit DaoChanged(address(0), _dao); } /** * @dev Returns the address of the current Dao. */ function dao() public view returns (address) { return _dao; } /** * @dev Throws if called by any account other than the Dao. */ modifier onlyDao() { require(isDao(), "GOV: caller is not the Dao"); _; } /** * @dev Returns true if the caller is the current Dao. */ function isDao() public view returns (bool) { return msg.sender == _dao; } /** * @dev Transfers Dao of the contract to a new account (`newDao`). * Can only be called by the current Dao. * @param _newDao Address of the new Dao */ function changeDao(address _newDao) external onlyDao { _changeDao(_newDao); } /** * @dev Change Dao of the contract to a new account (`newDao`). * @param _newDao Address of the new Governor */ function _changeDao(address _newDao) internal { require(_newDao != address(0), "GOV: new Dao is address(0)"); emit DaoChanged(_dao, _newDao); _dao = _newDao; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
pragma solidity 0.6.8; /** * @title ProtocolDaoGovernable * @author Stability Labs Pty. Ltd. * @notice Simple contract implementing an Ownable pattern. * @dev Derives from V2.3.0 @openzeppelin/contracts/ownership/Ownable.sol * Modified to have custom name and features * - Removed `renounceOwnership` * - Changes `_owner` to `_governor` */ contract ProtocolDaoGovernable { event ProtocolDaoChanged(address indexed previousProtocolDao, address indexed newProtocolDao); address private _protocolDao; /** * @dev Initializes the contract setting supplied address as the initial Protocol Dao. */ // constructor (address _newProtocolDao) internal { // _protocolDao = _newProtocolDao; // emit ProtocolDaoChanged(address(0), _protocolDao); // } function __ProtocolDaoGovernable_init(address _newProtocolDao) internal { _protocolDao = _newProtocolDao; emit ProtocolDaoChanged(address(0), _protocolDao); } /** * @dev Returns the address of the current Protocol Dao. */ function protocolDao() public view returns (address) { return _protocolDao; } /** * @dev Throws if called by any account other than the Protocol Dao. */ modifier onlyProtocolDao() { require(isProtocolDao(), "GOV: caller is not the Protocol Dao"); _; } /** * @dev Returns true if the caller is the current Protocol Dao. */ function isProtocolDao() public view returns (bool) { return msg.sender == _protocolDao; } /** * @dev Transfers Protocol Dao of the contract to a new account (`newProtocolDao`). * Can only be called by the current Protocol Dao. * @param _newProtocolDao Address of the new Protocol Dao */ function changeProtocolDao(address _newProtocolDao) external onlyProtocolDao { _changeProtocolDao(_newProtocolDao); } /** * @dev Change Protocol Dao of the contract to a new account (`newProtocolDao`). * @param _newProtocolDao Address of the new Governor */ function _changeProtocolDao(address _newProtocolDao) internal { require(_newProtocolDao != address(0), "GOV: new Protocol Dao is address(0)"); emit ProtocolDaoChanged(_protocolDao, _newProtocolDao); _protocolDao = _newProtocolDao; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
pragma solidity 0.6.8; import { IERC20WithCheckpointing } from "../shared/IERC20WithCheckpointing.sol"; interface IIncentivisedVotingLockup is IERC20WithCheckpointing { function getLastUserPoint(address _addr) external view returns(int128 bias, int128 slope, uint256 ts); function createLock(uint256 _value, uint256 _unlockTime) external; function withdraw() external; function increaseLockAmount(uint256 _value) external; function increaseLockLength(uint256 _unlockTime) external; function expireContract() external; }
pragma solidity 0.6.8; interface IBasicToken { function decimals() external view returns (uint8); }
pragma solidity 0.6.8; // From https://github.com/aragonone/voting-connectors interface IERC20WithCheckpointing { function balanceOf(address _owner) external view returns (uint256); function balanceOfAt(address _owner, uint256 _blockNumber) external view returns (uint256); function totalSupply() external view returns (uint256); function totalSupplyAt(uint256 _blockNumber) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.6.8; /** * @title SignedSafeMath128 * @author OpenZeppelin > https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SignedSafeMath.sol * @dev Signed math operations with safety checks that revert on error. * Reverted to solc 0.5.16 & updated from int256 to int128 */ library SignedSafeMath128 { int128 constant private _INT128_MIN = -2**127; /** * @dev Returns the multiplication of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(int128 a, int128 b) internal pure returns (int128) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } require(!(a == -1 && b == _INT128_MIN), "SignedSafeMath: multiplication overflow"); int128 c = a * b; require(c / a == b, "SignedSafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two signed integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(int128 a, int128 b) internal pure returns (int128) { require(b != 0, "SignedSafeMath: division by zero"); require(!(b == -1 && a == _INT128_MIN), "SignedSafeMath: division overflow"); int128 c = a / b; return c; } /** * @dev Returns the subtraction of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(int128 a, int128 b) internal pure returns (int128) { int128 c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow"); return c; } /** * @dev Returns the addition of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(int128 a, int128 b) internal pure returns (int128) { int128 c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow"); return c; } }
pragma solidity 0.6.8; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; /** * @title StableMath * @author Stability Labs Pty. Ltd. * @notice A library providing safe mathematical operations to multiply and * divide with standardised precision. * @dev Derives from OpenZeppelin's SafeMath lib and uses generic system * wide variables for managing precision. */ library StableMath { using SafeMath for uint256; /** * @dev Scaling unit for use in specific calculations, * where 1 * 10**18, or 1e18 represents a unit '1' */ uint256 private constant FULL_SCALE = 1e18; /** * @notice Token Ratios are used when converting between units of bAsset, mAsset and MTA * Reasoning: Takes into account token decimals, and difference in base unit (i.e. grams to Troy oz for gold) * @dev bAsset ratio unit for use in exact calculations, * where (1 bAsset unit * bAsset.ratio) / ratioScale == x mAsset unit */ uint256 private constant RATIO_SCALE = 1e8; /** * @dev Provides an interface to the scaling unit * @return Scaling unit (1e18 or 1 * 10**18) */ function getFullScale() internal pure returns (uint256) { return FULL_SCALE; } /** * @dev Provides an interface to the ratio unit * @return Ratio scale unit (1e8 or 1 * 10**8) */ function getRatioScale() internal pure returns (uint256) { return RATIO_SCALE; } /** * @dev Scales a given integer to the power of the full scale. * @param x Simple uint256 to scale * @return Scaled value a to an exact number */ function scaleInteger(uint256 x) internal pure returns (uint256) { return x.mul(FULL_SCALE); } /*************************************** PRECISE ARITHMETIC ****************************************/ /** * @dev Multiplies two precise units, and then truncates by the full scale * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @return Result after multiplying the two inputs and then dividing by the shared * scale unit */ function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) { return mulTruncateScale(x, y, FULL_SCALE); } /** * @dev Multiplies two precise units, and then truncates by the given scale. For example, * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18 * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @param scale Scale unit * @return Result after multiplying the two inputs and then dividing by the shared * scale unit */ function mulTruncateScale(uint256 x, uint256 y, uint256 scale) internal pure returns (uint256) { // e.g. assume scale = fullScale // z = 10e18 * 9e17 = 9e36 uint256 z = x.mul(y); // return 9e38 / 1e18 = 9e18 return z.div(scale); } /** * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @return Result after multiplying the two inputs and then dividing by the shared * scale unit, rounded up to the closest base unit. */ function mulTruncateCeil(uint256 x, uint256 y) internal pure returns (uint256) { // e.g. 8e17 * 17268172638 = 138145381104e17 uint256 scaled = x.mul(y); // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17 uint256 ceil = scaled.add(FULL_SCALE.sub(1)); // e.g. 13814538111.399...e18 / 1e18 = 13814538111 return ceil.div(FULL_SCALE); } /** * @dev Precisely divides two units, by first scaling the left hand operand. Useful * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17) * @param x Left hand input to division * @param y Right hand input to division * @return Result after multiplying the left operand by the scale, and * executing the division on the right hand input. */ function divPrecisely(uint256 x, uint256 y) internal pure returns (uint256) { // e.g. 8e18 * 1e18 = 8e36 uint256 z = x.mul(FULL_SCALE); // e.g. 8e36 / 10e18 = 8e17 return z.div(y); } /*************************************** RATIO FUNCS ****************************************/ /** * @dev Multiplies and truncates a token ratio, essentially flooring the result * i.e. How much mAsset is this bAsset worth? * @param x Left hand operand to multiplication (i.e Exact quantity) * @param ratio bAsset ratio * @return c Result after multiplying the two inputs and then dividing by the ratio scale */ function mulRatioTruncate(uint256 x, uint256 ratio) internal pure returns (uint256 c) { return mulTruncateScale(x, ratio, RATIO_SCALE); } /** * @dev Multiplies and truncates a token ratio, rounding up the result * i.e. How much mAsset is this bAsset worth? * @param x Left hand input to multiplication (i.e Exact quantity) * @param ratio bAsset ratio * @return Result after multiplying the two inputs and then dividing by the shared * ratio scale, rounded up to the closest base unit. */ function mulRatioTruncateCeil(uint256 x, uint256 ratio) internal pure returns (uint256) { // e.g. How much mAsset should I burn for this bAsset (x)? // 1e18 * 1e8 = 1e26 uint256 scaled = x.mul(ratio); // 1e26 + 9.99e7 = 100..00.999e8 uint256 ceil = scaled.add(RATIO_SCALE.sub(1)); // return 100..00.999e8 / 1e8 = 1e18 return ceil.div(RATIO_SCALE); } /** * @dev Precisely divides two ratioed units, by first scaling the left hand operand * i.e. How much bAsset is this mAsset worth? * @param x Left hand operand in division * @param ratio bAsset ratio * @return c Result after multiplying the left operand by the scale, and * executing the division on the right hand input. */ function divRatioPrecisely(uint256 x, uint256 ratio) internal pure returns (uint256 c) { // e.g. 1e14 * 1e8 = 1e22 uint256 y = x.mul(RATIO_SCALE); // return 1e22 / 1e12 = 1e10 return y.div(ratio); } /*************************************** HELPERS ****************************************/ /** * @dev Calculates minimum of two numbers * @param x Left hand input * @param y Right hand input * @return Minimum of the two inputs */ function min(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? y : x; } /** * @dev Calculated maximum of two numbers * @param x Left hand input * @param y Right hand input * @return Maximum of the two inputs */ function max(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? x : y; } /** * @dev Clamps a value to an upper bound * @param x Left hand input * @param upperBound Maximum possible value to return * @return Input x clamped to a maximum value, upperBound */ function clamp(uint256 x, uint256 upperBound) internal pure returns (uint256) { return x > upperBound ? upperBound : x; } }
// SPDX-License-Identifier: MIT // solhint-disable-next-line compiler-version pragma solidity >=0.4.24 <0.8.0; /** * @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 a proxied contract can't have 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. * * 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 {UpgradeableProxy-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. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function _isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; // solhint-disable-next-line no-inline-assembly assembly { cs := extcodesize(self) } return cs == 0; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../proxy/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 initializer { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal initializer { _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 make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @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.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.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 SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } 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' // solhint-disable-next-line max-line-length 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)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _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 // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 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://diligence.consensys.net/posts/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.5.11/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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "istanbul", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousDao","type":"address"},{"indexed":true,"internalType":"address","name":"newDao","type":"address"}],"name":"DaoChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"locktime","type":"uint256"},{"indexed":true,"internalType":"enum IncentivisedVotingLockup.LockAction","name":"action","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[],"name":"Expired","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousProtocolDao","type":"address"},{"indexed":true,"internalType":"address","name":"newProtocolDao","type":"address"}],"name":"ProtocolDaoChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAXTIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newDao","type":"address"}],"name":"changeDao","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newProtocolDao","type":"address"}],"name":"changeProtocolDao","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_unlockTime","type":"uint256"}],"name":"createLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dao","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expireContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"getLastUserPoint","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"increaseLockAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unlockTime","type":"uint256"}],"name":"increaseLockLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_dao","type":"address"},{"internalType":"address","name":"_protocolDao","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isDao","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isProtocolDao","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"locked","outputs":[{"internalType":"int128","name":"amount","type":"int128"},{"internalType":"uint256","name":"end","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pointHistory","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolDao","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"salvage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slopeChanges","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userPointEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userPointHistory","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50613a82806100206000396000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c806372f702f31161011a578063ad2e8c9b116100ad578063cbf9fe5f1161007c578063cbf9fe5f14610619578063d8826fec14610662578063ee00ef3a14610688578063efe7a50414610690578063f52a36f714610698576101fb565b8063ad2e8c9b14610598578063b52c05fe146105a0578063c2c4c5c1146105c3578063c4698ee5146105cb576101fb565b806395d89b41116100e957806395d89b4114610563578063981b24d01461056b5780639d8ec51814610588578063a980cbf814610590576101fb565b806372f702f3146104f257806381fc83bb146104fa578063863a03e0146105205780638ad4c44714610546576101fb565b80634162169f116101925780635719098b116101615780635719098b146103c457806363160282146103cc5780636cf1dbed146103e957806370a08231146104cc576101fb565b80634162169f146103505780634c2067c7146103745780634ee2cd7e146103905780635029e602146103bc576101fb565b8063313ce567116101ce578063313ce567146102c757806334d901a4146102cf5780633ccfd60b1461032b578063403f444714610333576101fb565b806306fdde03146102005780630f73d0b41461027d57806318160ddd146102875780632d95baf9146102a1575b600080fd5b6102086106ce565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61028561075c565b005b61028f610825565b60408051918252519081900360200190f35b610285600480360360208110156102b757600080fd5b50356001600160a01b03166108a7565b61028f6108f6565b6102fb600480360360408110156102e557600080fd5b506001600160a01b0381351690602001356108fc565b60408051600f95860b860b815293850b90940b602084015282840191909152606082015290519081900360800190f35b610285610949565b6102856004803603602081101561034957600080fd5b5035610954565b610358610b2b565b604080516001600160a01b039092168252519081900360200190f35b61037c610b3a565b604080519115158252519081900360200190f35b61028f600480360360408110156103a657600080fd5b506001600160a01b038135169060200135610b43565b61037c610e58565b61028f610e69565b610285600480360360208110156103e257600080fd5b5035610e6f565b610285600480360360a08110156103ff57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561042a57600080fd5b82018360208201111561043c57600080fd5b8035906020019184600183028401116401000000008311171561045e57600080fd5b91939092909160208101903564010000000081111561047c57600080fd5b82018360208201111561048e57600080fd5b803590602001918460018302840111640100000000831117156104b057600080fd5b91935091506001600160a01b038135811691602001351661109b565b61028f600480360360208110156104e257600080fd5b50356001600160a01b03166111d2565b6103586112e1565b61028f6004803603602081101561051057600080fd5b50356001600160a01b03166112f0565b6102856004803603602081101561053657600080fd5b50356001600160a01b0316611302565b6102fb6004803603602081101561055c57600080fd5b5035611473565b6102086114b4565b61028f6004803603602081101561058157600080fd5b503561150f565b61037c61175a565b61035861176b565b61028f61177a565b610285600480360360408110156105b657600080fd5b5080359060200135611781565b6102856119a5565b6105f1600480360360208110156105e157600080fd5b50356001600160a01b03166119b9565b60408051600f94850b850b815292840b90930b60208301528183015290519081900360600190f35b61063f6004803603602081101561062f57600080fd5b50356001600160a01b0316611a82565b6040518083600f0b600f0b81526020018281526020019250505060405180910390f35b6102856004803603602081101561067857600080fd5b50356001600160a01b0316611aa2565b61028f611b04565b61028f611b0c565b6106b5600480360360208110156106ae57600080fd5b5035611b12565b60408051600f92830b90920b8252519081900360200190f35b60a2805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107545780601f1061072957610100808354040283529160200191610754565b820191906000526020600020905b81548152906001019060200180831161073757829003601f168201915b505050505081565b61076461175a565b61079f5760405162461bcd60e51b81526004018080602001828103825260238152602001806138026023913960400191505060405180910390fd5b609b5460ff16156107ed576040805162461bcd60e51b815260206004820152601360248201527210dbdb9d1c9858dd081a5cc8195e1c1a5c9959606a1b604482015290519081900360640190fd5b609b805460ff191660011790556040517f203d82d8d99f63bfecc8335216735e0271df4249ea752b030f9ab305b94e5afe90600090a1565b609c54600090610833613724565b609d828154811061084057fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b938301939093526001830154908201526002909101546060820152905061089f8142611b27565b925050505b90565b6108af61175a565b6108ea5760405162461bcd60e51b81526004018080602001828103825260238152602001806138026023913960400191505060405180910390fd5b6108f381611c3b565b50565b60a45481565b609e602052816000526040600020818154811061091557fe5b6000918252602090912060039091020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b61095233611cdc565b565b6002600154141561099a576040805162461bcd60e51b815260206004820152601f6024820152600080516020613825833981519152604482015290519081900360640190fd5b6002600155609b5460ff16156109ed576040805162461bcd60e51b815260206004820152601360248201527210dbdb9d1c9858dd081a5cc8195e1c1a5c9959606a1b604482015290519081900360640190fd5b6109f5613752565b5060408051808201825233600081815260a160208181529482208054600f90810b900b8552929091528352600101549181019190915281610a7d576040805162461bcd60e51b815260206004820152601a60248201527f4d757374207374616b65206e6f6e207a65726f20616d6f756e74000000000000604482015290519081900360640190fd5b60008160000151600f0b13610ad2576040805162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b604482015290519081900360640190fd5b42816020015111610b145760405162461bcd60e51b81526004018080602001828103825260248152602001806138456024913960400191505060405180910390fd5b610b2333836000846001611f07565b505060018055565b6033546001600160a01b031690565b609b5460ff1681565b600043821115610b845760405162461bcd60e51b815260040180806020018281038252602281526020018061388a6022913960400191505060405180910390fd5b6000610b908484612030565b905080610ba1576000915050610e52565b610ba9613724565b6001600160a01b0385166000908152609e60205260409020805483908110610bcd57fe5b600091825260208083206040805160808101825260039094029091018054600f81810b810b810b8652600160801b909104810b810b900b92840192909252600182015490830152600201546060820152609c5490925090610c2e86836120f9565b9050610c38613724565b609d8281548110610c4557fe5b600091825260208083206040805160808101825260039094029091018054600f81810b810b810b8652600160801b909104810b810b900b9284019290925260018201549083015260020154606082015291508084841015610d5557610ca8613724565b609d610cbb86600163ffffffff61217c16565b81548110610cc557fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b938301939093526001830154908201526002909101546060808301829052860151919250610d309163ffffffff6121dd16565b9250610d4d846040015182604001516121dd90919063ffffffff16565b915050610d87565b6060830151610d6b90439063ffffffff6121dd16565b9150610d848360400151426121dd90919063ffffffff16565b90505b60408301518215610ddc57610dd9610dcc84610dc0610db388606001518f6121dd90919063ffffffff16565b869063ffffffff61221f16565b9063ffffffff61227816565b829063ffffffff61217c16565b90505b610e1e610e0d610df98960400151846121dd90919063ffffffff16565b60208a0151600f0b9063ffffffff6122ba16565b8851600f0b9063ffffffff61238516565b600f90810b810b8089526000910b12610e455750509351600f0b9550610e52945050505050565b6000985050505050505050505b92915050565b6033546001600160a01b0316331490565b609c5481565b60026001541415610eb5576040805162461bcd60e51b815260206004820152601f6024820152600080516020613825833981519152604482015290519081900360640190fd5b6002600155609b5460ff1615610f08576040805162461bcd60e51b815260206004820152601360248201527210dbdb9d1c9858dd081a5cc8195e1c1a5c9959606a1b604482015290519081900360640190fd5b610f10613752565b5060408051808201825233600081815260a160208181529482208054600f90810b900b855292825284526001909101549282019290925290610f51836123fd565b905060008260000151600f0b13610fa3576040805162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b604482015290519081900360640190fd5b42826020015111610fea576040805162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b604482015290519081900360640190fd5b81602001518111611042576040805162461bcd60e51b815260206004820152601b60248201527f43616e206f6e6c7920696e637265617365206c6f636b205745454b0000000000604482015290519081900360640190fd5b609a548111156110835760405162461bcd60e51b815260040180806020018281038252602c8152602001806138d2602c913960400191505060405180910390fd5b61109233600083856002611f07565b50506001805550565b600054610100900460ff16806110b457506110b4612416565b806110c2575060005460ff16155b6110fd5760405162461bcd60e51b815260040180806020018281038252602e8152602001806138fe602e913960400191505060405180910390fd5b600054610100900460ff16158015611128576000805460ff1961ff0019909116610100171660011790555b61113061241c565b611139836124c5565b61114282612517565b6111b68888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a915089908190840183828082843760009201919091525061256992505050565b80156111c8576000805461ff00191690555b5050505050505050565b6001600160a01b0381166000908152609f6020526040812054806111fa5760009150506112dc565b611202613724565b6001600160a01b0384166000908152609e6020526040902080548390811061122657fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b938301939093526001830154908201819052600290920154606082015291506112bb906112aa9061129690429063ffffffff6121dd16565b6020840151600f0b9063ffffffff6122ba16565b8251600f0b9063ffffffff61238516565b600f90810b810b8083526000910b12156112d457600081525b51600f0b9150505b919050565b6099546001600160a01b031681565b609f6020526000908152604090205481565b61130a610e58565b61135b576040805162461bcd60e51b815260206004820152601a60248201527f474f563a2063616c6c6572206973206e6f74207468652044616f000000000000604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b1580156113a557600080fd5b505afa1580156113b9573d6000803e3d6000fd5b505050506040513d60208110156113cf57600080fd5b505190506001600160a01b03821663a9059cbb6113ea610b2b565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561143a57600080fd5b505af115801561144e573d6000803e3d6000fd5b505050506040513d602081101561146457600080fd5b505161146f57600080fd5b5050565b609d818154811061148057fe5b6000918252602090912060039091020180546001820154600290920154600f82810b9450600160801b90920490910b919084565b60a3805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107545780601f1061072957610100808354040283529160200191610754565b6000438211156115505760405162461bcd60e51b815260040180806020018281038252602281526020018061388a6022913960400191505060405180910390fd5b609c54600061155f84836120f9565b9050611569613724565b609d828154811061157657fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b93830193909352600183015490820152600290910154606082018190529091508510156115e157600093505050506112dc565b6000838310156116d8576115f3613724565b609d61160685600163ffffffff61217c16565b8154811061161057fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b938301939093526001830154908201526002909101546060808301829052850151919250146116d2576116cf61168f846060015183606001516121dd90919063ffffffff16565b610dc06116ad866040015185604001516121dd90919063ffffffff16565b60608701516116c3908c9063ffffffff6121dd16565b9063ffffffff61221f16565b91505b50611730565b438260600151146117305761172d6116fd8360600151436121dd90919063ffffffff16565b610dc06117178560400151426121dd90919063ffffffff16565b60608601516116c3908b9063ffffffff6121dd16565b90505b6117508261174b83856040015161217c90919063ffffffff16565b611b27565b9695505050505050565b6066546001600160a01b0316331490565b6066546001600160a01b031690565b62093a8090565b600260015414156117c7576040805162461bcd60e51b815260206004820152601f6024820152600080516020613825833981519152604482015290519081900360640190fd5b6002600155609b5460ff161561181a576040805162461bcd60e51b815260206004820152601360248201527210dbdb9d1c9858dd081a5cc8195e1c1a5c9959606a1b604482015290519081900360640190fd5b6000611825826123fd565b905061182f613752565b5060408051808201825233600081815260a160208181529482208054600f90810b900b85529290915283526001015491810191909152836118b7576040805162461bcd60e51b815260206004820152601a60248201527f4d757374207374616b65206e6f6e207a65726f20616d6f756e74000000000000604482015290519081900360640190fd5b8051600f0b1561190e576040805162461bcd60e51b815260206004820152601960248201527f5769746864726177206f6c6420746f6b656e7320666972737400000000000000604482015290519081900360640190fd5b42821161194c5760405162461bcd60e51b81526004018080602001828103825260268152602001806139d96026913960400191505060405180910390fd5b609a5482111561198d5760405162461bcd60e51b815260040180806020018281038252602c8152602001806138d2602c913960400191505060405180910390fd5b61199b338584846000611f07565b5050600180555050565b6119ad613752565b6108f360008283612775565b6001600160a01b0381166000908152609f602052604081205481908190806119eb575060009250829150819050611a7b565b6119f3613724565b6001600160a01b0386166000908152609e60205260409020805483908110611a1757fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b808652600160801b909204810b810b900b9484018590526001820154928401839052600290910154606090930192909252909650909450925050505b9193909250565b60a16020526000908152604090208054600190910154600f9190910b9082565b611aaa610e58565b611afb576040805162461bcd60e51b815260206004820152601a60248201527f474f563a2063616c6c6572206973206e6f74207468652044616f000000000000604482015290519081900360640190fd5b6108f381612fe0565b6305a39a8081565b609a5481565b60a060205260009081526040902054600f0b81565b6000611b31613724565b8390506000611b4382604001516123fd565b905060005b60ff811015611c1957611b648262093a8063ffffffff61217c16565b9150600085831115611b7857859250611b8c565b50600082815260a06020526040902054600f0b5b611bce611bbd611ba98660400151866121dd90919063ffffffff16565b6020870151600f0b9063ffffffff6122ba16565b8551600f0b9063ffffffff61238516565b600f90810b900b845282861415611be55750611c19565b6020840151611bfd90600f0b8263ffffffff61309716565b600f90810b900b60208501525060408301829052600101611b48565b5060008260000151600f0b1215611c2f57600082525b5051600f0b9392505050565b6001600160a01b038116611c805760405162461bcd60e51b815260040180806020018281038252602381526020018061396e6023913960400191505060405180910390fd5b6066546040516001600160a01b038084169216907f370ebd24a4f14b319c7fa82630f6571686fc22c4c000f9b0523dd6dc5e3405db90600090a3606680546001600160a01b0319166001600160a01b0392909216919091179055565b60026001541415611d22576040805162461bcd60e51b815260206004820152601f6024820152600080516020613825833981519152604482015290519081900360640190fd5b6002600155611d2f613752565b506040805180820182526001600160a01b038316600081815260a160208181529482208054600f90810b900b8552929091528352600101549181018290529042101580611d7e5750609b5460ff165b611dc8576040805162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b604482015290519081900360640190fd5b60008160000151600f0b13611e24576040805162461bcd60e51b815260206004820152601f60248201527f4d757374206861766520736f6d657468696e6720746f20776974686472617700604482015290519081900360640190fd5b8051600f0b611e31613752565b50604080518082018252600080825260208083018281526001600160a01b038816835260a190915292902081518154600f9190910b6001600160801b03166001600160801b03199091161781559151600190920191909155609b5460ff16611e9e57611e9e848483612775565b609954611ebb906001600160a01b0316858463ffffffff61310f16565b6040805183815242602082015281516001600160a01b038716927ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568928290030190a25050600180555050565b611f0f613752565b50604080518082019091528251600f90810b80835260208086015190840152611f3f910b8663ffffffff61309716565b600f90810b900b81528315611f5657602081018490525b6001600160a01b038616600090815260a16020908152604090912082518154600f9190910b6001600160801b03166001600160801b031990911617815590820151600190910155611fa8868483612775565b8415611fcc57609954611fcc906001600160a01b031687308863ffffffff61316616565b816002811115611fd857fe5b60208083015160408051898152928301919091524282820152516001600160a01b038916917fbe9cf0e939c614fad640a623a53ba0a807c8cb503c4c4c8dacabe27b86ff2dd5919081900360600190a3505050505050565b6001600160a01b0382166000908152609f60205260408120548190815b60808110156120ef57818310612062576120ef565b600061208a6002610dc0600161207e888863ffffffff61217c16565b9063ffffffff61217c16565b6001600160a01b0388166000908152609e6020526040902080549192508791839081106120b357fe5b906000526020600020906003020160020154116120d2578093506120e6565b6120e381600163ffffffff6121dd16565b92505b5060010161204d565b5090949350505050565b60008082815b60808110156120ef57818310612114576120ef565b60006121306002610dc0600161207e888863ffffffff61217c16565b905086609d828154811061214057fe5b9060005260206000209060030201600201541161215f57809350612173565b61217081600163ffffffff6121dd16565b92505b506001016120ff565b6000828201838110156121d6576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60006121d683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506131c6565b60008261222e57506000610e52565b8282028284828161223b57fe5b04146121d65760405162461bcd60e51b81526004018080602001828103825260218152602001806139916021913960400191505060405180910390fd5b60006121d683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061325d565b600082600f0b600014156122d057506000610e52565b82600f0b6000191480156122ef5750600f82900b60016001607f1b0319145b1561232b5760405162461bcd60e51b81526004018080602001828103825260278152602001806139b26027913960400191505060405180910390fd5b6000828402905082600f0b84600f0b82600f0b8161234557fe5b05600f0b146121d65760405162461bcd60e51b81526004018080602001828103825260278152602001806139b26027913960400191505060405180910390fd5b6000818303600f83900b82138015906123a4575083600f0b81600f0b13155b806123c25750600083600f0b1280156123c2575083600f0b81600f0b135b6121d65760405162461bcd60e51b81526004018080602001828103825260248152602001806139ff6024913960400191505060405180910390fd5b6000610e5262093a806116c3848263ffffffff61227816565b303b1590565b600054610100900460ff16806124355750612435612416565b80612443575060005460ff16155b61247e5760405162461bcd60e51b815260040180806020018281038252602e8152602001806138fe602e913960400191505060405180910390fd5b600054610100900460ff161580156124a9576000805460ff1961ff0019909116610100171660011790555b6124b16132c2565b80156108f3576000805461ff001916905550565b603380546001600160a01b0319166001600160a01b0383811691909117918290556040519116906000907ffcde6c827a52b0870bc44ed9b10212272e18c9ea1725b772e9b493750afd8da4908290a350565b606680546001600160a01b0319166001600160a01b0383811691909117918290556040519116906000907f370ebd24a4f14b319c7fa82630f6571686fc22c4c000f9b0523dd6dc5e3405db908290a350565b609980546001600160a01b0319166001600160a01b03851617905561258c613724565b506040805160808101825260008082526020808301828152428486019081524360608601908152609d8054600181018255955285517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b6003909602958601805494516001600160801b0319909516600f92830b6001600160801b03908116919091178116600160801b9690930b169490940217909255517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7c840155517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7d90920191909155825163313ce56760e01b8152925191926001600160a01b0387169263313ce56792600480840193919291829003018186803b1580156126ae57600080fd5b505afa1580156126c2573d6000803e3d6000fd5b505050506040513d60208110156126d857600080fd5b505160ff1660a4819055601210156127215760405162461bcd60e51b815260040180806020018281038252602181526020018061394d6021913960400191505060405180910390fd5b82516127349060a2906020860190613769565b5081516127489060a3906020850190613769565b50601260a455612762426305a39a8063ffffffff61217c16565b609a555050609b805460ff191690555050565b61277d613724565b612785613724565b609c5460009081906001600160a01b03881615612a20574287602001511180156127b6575060008760000151600f0b135b156128055786516127d490600f0b6305a39a8063ffffffff61336716565b600f90810b900b6020808701919091528701516127fb90611ba9904263ffffffff6121dd16565b600f90810b900b85525b42866020015111801561281f575060008660000151600f0b135b1561288257855161283d90600f0b6305a39a8063ffffffff61336716565b600f90810b900b60208086019190915286015161287890612864904263ffffffff6121dd16565b6020860151600f0b9063ffffffff6122ba16565b600f90810b900b84525b6001600160a01b0388166000908152609f602052604090205480612924576001600160a01b0389166000908152609e60209081526040808320805460018181018355918552938390208a516003909502018054938b0151600f90810b6001600160801b03908116600160801b029690910b81166001600160801b0319909516949094179093169390931782558801519181019190915560608701516002909101555b61293581600163ffffffff61217c16565b6001600160a01b038a166000818152609f6020908152604080832094909455428985019081524360608b01908152938352609e82528483208054600181810183559185528385208c5160039092020180548d860151600f90810b6001600160801b03908116600160801b0294820b81166001600160801b03199093169290921790911692909217815592519183019190915593516002909101558b810151825260a08152929020549189015191900b945015612a1e57876020015187602001511415612a0357839250612a1e565b602080880151600090815260a09091526040902054600f0b92505b505b612a28613724565b50604080516080810182526000808252602082015242918101919091524360608201528115612ab457609d8281548110612a5e57fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b93830193909352600183015490820152600290910154606082015290505b6040810151612ac1613724565b5060408051608081018252600080825260208201819052848301805193830193909352606080860151908301529151909190421115612b3657612b33612b148560400151426121dd90919063ffffffff16565b610dc0612b2e8760600151436121dd90919063ffffffff16565b613437565b90505b6000612b41846123fd565b905060005b60ff811015612d5257612b628262093a8063ffffffff61217c16565b9150600042831115612b7657429250612b8a565b50600082815260a06020526040902054600f0b5b6000612b9f610df9858963ffffffff6121dd16565b8851909150612bb790600f0b8263ffffffff61238516565b600f90810b810b89526020890151612bd6910b8363ffffffff61309716565b600f90810b810b60208a015288516000910b1215612bf357600088525b60008860200151600f0b1215612c0b57600060208901525b83965083886040018181525050612c53612c42612c358860400151876121dd90919063ffffffff16565b879063ffffffff61345116565b60608801519063ffffffff61217c16565b6060890152612c6989600163ffffffff61217c16565b985042841415612c80575050436060870152612d52565b609d8054600181018255600091909152885160039091027fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b8101805460208c0151600f90810b6001600160801b03908116600160801b029590910b81166001600160801b031990921691909117169290921790915560408901517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7c82015560608901517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7d909101555050600101612b46565b50609c8690556001600160a01b038d1615612e0957612d9c612d888b602001518b60200151600f0b61238590919063ffffffff16565b6020870151600f0b9063ffffffff61309716565b600f90810b810b60208701528a518a51612dd492612dc39291900b9063ffffffff61238516565b8651600f0b9063ffffffff61309716565b600f90810b810b865260208601516000910b1215612df457600060208601525b60008560000151600f0b1215612e0957600085525b609d8054600181018255600091909152855160039091027fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b810180546020890151600f90810b6001600160801b03908116600160801b029590910b81166001600160801b031990921691909117169290921790915560408601517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7c82015560608601517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7d909101556001600160a01b038d1615612fd157428c602001511115612f6757612f068a6020015189600f0b61309790919063ffffffff16565b97508b602001518b602001511415612f3557612f32896020015189600f0b61238590919063ffffffff16565b97505b60208c810151600090815260a09091526040902080546001600160801b0319166001600160801b03600f8b900b161790555b428b602001511115612fd1578b602001518b602001511115612fd157612f9d896020015188600f0b61238590919063ffffffff16565b60208c810151600090815260a09091526040902080546001600160801b0319166001600160801b03600f84900b1617905596505b50505050505050505050505050565b6001600160a01b03811661303b576040805162461bcd60e51b815260206004820152601a60248201527f474f563a206e65772044616f2069732061646472657373283029000000000000604482015290519081900360640190fd5b6033546040516001600160a01b038084169216907ffcde6c827a52b0870bc44ed9b10212272e18c9ea1725b772e9b493750afd8da490600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b6000828201600f83900b82138015906130b6575083600f0b81600f0b12155b806130d45750600083600f0b1280156130d4575083600f0b81600f0b125b6121d65760405162461bcd60e51b81526004018080602001828103825260218152602001806138696021913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052613161908490613466565b505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526131c0908590613466565b50505050565b600081848411156132555760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561321a578181015183820152602001613202565b50505050905090810190601f1680156132475780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836132ac5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561321a578181015183820152602001613202565b5060008385816132b857fe5b0495945050505050565b600054610100900460ff16806132db57506132db612416565b806132e9575060005460ff16155b6133245760405162461bcd60e51b815260040180806020018281038252602e8152602001806138fe602e913960400191505060405180910390fd5b600054610100900460ff1615801561334f576000805460ff1961ff0019909116610100171660011790555b6001805580156108f3576000805461ff001916905550565b600081600f0b600014156133c2576040805162461bcd60e51b815260206004820181905260248201527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604482015290519081900360640190fd5b81600f0b6000191480156133e15750600f83900b60016001607f1b0319145b1561341d5760405162461bcd60e51b815260040180806020018281038252602181526020018061392c6021913960400191505060405180910390fd5b600082600f0b84600f0b8161342e57fe5b05949350505050565b6000610e5282670de0b6b3a764000063ffffffff61221f16565b60006121d68383670de0b6b3a7640000613517565b60606134bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166135459092919063ffffffff16565b805190915015613161578080602001905160208110156134da57600080fd5b50516131615760405162461bcd60e51b815260040180806020018281038252602a815260200180613a23602a913960400191505060405180910390fd5b60008061352a858563ffffffff61221f16565b905061353c818463ffffffff61227816565b95945050505050565b6060613554848460008561355c565b949350505050565b60608247101561359d5760405162461bcd60e51b81526004018080602001828103825260268152602001806138ac6026913960400191505060405180910390fd5b6135a6856136b8565b6135f7576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106136365780518252601f199092019160209182019101613617565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613698576040519150601f19603f3d011682016040523d82523d6000602084013e61369d565b606091505b50915091506136ad8282866136be565b979650505050505050565b3b151590565b606083156136cd5750816121d6565b8251156136dd5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561321a578181015183820152602001613202565b60405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525090565b604080518082019091526000808252602082015290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106137aa57805160ff19168380011785556137d7565b828001600101855582156137d7579182015b828111156137d75782518255916020019190600101906137bc565b506137e39291506137e7565b5090565b6108a491905b808211156137e357600081556001016137ed56fe474f563a2063616c6c6572206973206e6f74207468652050726f746f636f6c2044616f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0043616e6e6f742061646420746f2065787069726564206c6f636b2e2057697468647261775369676e6564536166654d6174683a206164646974696f6e206f766572666c6f774d757374207061737320626c6f636b206e756d62657220696e207468652070617374416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c566f74696e67206c6f636b2063616e2062652033207965617273206d61782028756e74696c207265636f6c29496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65645369676e6564536166654d6174683a206469766973696f6e206f766572666c6f7743616e6e6f742068617665206d6f7265207468616e20313820646563696d616c73474f563a206e65772050726f746f636f6c2044616f2069732061646472657373283029536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c79206c6f636b20756e74696c2074696d6520696e20746865206675747572655369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122002c8ea0f120c536e077c29133ee511f07d38696b10a9b965502a9b71763b67d864736f6c63430006080033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c806372f702f31161011a578063ad2e8c9b116100ad578063cbf9fe5f1161007c578063cbf9fe5f14610619578063d8826fec14610662578063ee00ef3a14610688578063efe7a50414610690578063f52a36f714610698576101fb565b8063ad2e8c9b14610598578063b52c05fe146105a0578063c2c4c5c1146105c3578063c4698ee5146105cb576101fb565b806395d89b41116100e957806395d89b4114610563578063981b24d01461056b5780639d8ec51814610588578063a980cbf814610590576101fb565b806372f702f3146104f257806381fc83bb146104fa578063863a03e0146105205780638ad4c44714610546576101fb565b80634162169f116101925780635719098b116101615780635719098b146103c457806363160282146103cc5780636cf1dbed146103e957806370a08231146104cc576101fb565b80634162169f146103505780634c2067c7146103745780634ee2cd7e146103905780635029e602146103bc576101fb565b8063313ce567116101ce578063313ce567146102c757806334d901a4146102cf5780633ccfd60b1461032b578063403f444714610333576101fb565b806306fdde03146102005780630f73d0b41461027d57806318160ddd146102875780632d95baf9146102a1575b600080fd5b6102086106ce565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61028561075c565b005b61028f610825565b60408051918252519081900360200190f35b610285600480360360208110156102b757600080fd5b50356001600160a01b03166108a7565b61028f6108f6565b6102fb600480360360408110156102e557600080fd5b506001600160a01b0381351690602001356108fc565b60408051600f95860b860b815293850b90940b602084015282840191909152606082015290519081900360800190f35b610285610949565b6102856004803603602081101561034957600080fd5b5035610954565b610358610b2b565b604080516001600160a01b039092168252519081900360200190f35b61037c610b3a565b604080519115158252519081900360200190f35b61028f600480360360408110156103a657600080fd5b506001600160a01b038135169060200135610b43565b61037c610e58565b61028f610e69565b610285600480360360208110156103e257600080fd5b5035610e6f565b610285600480360360a08110156103ff57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561042a57600080fd5b82018360208201111561043c57600080fd5b8035906020019184600183028401116401000000008311171561045e57600080fd5b91939092909160208101903564010000000081111561047c57600080fd5b82018360208201111561048e57600080fd5b803590602001918460018302840111640100000000831117156104b057600080fd5b91935091506001600160a01b038135811691602001351661109b565b61028f600480360360208110156104e257600080fd5b50356001600160a01b03166111d2565b6103586112e1565b61028f6004803603602081101561051057600080fd5b50356001600160a01b03166112f0565b6102856004803603602081101561053657600080fd5b50356001600160a01b0316611302565b6102fb6004803603602081101561055c57600080fd5b5035611473565b6102086114b4565b61028f6004803603602081101561058157600080fd5b503561150f565b61037c61175a565b61035861176b565b61028f61177a565b610285600480360360408110156105b657600080fd5b5080359060200135611781565b6102856119a5565b6105f1600480360360208110156105e157600080fd5b50356001600160a01b03166119b9565b60408051600f94850b850b815292840b90930b60208301528183015290519081900360600190f35b61063f6004803603602081101561062f57600080fd5b50356001600160a01b0316611a82565b6040518083600f0b600f0b81526020018281526020019250505060405180910390f35b6102856004803603602081101561067857600080fd5b50356001600160a01b0316611aa2565b61028f611b04565b61028f611b0c565b6106b5600480360360208110156106ae57600080fd5b5035611b12565b60408051600f92830b90920b8252519081900360200190f35b60a2805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107545780601f1061072957610100808354040283529160200191610754565b820191906000526020600020905b81548152906001019060200180831161073757829003601f168201915b505050505081565b61076461175a565b61079f5760405162461bcd60e51b81526004018080602001828103825260238152602001806138026023913960400191505060405180910390fd5b609b5460ff16156107ed576040805162461bcd60e51b815260206004820152601360248201527210dbdb9d1c9858dd081a5cc8195e1c1a5c9959606a1b604482015290519081900360640190fd5b609b805460ff191660011790556040517f203d82d8d99f63bfecc8335216735e0271df4249ea752b030f9ab305b94e5afe90600090a1565b609c54600090610833613724565b609d828154811061084057fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b938301939093526001830154908201526002909101546060820152905061089f8142611b27565b925050505b90565b6108af61175a565b6108ea5760405162461bcd60e51b81526004018080602001828103825260238152602001806138026023913960400191505060405180910390fd5b6108f381611c3b565b50565b60a45481565b609e602052816000526040600020818154811061091557fe5b6000918252602090912060039091020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b61095233611cdc565b565b6002600154141561099a576040805162461bcd60e51b815260206004820152601f6024820152600080516020613825833981519152604482015290519081900360640190fd5b6002600155609b5460ff16156109ed576040805162461bcd60e51b815260206004820152601360248201527210dbdb9d1c9858dd081a5cc8195e1c1a5c9959606a1b604482015290519081900360640190fd5b6109f5613752565b5060408051808201825233600081815260a160208181529482208054600f90810b900b8552929091528352600101549181019190915281610a7d576040805162461bcd60e51b815260206004820152601a60248201527f4d757374207374616b65206e6f6e207a65726f20616d6f756e74000000000000604482015290519081900360640190fd5b60008160000151600f0b13610ad2576040805162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b604482015290519081900360640190fd5b42816020015111610b145760405162461bcd60e51b81526004018080602001828103825260248152602001806138456024913960400191505060405180910390fd5b610b2333836000846001611f07565b505060018055565b6033546001600160a01b031690565b609b5460ff1681565b600043821115610b845760405162461bcd60e51b815260040180806020018281038252602281526020018061388a6022913960400191505060405180910390fd5b6000610b908484612030565b905080610ba1576000915050610e52565b610ba9613724565b6001600160a01b0385166000908152609e60205260409020805483908110610bcd57fe5b600091825260208083206040805160808101825260039094029091018054600f81810b810b810b8652600160801b909104810b810b900b92840192909252600182015490830152600201546060820152609c5490925090610c2e86836120f9565b9050610c38613724565b609d8281548110610c4557fe5b600091825260208083206040805160808101825260039094029091018054600f81810b810b810b8652600160801b909104810b810b900b9284019290925260018201549083015260020154606082015291508084841015610d5557610ca8613724565b609d610cbb86600163ffffffff61217c16565b81548110610cc557fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b938301939093526001830154908201526002909101546060808301829052860151919250610d309163ffffffff6121dd16565b9250610d4d846040015182604001516121dd90919063ffffffff16565b915050610d87565b6060830151610d6b90439063ffffffff6121dd16565b9150610d848360400151426121dd90919063ffffffff16565b90505b60408301518215610ddc57610dd9610dcc84610dc0610db388606001518f6121dd90919063ffffffff16565b869063ffffffff61221f16565b9063ffffffff61227816565b829063ffffffff61217c16565b90505b610e1e610e0d610df98960400151846121dd90919063ffffffff16565b60208a0151600f0b9063ffffffff6122ba16565b8851600f0b9063ffffffff61238516565b600f90810b810b8089526000910b12610e455750509351600f0b9550610e52945050505050565b6000985050505050505050505b92915050565b6033546001600160a01b0316331490565b609c5481565b60026001541415610eb5576040805162461bcd60e51b815260206004820152601f6024820152600080516020613825833981519152604482015290519081900360640190fd5b6002600155609b5460ff1615610f08576040805162461bcd60e51b815260206004820152601360248201527210dbdb9d1c9858dd081a5cc8195e1c1a5c9959606a1b604482015290519081900360640190fd5b610f10613752565b5060408051808201825233600081815260a160208181529482208054600f90810b900b855292825284526001909101549282019290925290610f51836123fd565b905060008260000151600f0b13610fa3576040805162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b604482015290519081900360640190fd5b42826020015111610fea576040805162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b604482015290519081900360640190fd5b81602001518111611042576040805162461bcd60e51b815260206004820152601b60248201527f43616e206f6e6c7920696e637265617365206c6f636b205745454b0000000000604482015290519081900360640190fd5b609a548111156110835760405162461bcd60e51b815260040180806020018281038252602c8152602001806138d2602c913960400191505060405180910390fd5b61109233600083856002611f07565b50506001805550565b600054610100900460ff16806110b457506110b4612416565b806110c2575060005460ff16155b6110fd5760405162461bcd60e51b815260040180806020018281038252602e8152602001806138fe602e913960400191505060405180910390fd5b600054610100900460ff16158015611128576000805460ff1961ff0019909116610100171660011790555b61113061241c565b611139836124c5565b61114282612517565b6111b68888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a915089908190840183828082843760009201919091525061256992505050565b80156111c8576000805461ff00191690555b5050505050505050565b6001600160a01b0381166000908152609f6020526040812054806111fa5760009150506112dc565b611202613724565b6001600160a01b0384166000908152609e6020526040902080548390811061122657fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b938301939093526001830154908201819052600290920154606082015291506112bb906112aa9061129690429063ffffffff6121dd16565b6020840151600f0b9063ffffffff6122ba16565b8251600f0b9063ffffffff61238516565b600f90810b810b8083526000910b12156112d457600081525b51600f0b9150505b919050565b6099546001600160a01b031681565b609f6020526000908152604090205481565b61130a610e58565b61135b576040805162461bcd60e51b815260206004820152601a60248201527f474f563a2063616c6c6572206973206e6f74207468652044616f000000000000604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b1580156113a557600080fd5b505afa1580156113b9573d6000803e3d6000fd5b505050506040513d60208110156113cf57600080fd5b505190506001600160a01b03821663a9059cbb6113ea610b2b565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561143a57600080fd5b505af115801561144e573d6000803e3d6000fd5b505050506040513d602081101561146457600080fd5b505161146f57600080fd5b5050565b609d818154811061148057fe5b6000918252602090912060039091020180546001820154600290920154600f82810b9450600160801b90920490910b919084565b60a3805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107545780601f1061072957610100808354040283529160200191610754565b6000438211156115505760405162461bcd60e51b815260040180806020018281038252602281526020018061388a6022913960400191505060405180910390fd5b609c54600061155f84836120f9565b9050611569613724565b609d828154811061157657fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b93830193909352600183015490820152600290910154606082018190529091508510156115e157600093505050506112dc565b6000838310156116d8576115f3613724565b609d61160685600163ffffffff61217c16565b8154811061161057fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b938301939093526001830154908201526002909101546060808301829052850151919250146116d2576116cf61168f846060015183606001516121dd90919063ffffffff16565b610dc06116ad866040015185604001516121dd90919063ffffffff16565b60608701516116c3908c9063ffffffff6121dd16565b9063ffffffff61221f16565b91505b50611730565b438260600151146117305761172d6116fd8360600151436121dd90919063ffffffff16565b610dc06117178560400151426121dd90919063ffffffff16565b60608601516116c3908b9063ffffffff6121dd16565b90505b6117508261174b83856040015161217c90919063ffffffff16565b611b27565b9695505050505050565b6066546001600160a01b0316331490565b6066546001600160a01b031690565b62093a8090565b600260015414156117c7576040805162461bcd60e51b815260206004820152601f6024820152600080516020613825833981519152604482015290519081900360640190fd5b6002600155609b5460ff161561181a576040805162461bcd60e51b815260206004820152601360248201527210dbdb9d1c9858dd081a5cc8195e1c1a5c9959606a1b604482015290519081900360640190fd5b6000611825826123fd565b905061182f613752565b5060408051808201825233600081815260a160208181529482208054600f90810b900b85529290915283526001015491810191909152836118b7576040805162461bcd60e51b815260206004820152601a60248201527f4d757374207374616b65206e6f6e207a65726f20616d6f756e74000000000000604482015290519081900360640190fd5b8051600f0b1561190e576040805162461bcd60e51b815260206004820152601960248201527f5769746864726177206f6c6420746f6b656e7320666972737400000000000000604482015290519081900360640190fd5b42821161194c5760405162461bcd60e51b81526004018080602001828103825260268152602001806139d96026913960400191505060405180910390fd5b609a5482111561198d5760405162461bcd60e51b815260040180806020018281038252602c8152602001806138d2602c913960400191505060405180910390fd5b61199b338584846000611f07565b5050600180555050565b6119ad613752565b6108f360008283612775565b6001600160a01b0381166000908152609f602052604081205481908190806119eb575060009250829150819050611a7b565b6119f3613724565b6001600160a01b0386166000908152609e60205260409020805483908110611a1757fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b808652600160801b909204810b810b900b9484018590526001820154928401839052600290910154606090930192909252909650909450925050505b9193909250565b60a16020526000908152604090208054600190910154600f9190910b9082565b611aaa610e58565b611afb576040805162461bcd60e51b815260206004820152601a60248201527f474f563a2063616c6c6572206973206e6f74207468652044616f000000000000604482015290519081900360640190fd5b6108f381612fe0565b6305a39a8081565b609a5481565b60a060205260009081526040902054600f0b81565b6000611b31613724565b8390506000611b4382604001516123fd565b905060005b60ff811015611c1957611b648262093a8063ffffffff61217c16565b9150600085831115611b7857859250611b8c565b50600082815260a06020526040902054600f0b5b611bce611bbd611ba98660400151866121dd90919063ffffffff16565b6020870151600f0b9063ffffffff6122ba16565b8551600f0b9063ffffffff61238516565b600f90810b900b845282861415611be55750611c19565b6020840151611bfd90600f0b8263ffffffff61309716565b600f90810b900b60208501525060408301829052600101611b48565b5060008260000151600f0b1215611c2f57600082525b5051600f0b9392505050565b6001600160a01b038116611c805760405162461bcd60e51b815260040180806020018281038252602381526020018061396e6023913960400191505060405180910390fd5b6066546040516001600160a01b038084169216907f370ebd24a4f14b319c7fa82630f6571686fc22c4c000f9b0523dd6dc5e3405db90600090a3606680546001600160a01b0319166001600160a01b0392909216919091179055565b60026001541415611d22576040805162461bcd60e51b815260206004820152601f6024820152600080516020613825833981519152604482015290519081900360640190fd5b6002600155611d2f613752565b506040805180820182526001600160a01b038316600081815260a160208181529482208054600f90810b900b8552929091528352600101549181018290529042101580611d7e5750609b5460ff165b611dc8576040805162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b604482015290519081900360640190fd5b60008160000151600f0b13611e24576040805162461bcd60e51b815260206004820152601f60248201527f4d757374206861766520736f6d657468696e6720746f20776974686472617700604482015290519081900360640190fd5b8051600f0b611e31613752565b50604080518082018252600080825260208083018281526001600160a01b038816835260a190915292902081518154600f9190910b6001600160801b03166001600160801b03199091161781559151600190920191909155609b5460ff16611e9e57611e9e848483612775565b609954611ebb906001600160a01b0316858463ffffffff61310f16565b6040805183815242602082015281516001600160a01b038716927ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568928290030190a25050600180555050565b611f0f613752565b50604080518082019091528251600f90810b80835260208086015190840152611f3f910b8663ffffffff61309716565b600f90810b900b81528315611f5657602081018490525b6001600160a01b038616600090815260a16020908152604090912082518154600f9190910b6001600160801b03166001600160801b031990911617815590820151600190910155611fa8868483612775565b8415611fcc57609954611fcc906001600160a01b031687308863ffffffff61316616565b816002811115611fd857fe5b60208083015160408051898152928301919091524282820152516001600160a01b038916917fbe9cf0e939c614fad640a623a53ba0a807c8cb503c4c4c8dacabe27b86ff2dd5919081900360600190a3505050505050565b6001600160a01b0382166000908152609f60205260408120548190815b60808110156120ef57818310612062576120ef565b600061208a6002610dc0600161207e888863ffffffff61217c16565b9063ffffffff61217c16565b6001600160a01b0388166000908152609e6020526040902080549192508791839081106120b357fe5b906000526020600020906003020160020154116120d2578093506120e6565b6120e381600163ffffffff6121dd16565b92505b5060010161204d565b5090949350505050565b60008082815b60808110156120ef57818310612114576120ef565b60006121306002610dc0600161207e888863ffffffff61217c16565b905086609d828154811061214057fe5b9060005260206000209060030201600201541161215f57809350612173565b61217081600163ffffffff6121dd16565b92505b506001016120ff565b6000828201838110156121d6576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60006121d683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506131c6565b60008261222e57506000610e52565b8282028284828161223b57fe5b04146121d65760405162461bcd60e51b81526004018080602001828103825260218152602001806139916021913960400191505060405180910390fd5b60006121d683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061325d565b600082600f0b600014156122d057506000610e52565b82600f0b6000191480156122ef5750600f82900b60016001607f1b0319145b1561232b5760405162461bcd60e51b81526004018080602001828103825260278152602001806139b26027913960400191505060405180910390fd5b6000828402905082600f0b84600f0b82600f0b8161234557fe5b05600f0b146121d65760405162461bcd60e51b81526004018080602001828103825260278152602001806139b26027913960400191505060405180910390fd5b6000818303600f83900b82138015906123a4575083600f0b81600f0b13155b806123c25750600083600f0b1280156123c2575083600f0b81600f0b135b6121d65760405162461bcd60e51b81526004018080602001828103825260248152602001806139ff6024913960400191505060405180910390fd5b6000610e5262093a806116c3848263ffffffff61227816565b303b1590565b600054610100900460ff16806124355750612435612416565b80612443575060005460ff16155b61247e5760405162461bcd60e51b815260040180806020018281038252602e8152602001806138fe602e913960400191505060405180910390fd5b600054610100900460ff161580156124a9576000805460ff1961ff0019909116610100171660011790555b6124b16132c2565b80156108f3576000805461ff001916905550565b603380546001600160a01b0319166001600160a01b0383811691909117918290556040519116906000907ffcde6c827a52b0870bc44ed9b10212272e18c9ea1725b772e9b493750afd8da4908290a350565b606680546001600160a01b0319166001600160a01b0383811691909117918290556040519116906000907f370ebd24a4f14b319c7fa82630f6571686fc22c4c000f9b0523dd6dc5e3405db908290a350565b609980546001600160a01b0319166001600160a01b03851617905561258c613724565b506040805160808101825260008082526020808301828152428486019081524360608601908152609d8054600181018255955285517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b6003909602958601805494516001600160801b0319909516600f92830b6001600160801b03908116919091178116600160801b9690930b169490940217909255517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7c840155517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7d90920191909155825163313ce56760e01b8152925191926001600160a01b0387169263313ce56792600480840193919291829003018186803b1580156126ae57600080fd5b505afa1580156126c2573d6000803e3d6000fd5b505050506040513d60208110156126d857600080fd5b505160ff1660a4819055601210156127215760405162461bcd60e51b815260040180806020018281038252602181526020018061394d6021913960400191505060405180910390fd5b82516127349060a2906020860190613769565b5081516127489060a3906020850190613769565b50601260a455612762426305a39a8063ffffffff61217c16565b609a555050609b805460ff191690555050565b61277d613724565b612785613724565b609c5460009081906001600160a01b03881615612a20574287602001511180156127b6575060008760000151600f0b135b156128055786516127d490600f0b6305a39a8063ffffffff61336716565b600f90810b900b6020808701919091528701516127fb90611ba9904263ffffffff6121dd16565b600f90810b900b85525b42866020015111801561281f575060008660000151600f0b135b1561288257855161283d90600f0b6305a39a8063ffffffff61336716565b600f90810b900b60208086019190915286015161287890612864904263ffffffff6121dd16565b6020860151600f0b9063ffffffff6122ba16565b600f90810b900b84525b6001600160a01b0388166000908152609f602052604090205480612924576001600160a01b0389166000908152609e60209081526040808320805460018181018355918552938390208a516003909502018054938b0151600f90810b6001600160801b03908116600160801b029690910b81166001600160801b0319909516949094179093169390931782558801519181019190915560608701516002909101555b61293581600163ffffffff61217c16565b6001600160a01b038a166000818152609f6020908152604080832094909455428985019081524360608b01908152938352609e82528483208054600181810183559185528385208c5160039092020180548d860151600f90810b6001600160801b03908116600160801b0294820b81166001600160801b03199093169290921790911692909217815592519183019190915593516002909101558b810151825260a08152929020549189015191900b945015612a1e57876020015187602001511415612a0357839250612a1e565b602080880151600090815260a09091526040902054600f0b92505b505b612a28613724565b50604080516080810182526000808252602082015242918101919091524360608201528115612ab457609d8281548110612a5e57fe5b60009182526020918290206040805160808101825260039093029091018054600f81810b810b810b8552600160801b909104810b810b900b93830193909352600183015490820152600290910154606082015290505b6040810151612ac1613724565b5060408051608081018252600080825260208201819052848301805193830193909352606080860151908301529151909190421115612b3657612b33612b148560400151426121dd90919063ffffffff16565b610dc0612b2e8760600151436121dd90919063ffffffff16565b613437565b90505b6000612b41846123fd565b905060005b60ff811015612d5257612b628262093a8063ffffffff61217c16565b9150600042831115612b7657429250612b8a565b50600082815260a06020526040902054600f0b5b6000612b9f610df9858963ffffffff6121dd16565b8851909150612bb790600f0b8263ffffffff61238516565b600f90810b810b89526020890151612bd6910b8363ffffffff61309716565b600f90810b810b60208a015288516000910b1215612bf357600088525b60008860200151600f0b1215612c0b57600060208901525b83965083886040018181525050612c53612c42612c358860400151876121dd90919063ffffffff16565b879063ffffffff61345116565b60608801519063ffffffff61217c16565b6060890152612c6989600163ffffffff61217c16565b985042841415612c80575050436060870152612d52565b609d8054600181018255600091909152885160039091027fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b8101805460208c0151600f90810b6001600160801b03908116600160801b029590910b81166001600160801b031990921691909117169290921790915560408901517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7c82015560608901517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7d909101555050600101612b46565b50609c8690556001600160a01b038d1615612e0957612d9c612d888b602001518b60200151600f0b61238590919063ffffffff16565b6020870151600f0b9063ffffffff61309716565b600f90810b810b60208701528a518a51612dd492612dc39291900b9063ffffffff61238516565b8651600f0b9063ffffffff61309716565b600f90810b810b865260208601516000910b1215612df457600060208601525b60008560000151600f0b1215612e0957600085525b609d8054600181018255600091909152855160039091027fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b810180546020890151600f90810b6001600160801b03908116600160801b029590910b81166001600160801b031990921691909117169290921790915560408601517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7c82015560608601517fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7d909101556001600160a01b038d1615612fd157428c602001511115612f6757612f068a6020015189600f0b61309790919063ffffffff16565b97508b602001518b602001511415612f3557612f32896020015189600f0b61238590919063ffffffff16565b97505b60208c810151600090815260a09091526040902080546001600160801b0319166001600160801b03600f8b900b161790555b428b602001511115612fd1578b602001518b602001511115612fd157612f9d896020015188600f0b61238590919063ffffffff16565b60208c810151600090815260a09091526040902080546001600160801b0319166001600160801b03600f84900b1617905596505b50505050505050505050505050565b6001600160a01b03811661303b576040805162461bcd60e51b815260206004820152601a60248201527f474f563a206e65772044616f2069732061646472657373283029000000000000604482015290519081900360640190fd5b6033546040516001600160a01b038084169216907ffcde6c827a52b0870bc44ed9b10212272e18c9ea1725b772e9b493750afd8da490600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b6000828201600f83900b82138015906130b6575083600f0b81600f0b12155b806130d45750600083600f0b1280156130d4575083600f0b81600f0b125b6121d65760405162461bcd60e51b81526004018080602001828103825260218152602001806138696021913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052613161908490613466565b505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526131c0908590613466565b50505050565b600081848411156132555760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561321a578181015183820152602001613202565b50505050905090810190601f1680156132475780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836132ac5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561321a578181015183820152602001613202565b5060008385816132b857fe5b0495945050505050565b600054610100900460ff16806132db57506132db612416565b806132e9575060005460ff16155b6133245760405162461bcd60e51b815260040180806020018281038252602e8152602001806138fe602e913960400191505060405180910390fd5b600054610100900460ff1615801561334f576000805460ff1961ff0019909116610100171660011790555b6001805580156108f3576000805461ff001916905550565b600081600f0b600014156133c2576040805162461bcd60e51b815260206004820181905260248201527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604482015290519081900360640190fd5b81600f0b6000191480156133e15750600f83900b60016001607f1b0319145b1561341d5760405162461bcd60e51b815260040180806020018281038252602181526020018061392c6021913960400191505060405180910390fd5b600082600f0b84600f0b8161342e57fe5b05949350505050565b6000610e5282670de0b6b3a764000063ffffffff61221f16565b60006121d68383670de0b6b3a7640000613517565b60606134bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166135459092919063ffffffff16565b805190915015613161578080602001905160208110156134da57600080fd5b50516131615760405162461bcd60e51b815260040180806020018281038252602a815260200180613a23602a913960400191505060405180910390fd5b60008061352a858563ffffffff61221f16565b905061353c818463ffffffff61227816565b95945050505050565b6060613554848460008561355c565b949350505050565b60608247101561359d5760405162461bcd60e51b81526004018080602001828103825260268152602001806138ac6026913960400191505060405180910390fd5b6135a6856136b8565b6135f7576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106136365780518252601f199092019160209182019101613617565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613698576040519150601f19603f3d011682016040523d82523d6000602084013e61369d565b606091505b50915091506136ad8282866136be565b979650505050505050565b3b151590565b606083156136cd5750816121d6565b8251156136dd5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561321a578181015183820152602001613202565b60405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525090565b604080518082019091526000808252602082015290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106137aa57805160ff19168380011785556137d7565b828001600101855582156137d7579182015b828111156137d75782518255916020019190600101906137bc565b506137e39291506137e7565b5090565b6108a491905b808211156137e357600081556001016137ed56fe474f563a2063616c6c6572206973206e6f74207468652050726f746f636f6c2044616f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0043616e6e6f742061646420746f2065787069726564206c6f636b2e2057697468647261775369676e6564536166654d6174683a206164646974696f6e206f766572666c6f774d757374207061737320626c6f636b206e756d62657220696e207468652070617374416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c566f74696e67206c6f636b2063616e2062652033207965617273206d61782028756e74696c207265636f6c29496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65645369676e6564536166654d6174683a206469766973696f6e206f766572666c6f7743616e6e6f742068617665206d6f7265207468616e20313820646563696d616c73474f563a206e65772050726f746f636f6c2044616f2069732061646472657373283029536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c79206c6f636b20756e74696c2074696d6520696e20746865206675747572655369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122002c8ea0f120c536e077c29133ee511f07d38696b10a9b965502a9b71763b67d864736f6c63430006080033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.