Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 17,656 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Vote | 12345389 | 1354 days ago | IN | 0 ETH | 0.00084531 | ||||
Vote | 12318226 | 1359 days ago | IN | 0 ETH | 0.00166244 | ||||
Vote | 12307770 | 1360 days ago | IN | 0 ETH | 0.00157791 | ||||
Vote | 12307770 | 1360 days ago | IN | 0 ETH | 0.00098619 | ||||
Vote | 12294683 | 1362 days ago | IN | 0 ETH | 0.00270499 | ||||
Vote | 12276617 | 1365 days ago | IN | 0 ETH | 0.00493097 | ||||
Vote | 12272232 | 1366 days ago | IN | 0 ETH | 0.03459978 | ||||
Vote | 12270776 | 1366 days ago | IN | 0 ETH | 0.02824939 | ||||
Vote | 12268168 | 1366 days ago | IN | 0 ETH | 0.0256947 | ||||
Vote | 12266627 | 1366 days ago | IN | 0 ETH | 0.01799447 | ||||
Vote | 12265877 | 1367 days ago | IN | 0 ETH | 0.01215292 | ||||
Vote | 12265639 | 1367 days ago | IN | 0 ETH | 0.02263821 | ||||
Vote | 12262088 | 1367 days ago | IN | 0 ETH | 0.02660679 | ||||
Vote | 12262062 | 1367 days ago | IN | 0 ETH | 0.07429977 | ||||
Vote | 12262013 | 1367 days ago | IN | 0 ETH | 0.03832255 | ||||
Vote | 12262010 | 1367 days ago | IN | 0 ETH | 0.06752766 | ||||
Vote | 12261380 | 1367 days ago | IN | 0 ETH | 0.02798433 | ||||
Vote | 12261160 | 1367 days ago | IN | 0 ETH | 0.01062082 | ||||
Vote | 12259999 | 1367 days ago | IN | 0 ETH | 0.01896192 | ||||
Vote | 12258906 | 1368 days ago | IN | 0 ETH | 0.00812849 | ||||
Vote | 12258899 | 1368 days ago | IN | 0 ETH | 0.01511003 | ||||
Vote | 12258884 | 1368 days ago | IN | 0 ETH | 0.04350291 | ||||
Vote | 12258811 | 1368 days ago | IN | 0 ETH | 0.01521952 | ||||
Vote | 12258395 | 1368 days ago | IN | 0 ETH | 0.02200809 | ||||
Vote | 12258389 | 1368 days ago | IN | 0 ETH | 0.03463453 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
10403248 | 1653 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
KyberDao
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-07-06 */ // File: contracts/sol6/utils/zeppelin/SafeMath.sol pragma solidity 0.6.6; /** * @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) { // Solidity only automatically asserts when dividing by 0 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; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } } // File: contracts/sol6/Dao/IEpochUtils.sol pragma solidity 0.6.6; interface IEpochUtils { function epochPeriodInSeconds() external view returns (uint256); function firstEpochStartTimestamp() external view returns (uint256); function getCurrentEpochNumber() external view returns (uint256); function getEpochNumber(uint256 timestamp) external view returns (uint256); } // File: contracts/sol6/Dao/EpochUtils.sol pragma solidity 0.6.6; contract EpochUtils is IEpochUtils { using SafeMath for uint256; uint256 public override epochPeriodInSeconds; uint256 public override firstEpochStartTimestamp; function getCurrentEpochNumber() public view override returns (uint256) { return getEpochNumber(now); } function getEpochNumber(uint256 timestamp) public view override returns (uint256) { if (timestamp < firstEpochStartTimestamp || epochPeriodInSeconds == 0) { return 0; } // ((timestamp - firstEpochStartTimestamp) / epochPeriodInSeconds) + 1; return ((timestamp.sub(firstEpochStartTimestamp)).div(epochPeriodInSeconds)).add(1); } } // File: contracts/sol6/Dao/DaoOperator.sol pragma solidity 0.6.6; contract DaoOperator { address public daoOperator; constructor(address _daoOperator) public { require(_daoOperator != address(0), "daoOperator is 0"); daoOperator = _daoOperator; } modifier onlyDaoOperator() { require(msg.sender == daoOperator, "only daoOperator"); _; } } // File: contracts/sol6/IERC20.sol pragma solidity 0.6.6; interface IERC20 { event Approval(address indexed _owner, address indexed _spender, uint256 _value); function approve(address _spender, uint256 _value) external returns (bool success); function transfer(address _to, uint256 _value) external returns (bool success); function transferFrom( address _from, address _to, uint256 _value ) external returns (bool success); function allowance(address _owner, address _spender) external view returns (uint256 remaining); function balanceOf(address _owner) external view returns (uint256 balance); function decimals() external view returns (uint8 digits); function totalSupply() external view returns (uint256 supply); } // to support backward compatible contract name -- so function signature remains same abstract contract ERC20 is IERC20 { } // File: contracts/sol6/utils/zeppelin/ReentrancyGuard.sol pragma solidity 0.6.6; /** * @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]. */ contract ReentrancyGuard { bool private _notEntered; constructor () internal { // Storing an initial 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 percetange 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. _notEntered = true; } /** * @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(_notEntered, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _notEntered = false; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _notEntered = true; } } // File: contracts/sol6/Dao/IKyberStaking.sol pragma solidity 0.6.6; interface IKyberStaking is IEpochUtils { event Delegated( address indexed staker, address indexed representative, uint256 indexed epoch, bool isDelegated ); event Deposited(uint256 curEpoch, address indexed staker, uint256 amount); event Withdraw(uint256 indexed curEpoch, address indexed staker, uint256 amount); function initAndReturnStakerDataForCurrentEpoch(address staker) external returns ( uint256 stake, uint256 delegatedStake, address representative ); function deposit(uint256 amount) external; function delegate(address dAddr) external; function withdraw(uint256 amount) external; /** * @notice return combine data (stake, delegatedStake, representative) of a staker * @dev allow to get staker data up to current epoch + 1 */ function getStakerData(address staker, uint256 epoch) external view returns ( uint256 stake, uint256 delegatedStake, address representative ); function getLatestStakerData(address staker) external view returns ( uint256 stake, uint256 delegatedStake, address representative ); /** * @notice return raw data of a staker for an epoch * WARN: should be used only for initialized data * if data has not been initialized, it will return all 0 * pool master shouldn't use this function to compute/distribute rewards of pool members */ function getStakerRawData(address staker, uint256 epoch) external view returns ( uint256 stake, uint256 delegatedStake, address representative ); } // File: contracts/sol6/IKyberDao.sol pragma solidity 0.6.6; interface IKyberDao is IEpochUtils { event Voted(address indexed staker, uint indexed epoch, uint indexed campaignID, uint option); function getLatestNetworkFeeDataWithCache() external returns (uint256 feeInBps, uint256 expiryTimestamp); function getLatestBRRDataWithCache() external returns ( uint256 burnInBps, uint256 rewardInBps, uint256 rebateInBps, uint256 epoch, uint256 expiryTimestamp ); function handleWithdrawal(address staker, uint256 penaltyAmount) external; function vote(uint256 campaignID, uint256 option) external; function getLatestNetworkFeeData() external view returns (uint256 feeInBps, uint256 expiryTimestamp); function shouldBurnRewardForEpoch(uint256 epoch) external view returns (bool); /** * @dev return staker's reward percentage in precision for a past epoch only * fee handler should call this function when a staker wants to claim reward * return 0 if staker has no votes or stakes */ function getPastEpochRewardPercentageInPrecision(address staker, uint256 epoch) external view returns (uint256); /** * @dev return staker's reward percentage in precision for the current epoch * reward percentage is not finalized until the current epoch is ended */ function getCurrentEpochRewardPercentageInPrecision(address staker) external view returns (uint256); } // File: contracts/sol6/Dao/KyberStaking.sol pragma solidity 0.6.6; /** * @notice This contract is using SafeMath for uint, which is inherited from EpochUtils * Some events are moved to interface, easier for public uses * Staking contract will be deployed by KyberDao's contract */ contract KyberStaking is IKyberStaking, EpochUtils, ReentrancyGuard { struct StakerData { uint256 stake; uint256 delegatedStake; address representative; } IERC20 public immutable kncToken; IKyberDao public immutable kyberDao; // staker data per epoch, including stake, delegated stake and representative mapping(uint256 => mapping(address => StakerData)) internal stakerPerEpochData; // latest data of a staker, including stake, delegated stake, representative mapping(address => StakerData) internal stakerLatestData; // true/false: if data has been initialized at an epoch for a staker mapping(uint256 => mapping(address => bool)) internal hasInited; // event is fired if something is wrong with withdrawal // even though the withdrawal is still successful event WithdrawDataUpdateFailed(uint256 curEpoch, address staker, uint256 amount); constructor( IERC20 _kncToken, uint256 _epochPeriod, uint256 _startTimestamp, IKyberDao _kyberDao ) public { require(_epochPeriod > 0, "ctor: epoch period is 0"); require(_startTimestamp >= now, "ctor: start in the past"); require(_kncToken != IERC20(0), "ctor: kncToken 0"); require(_kyberDao != IKyberDao(0), "ctor: kyberDao 0"); epochPeriodInSeconds = _epochPeriod; firstEpochStartTimestamp = _startTimestamp; kncToken = _kncToken; kyberDao = _kyberDao; } /** * @dev calls to set delegation for msg.sender, will take effect from the next epoch * @param newRepresentative address to delegate to */ function delegate(address newRepresentative) external override { require(newRepresentative != address(0), "delegate: representative 0"); address staker = msg.sender; uint256 curEpoch = getCurrentEpochNumber(); initDataIfNeeded(staker, curEpoch); address curRepresentative = stakerPerEpochData[curEpoch + 1][staker].representative; // nothing changes here if (newRepresentative == curRepresentative) { return; } uint256 updatedStake = stakerPerEpochData[curEpoch + 1][staker].stake; // reduce delegatedStake for curRepresentative if needed if (curRepresentative != staker) { initDataIfNeeded(curRepresentative, curEpoch); stakerPerEpochData[curEpoch + 1][curRepresentative].delegatedStake = stakerPerEpochData[curEpoch + 1][curRepresentative].delegatedStake.sub(updatedStake); stakerLatestData[curRepresentative].delegatedStake = stakerLatestData[curRepresentative].delegatedStake.sub(updatedStake); emit Delegated(staker, curRepresentative, curEpoch, false); } stakerLatestData[staker].representative = newRepresentative; stakerPerEpochData[curEpoch + 1][staker].representative = newRepresentative; // ignore if staker is delegating back to himself if (newRepresentative != staker) { initDataIfNeeded(newRepresentative, curEpoch); stakerPerEpochData[curEpoch + 1][newRepresentative].delegatedStake = stakerPerEpochData[curEpoch + 1][newRepresentative].delegatedStake.add(updatedStake); stakerLatestData[newRepresentative].delegatedStake = stakerLatestData[newRepresentative].delegatedStake.add(updatedStake); emit Delegated(staker, newRepresentative, curEpoch, true); } } /** * @dev call to stake more KNC for msg.sender * @param amount amount of KNC to stake */ function deposit(uint256 amount) external override { require(amount > 0, "deposit: amount is 0"); uint256 curEpoch = getCurrentEpochNumber(); address staker = msg.sender; // collect KNC token from staker require( kncToken.transferFrom(staker, address(this), amount), "deposit: can not get token" ); initDataIfNeeded(staker, curEpoch); stakerPerEpochData[curEpoch + 1][staker].stake = stakerPerEpochData[curEpoch + 1][staker].stake.add(amount); stakerLatestData[staker].stake = stakerLatestData[staker].stake.add(amount); // increase delegated stake for address that staker has delegated to (if it is not staker) address representative = stakerPerEpochData[curEpoch + 1][staker].representative; if (representative != staker) { initDataIfNeeded(representative, curEpoch); stakerPerEpochData[curEpoch + 1][representative].delegatedStake = stakerPerEpochData[curEpoch + 1][representative].delegatedStake.add(amount); stakerLatestData[representative].delegatedStake = stakerLatestData[representative].delegatedStake.add(amount); } emit Deposited(curEpoch, staker, amount); } /** * @dev call to withdraw KNC from staking, it could affect reward when calling KyberDao handleWithdrawal * @param amount amount of KNC to withdraw */ function withdraw(uint256 amount) external override nonReentrant { require(amount > 0, "withdraw: amount is 0"); uint256 curEpoch = getCurrentEpochNumber(); address staker = msg.sender; require( stakerLatestData[staker].stake >= amount, "withdraw: latest amount staked < withdrawal amount" ); (bool success, ) = address(this).call( abi.encodeWithSignature( "handleWithdrawal(address,uint256,uint256)", staker, amount, curEpoch ) ); if (!success) { // Note: should catch this event to check if something went wrong emit WithdrawDataUpdateFailed(curEpoch, staker, amount); } stakerLatestData[staker].stake = stakerLatestData[staker].stake.sub(amount); // transfer KNC back to staker require(kncToken.transfer(staker, amount), "withdraw: can not transfer knc"); emit Withdraw(curEpoch, staker, amount); } /** * @dev initialize data if needed, then return staker's data for current epoch * @dev for safe, only allow calling this func from KyberDao address * @param staker - staker's address to initialize and get data for */ function initAndReturnStakerDataForCurrentEpoch(address staker) external override returns ( uint256 stake, uint256 delegatedStake, address representative ) { require( msg.sender == address(kyberDao), "initAndReturnData: only kyberDao" ); uint256 curEpoch = getCurrentEpochNumber(); initDataIfNeeded(staker, curEpoch); StakerData memory stakerData = stakerPerEpochData[curEpoch][staker]; stake = stakerData.stake; delegatedStake = stakerData.delegatedStake; representative = stakerData.representative; } /** * @notice return raw data of a staker for an epoch * WARN: should be used only for initialized data * if data has not been initialized, it will return all 0 * pool master shouldn't use this function to compute/distribute rewards of pool members * @dev in KyberDao contract, if staker wants to claim reward for past epoch, * we must know the staker's data for that epoch * if the data has not been initialized, it means staker hasn't done any action -> no reward */ function getStakerRawData(address staker, uint256 epoch) external view override returns ( uint256 stake, uint256 delegatedStake, address representative ) { StakerData memory stakerData = stakerPerEpochData[epoch][staker]; stake = stakerData.stake; delegatedStake = stakerData.delegatedStake; representative = stakerData.representative; } /** * @dev allow to get data up to current epoch + 1 */ function getStake(address staker, uint256 epoch) external view returns (uint256) { uint256 curEpoch = getCurrentEpochNumber(); if (epoch > curEpoch + 1) { return 0; } uint256 i = epoch; while (true) { if (hasInited[i][staker]) { return stakerPerEpochData[i][staker].stake; } if (i == 0) { break; } i--; } return 0; } /** * @dev allow to get data up to current epoch + 1 */ function getDelegatedStake(address staker, uint256 epoch) external view returns (uint256) { uint256 curEpoch = getCurrentEpochNumber(); if (epoch > curEpoch + 1) { return 0; } uint256 i = epoch; while (true) { if (hasInited[i][staker]) { return stakerPerEpochData[i][staker].delegatedStake; } if (i == 0) { break; } i--; } return 0; } /** * @dev allow to get data up to current epoch + 1 */ function getRepresentative(address staker, uint256 epoch) external view returns (address) { uint256 curEpoch = getCurrentEpochNumber(); if (epoch > curEpoch + 1) { return address(0); } uint256 i = epoch; while (true) { if (hasInited[i][staker]) { return stakerPerEpochData[i][staker].representative; } if (i == 0) { break; } i--; } // not delegated to anyone, default to yourself return staker; } /** * @notice return combine data (stake, delegatedStake, representative) of a staker * @dev allow to get staker data up to current epoch + 1 */ function getStakerData(address staker, uint256 epoch) external view override returns ( uint256 stake, uint256 delegatedStake, address representative ) { stake = 0; delegatedStake = 0; representative = address(0); uint256 curEpoch = getCurrentEpochNumber(); if (epoch > curEpoch + 1) { return (stake, delegatedStake, representative); } uint256 i = epoch; while (true) { if (hasInited[i][staker]) { stake = stakerPerEpochData[i][staker].stake; delegatedStake = stakerPerEpochData[i][staker].delegatedStake; representative = stakerPerEpochData[i][staker].representative; return (stake, delegatedStake, representative); } if (i == 0) { break; } i--; } // not delegated to anyone, default to yourself representative = staker; } function getLatestRepresentative(address staker) external view returns (address) { return stakerLatestData[staker].representative == address(0) ? staker : stakerLatestData[staker].representative; } function getLatestDelegatedStake(address staker) external view returns (uint256) { return stakerLatestData[staker].delegatedStake; } function getLatestStakeBalance(address staker) external view returns (uint256) { return stakerLatestData[staker].stake; } function getLatestStakerData(address staker) external view override returns ( uint256 stake, uint256 delegatedStake, address representative ) { stake = stakerLatestData[staker].stake; delegatedStake = stakerLatestData[staker].delegatedStake; representative = stakerLatestData[staker].representative == address(0) ? staker : stakerLatestData[staker].representative; } /** * @dev separate logics from withdraw, so staker can withdraw as long as amount <= staker's deposit amount calling this function from withdraw function, ignore reverting * @param staker staker that is withdrawing * @param amount amount to withdraw * @param curEpoch current epoch */ function handleWithdrawal( address staker, uint256 amount, uint256 curEpoch ) external { require(msg.sender == address(this), "only staking contract"); initDataIfNeeded(staker, curEpoch); // Note: update latest stake will be done after this function // update staker's data for next epoch stakerPerEpochData[curEpoch + 1][staker].stake = stakerPerEpochData[curEpoch + 1][staker].stake.sub(amount); address representative = stakerPerEpochData[curEpoch][staker].representative; uint256 curStake = stakerPerEpochData[curEpoch][staker].stake; uint256 lStakeBal = stakerLatestData[staker].stake.sub(amount); uint256 newStake = curStake.min(lStakeBal); uint256 reduceAmount = curStake.sub(newStake); // newStake is always <= curStake if (reduceAmount > 0) { if (representative != staker) { initDataIfNeeded(representative, curEpoch); // staker has delegated to representative, withdraw will affect representative's delegated stakes stakerPerEpochData[curEpoch][representative].delegatedStake = stakerPerEpochData[curEpoch][representative].delegatedStake.sub(reduceAmount); } stakerPerEpochData[curEpoch][staker].stake = newStake; // call KyberDao to reduce reward, if staker has delegated, then pass his representative if (address(kyberDao) != address(0)) { // don't revert if KyberDao revert so data will be updated correctly (bool success, ) = address(kyberDao).call( abi.encodeWithSignature( "handleWithdrawal(address,uint256)", representative, reduceAmount ) ); if (!success) { emit WithdrawDataUpdateFailed(curEpoch, staker, amount); } } } representative = stakerPerEpochData[curEpoch + 1][staker].representative; if (representative != staker) { initDataIfNeeded(representative, curEpoch); stakerPerEpochData[curEpoch + 1][representative].delegatedStake = stakerPerEpochData[curEpoch + 1][representative].delegatedStake.sub(amount); stakerLatestData[representative].delegatedStake = stakerLatestData[representative].delegatedStake.sub(amount); } } /** * @dev initialize data if it has not been initialized yet * @param staker staker's address to initialize * @param epoch should be current epoch */ function initDataIfNeeded(address staker, uint256 epoch) internal { address representative = stakerLatestData[staker].representative; if (representative == address(0)) { // not delegate to anyone, consider as delegate to yourself stakerLatestData[staker].representative = staker; representative = staker; } uint256 ldStake = stakerLatestData[staker].delegatedStake; uint256 lStakeBal = stakerLatestData[staker].stake; if (!hasInited[epoch][staker]) { hasInited[epoch][staker] = true; StakerData storage stakerData = stakerPerEpochData[epoch][staker]; stakerData.representative = representative; stakerData.delegatedStake = ldStake; stakerData.stake = lStakeBal; } // whenever stakers deposit/withdraw/delegate, the current and next epoch data need to be updated // as the result, we will also initialize data for staker at the next epoch if (!hasInited[epoch + 1][staker]) { hasInited[epoch + 1][staker] = true; StakerData storage nextEpochStakerData = stakerPerEpochData[epoch + 1][staker]; nextEpochStakerData.representative = representative; nextEpochStakerData.delegatedStake = ldStake; nextEpochStakerData.stake = lStakeBal; } } } // File: contracts/sol6/utils/Utils5.sol pragma solidity 0.6.6; /** * @title Kyber utility file * mostly shared constants and rate calculation helpers * inherited by most of kyber contracts. * previous utils implementations are for previous solidity versions. */ contract Utils5 { IERC20 internal constant ETH_TOKEN_ADDRESS = IERC20( 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE ); uint256 internal constant PRECISION = (10**18); uint256 internal constant MAX_QTY = (10**28); // 10B tokens uint256 internal constant MAX_RATE = (PRECISION * 10**7); // up to 10M tokens per eth uint256 internal constant MAX_DECIMALS = 18; uint256 internal constant ETH_DECIMALS = 18; uint256 constant BPS = 10000; // Basic Price Steps. 1 step = 0.01% uint256 internal constant MAX_ALLOWANCE = uint256(-1); // token.approve inifinite mapping(IERC20 => uint256) internal decimals; function getUpdateDecimals(IERC20 token) internal returns (uint256) { if (token == ETH_TOKEN_ADDRESS) return ETH_DECIMALS; // save storage access uint256 tokenDecimals = decimals[token]; // moreover, very possible that old tokens have decimals 0 // these tokens will just have higher gas fees. if (tokenDecimals == 0) { tokenDecimals = token.decimals(); decimals[token] = tokenDecimals; } return tokenDecimals; } function setDecimals(IERC20 token) internal { if (decimals[token] != 0) return; //already set if (token == ETH_TOKEN_ADDRESS) { decimals[token] = ETH_DECIMALS; } else { decimals[token] = token.decimals(); } } /// @dev get the balance of a user. /// @param token The token type /// @return The balance function getBalance(IERC20 token, address user) internal view returns (uint256) { if (token == ETH_TOKEN_ADDRESS) { return user.balance; } else { return token.balanceOf(user); } } function getDecimals(IERC20 token) internal view returns (uint256) { if (token == ETH_TOKEN_ADDRESS) return ETH_DECIMALS; // save storage access uint256 tokenDecimals = decimals[token]; // moreover, very possible that old tokens have decimals 0 // these tokens will just have higher gas fees. if (tokenDecimals == 0) return token.decimals(); return tokenDecimals; } function calcDestAmount( IERC20 src, IERC20 dest, uint256 srcAmount, uint256 rate ) internal view returns (uint256) { return calcDstQty(srcAmount, getDecimals(src), getDecimals(dest), rate); } function calcSrcAmount( IERC20 src, IERC20 dest, uint256 destAmount, uint256 rate ) internal view returns (uint256) { return calcSrcQty(destAmount, getDecimals(src), getDecimals(dest), rate); } function calcDstQty( uint256 srcQty, uint256 srcDecimals, uint256 dstDecimals, uint256 rate ) internal pure returns (uint256) { require(srcQty <= MAX_QTY, "srcQty > MAX_QTY"); require(rate <= MAX_RATE, "rate > MAX_RATE"); if (dstDecimals >= srcDecimals) { require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS"); return (srcQty * rate * (10**(dstDecimals - srcDecimals))) / PRECISION; } else { require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS"); return (srcQty * rate) / (PRECISION * (10**(srcDecimals - dstDecimals))); } } function calcSrcQty( uint256 dstQty, uint256 srcDecimals, uint256 dstDecimals, uint256 rate ) internal pure returns (uint256) { require(dstQty <= MAX_QTY, "dstQty > MAX_QTY"); require(rate <= MAX_RATE, "rate > MAX_RATE"); //source quantity is rounded up. to avoid dest quantity being too low. uint256 numerator; uint256 denominator; if (srcDecimals >= dstDecimals) { require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS"); numerator = (PRECISION * dstQty * (10**(srcDecimals - dstDecimals))); denominator = rate; } else { require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS"); numerator = (PRECISION * dstQty); denominator = (rate * (10**(dstDecimals - srcDecimals))); } return (numerator + denominator - 1) / denominator; //avoid rounding down errors } function calcRateFromQty( uint256 srcAmount, uint256 destAmount, uint256 srcDecimals, uint256 dstDecimals ) internal pure returns (uint256) { require(srcAmount <= MAX_QTY, "srcAmount > MAX_QTY"); require(destAmount <= MAX_QTY, "destAmount > MAX_QTY"); if (dstDecimals >= srcDecimals) { require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS"); return ((destAmount * PRECISION) / ((10**(dstDecimals - srcDecimals)) * srcAmount)); } else { require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS"); return ((destAmount * PRECISION * (10**(srcDecimals - dstDecimals))) / srcAmount); } } function minOf(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? y : x; } } // File: contracts/sol6/Dao/KyberDao.sol pragma solidity 0.6.6; /** * @notice This contract is using SafeMath for uint, which is inherited from EpochUtils Some events are moved to interface, easier for public uses * @dev Network fee campaign: options are fee in bps * BRR fee handler campaign: options are combined of rebate (left most 128 bits) + reward (right most 128 bits) * General campaign: options are from 1 to num_options */ contract KyberDao is IKyberDao, EpochUtils, ReentrancyGuard, Utils5, DaoOperator { // max number of campaigns for each epoch uint256 public constant MAX_EPOCH_CAMPAIGNS = 10; // max number of options for each campaign uint256 public constant MAX_CAMPAIGN_OPTIONS = 8; uint256 internal constant POWER_128 = 2**128; enum CampaignType {General, NetworkFee, FeeHandlerBRR} struct FormulaData { uint256 minPercentageInPrecision; uint256 cInPrecision; uint256 tInPrecision; } struct CampaignVoteData { uint256 totalVotes; uint256[] votePerOption; } struct Campaign { CampaignType campaignType; bool campaignExists; uint256 startTimestamp; uint256 endTimestamp; uint256 totalKNCSupply; // total KNC supply at the time campaign was created FormulaData formulaData; // formula params for concluding campaign result bytes link; // link to KIP, explaination of options, etc. uint256[] options; // data of options CampaignVoteData campaignVoteData; // campaign vote data: total votes + vote per option } struct BRRData { uint256 rewardInBps; uint256 rebateInBps; } uint256 public minCampaignDurationInSeconds = 4 days; IERC20 public immutable kncToken; IKyberStaking public immutable staking; // use to generate increasing campaign ID uint256 public numberCampaigns = 0; mapping(uint256 => Campaign) internal campaignData; // epochCampaigns[epoch]: list campaign IDs for an epoch (epoch => campaign IDs) mapping(uint256 => uint256[]) internal epochCampaigns; // totalEpochPoints[epoch]: total points for an epoch (epoch => total points) mapping(uint256 => uint256) internal totalEpochPoints; // numberVotes[staker][epoch]: number of campaigns that the staker has voted in an epoch mapping(address => mapping(uint256 => uint256)) public numberVotes; // stakerVotedOption[staker][campaignID]: staker's voted option ID for a campaign mapping(address => mapping(uint256 => uint256)) public stakerVotedOption; uint256 internal latestNetworkFeeResult; // epoch => campaignID for network fee campaigns mapping(uint256 => uint256) public networkFeeCampaigns; // latest BRR data (reward and rebate in bps) BRRData internal latestBrrData; // epoch => campaignID for brr campaigns mapping(uint256 => uint256) public brrCampaigns; event NewCampaignCreated( CampaignType campaignType, uint256 indexed campaignID, uint256 startTimestamp, uint256 endTimestamp, uint256 minPercentageInPrecision, uint256 cInPrecision, uint256 tInPrecision, uint256[] options, bytes link ); event CancelledCampaign(uint256 indexed campaignID); constructor( uint256 _epochPeriod, uint256 _startTimestamp, IERC20 _knc, uint256 _defaultNetworkFeeBps, uint256 _defaultRewardBps, uint256 _defaultRebateBps, address _daoOperator ) public DaoOperator(_daoOperator) { require(_epochPeriod > 0, "ctor: epoch period is 0"); require(_startTimestamp >= now, "ctor: start in the past"); require(_knc != IERC20(0), "ctor: knc token 0"); // in Network, maximum fee that can be taken from 1 tx is (platform fee + 2 * network fee) // so network fee should be less than 50% require(_defaultNetworkFeeBps < BPS / 2, "ctor: network fee high"); require(_defaultRewardBps.add(_defaultRebateBps) <= BPS, "reward plus rebate high"); epochPeriodInSeconds = _epochPeriod; firstEpochStartTimestamp = _startTimestamp; kncToken = _knc; latestNetworkFeeResult = _defaultNetworkFeeBps; latestBrrData = BRRData({ rewardInBps: _defaultRewardBps, rebateInBps: _defaultRebateBps }); // deploy staking contract staking = new KyberStaking({ _kncToken: _knc, _epochPeriod: _epochPeriod, _startTimestamp: _startTimestamp, _kyberDao: IKyberDao(this) }); } modifier onlyStakingContract { require(msg.sender == address(staking), "only staking contract"); _; } /** * @dev called by staking contract when staker wanted to withdraw * @param staker address of staker to reduce reward * @param reduceAmount amount voting power to be reduced for each campaign staker has voted at this epoch */ function handleWithdrawal(address staker, uint256 reduceAmount) external override onlyStakingContract { // staking shouldn't call this func with reduce amount = 0 if (reduceAmount == 0) { return; } uint256 curEpoch = getCurrentEpochNumber(); uint256 numVotes = numberVotes[staker][curEpoch]; // staker has not participated in any campaigns at the current epoch if (numVotes == 0) { return; } // update total points for current epoch totalEpochPoints[curEpoch] = totalEpochPoints[curEpoch].sub(numVotes.mul(reduceAmount)); // update voted count for each campaign staker has voted uint256[] memory campaignIDs = epochCampaigns[curEpoch]; for (uint256 i = 0; i < campaignIDs.length; i++) { uint256 campaignID = campaignIDs[i]; uint256 votedOption = stakerVotedOption[staker][campaignID]; if (votedOption == 0) { continue; } // staker has not voted yet Campaign storage campaign = campaignData[campaignID]; if (campaign.endTimestamp >= now) { // the staker has voted for this campaign and the campaign has not ended yet // reduce total votes and vote count of staker's voted option campaign.campaignVoteData.totalVotes = campaign.campaignVoteData.totalVotes.sub(reduceAmount); campaign.campaignVoteData.votePerOption[votedOption - 1] = campaign.campaignVoteData.votePerOption[votedOption - 1].sub(reduceAmount); } } } /** * @dev create new campaign, only called by daoOperator * @param campaignType type of campaign (General, NetworkFee, FeeHandlerBRR) * @param startTimestamp timestamp to start running the campaign * @param endTimestamp timestamp to end this campaign * @param minPercentageInPrecision min percentage (in precision) for formula to conclude campaign * @param cInPrecision c value (in precision) for formula to conclude campaign * @param tInPrecision t value (in precision) for formula to conclude campaign * @param options list values of options to vote for this campaign * @param link additional data for this campaign */ function submitNewCampaign( CampaignType campaignType, uint256 startTimestamp, uint256 endTimestamp, uint256 minPercentageInPrecision, uint256 cInPrecision, uint256 tInPrecision, uint256[] calldata options, bytes calldata link ) external onlyDaoOperator returns (uint256 campaignID) { // campaign epoch could be different from current epoch // as we allow to create campaign of next epoch as well uint256 campaignEpoch = getEpochNumber(startTimestamp); validateCampaignParams( campaignType, startTimestamp, endTimestamp, minPercentageInPrecision, cInPrecision, tInPrecision, options ); numberCampaigns = numberCampaigns.add(1); campaignID = numberCampaigns; // add campaignID into the list campaign IDs epochCampaigns[campaignEpoch].push(campaignID); // update network fee or fee handler brr campaigns if (campaignType == CampaignType.NetworkFee) { networkFeeCampaigns[campaignEpoch] = campaignID; } else if (campaignType == CampaignType.FeeHandlerBRR) { brrCampaigns[campaignEpoch] = campaignID; } FormulaData memory formulaData = FormulaData({ minPercentageInPrecision: minPercentageInPrecision, cInPrecision: cInPrecision, tInPrecision: tInPrecision }); CampaignVoteData memory campaignVoteData = CampaignVoteData({ totalVotes: 0, votePerOption: new uint256[](options.length) }); campaignData[campaignID] = Campaign({ campaignExists: true, campaignType: campaignType, startTimestamp: startTimestamp, endTimestamp: endTimestamp, totalKNCSupply: kncToken.totalSupply(), link: link, formulaData: formulaData, options: options, campaignVoteData: campaignVoteData }); emit NewCampaignCreated( campaignType, campaignID, startTimestamp, endTimestamp, minPercentageInPrecision, cInPrecision, tInPrecision, options, link ); } /** * @dev cancel a campaign with given id, called by daoOperator only * only can cancel campaigns that have not started yet * @param campaignID id of the campaign to cancel */ function cancelCampaign(uint256 campaignID) external onlyDaoOperator { Campaign storage campaign = campaignData[campaignID]; require(campaign.campaignExists, "cancelCampaign: campaignID doesn't exist"); require(campaign.startTimestamp > now, "cancelCampaign: campaign already started"); uint256 epoch = getEpochNumber(campaign.startTimestamp); if (campaign.campaignType == CampaignType.NetworkFee) { delete networkFeeCampaigns[epoch]; } else if (campaign.campaignType == CampaignType.FeeHandlerBRR) { delete brrCampaigns[epoch]; } delete campaignData[campaignID]; uint256[] storage campaignIDs = epochCampaigns[epoch]; for (uint256 i = 0; i < campaignIDs.length; i++) { if (campaignIDs[i] == campaignID) { // remove this campaign id out of list campaignIDs[i] = campaignIDs[campaignIDs.length - 1]; campaignIDs.pop(); break; } } emit CancelledCampaign(campaignID); } /** * @dev vote for an option of a campaign * options are indexed from 1 to number of options * @param campaignID id of campaign to vote for * @param option id of options to vote for */ function vote(uint256 campaignID, uint256 option) external override { validateVoteOption(campaignID, option); address staker = msg.sender; uint256 curEpoch = getCurrentEpochNumber(); (uint256 stake, uint256 dStake, address representative) = staking.initAndReturnStakerDataForCurrentEpoch(staker); uint256 totalStake = representative == staker ? stake.add(dStake) : dStake; uint256 lastVotedOption = stakerVotedOption[staker][campaignID]; CampaignVoteData storage voteData = campaignData[campaignID].campaignVoteData; if (lastVotedOption == 0) { // increase number campaigns that the staker has voted at the current epoch numberVotes[staker][curEpoch]++; totalEpochPoints[curEpoch] = totalEpochPoints[curEpoch].add(totalStake); // increase voted count for this option voteData.votePerOption[option - 1] = voteData.votePerOption[option - 1].add(totalStake); // increase total votes voteData.totalVotes = voteData.totalVotes.add(totalStake); } else if (lastVotedOption != option) { // deduce previous option voted count voteData.votePerOption[lastVotedOption - 1] = voteData.votePerOption[lastVotedOption - 1].sub(totalStake); // increase new option voted count voteData.votePerOption[option - 1] = voteData.votePerOption[option - 1].add(totalStake); } stakerVotedOption[staker][campaignID] = option; emit Voted(staker, curEpoch, campaignID, option); } /** * @dev get latest network fee data + expiry timestamp * conclude network fee campaign if needed and caching latest result in KyberDao */ function getLatestNetworkFeeDataWithCache() external override returns (uint256 feeInBps, uint256 expiryTimestamp) { (feeInBps, expiryTimestamp) = getLatestNetworkFeeData(); // cache latest data latestNetworkFeeResult = feeInBps; } /** * @dev return latest burn/reward/rebate data, also affecting epoch + expiry timestamp * conclude brr campaign if needed and caching latest result in KyberDao */ function getLatestBRRDataWithCache() external override returns ( uint256 burnInBps, uint256 rewardInBps, uint256 rebateInBps, uint256 epoch, uint256 expiryTimestamp ) { (burnInBps, rewardInBps, rebateInBps, epoch, expiryTimestamp) = getLatestBRRData(); latestBrrData.rewardInBps = rewardInBps; latestBrrData.rebateInBps = rebateInBps; } /** * @dev some epochs have reward but no one can claim, for example: epoch 0 * return true if should burn all that reward * @param epoch epoch to check for burning reward */ function shouldBurnRewardForEpoch(uint256 epoch) external view override returns (bool) { uint256 curEpoch = getCurrentEpochNumber(); if (epoch >= curEpoch) { return false; } return totalEpochPoints[epoch] == 0; } // return list campaign ids for epoch, excluding non-existed ones function getListCampaignIDs(uint256 epoch) external view returns (uint256[] memory campaignIDs) { campaignIDs = epochCampaigns[epoch]; } // return total points for an epoch function getTotalEpochPoints(uint256 epoch) external view returns (uint256) { return totalEpochPoints[epoch]; } function getCampaignDetails(uint256 campaignID) external view returns ( CampaignType campaignType, uint256 startTimestamp, uint256 endTimestamp, uint256 totalKNCSupply, uint256 minPercentageInPrecision, uint256 cInPrecision, uint256 tInPrecision, bytes memory link, uint256[] memory options ) { Campaign storage campaign = campaignData[campaignID]; campaignType = campaign.campaignType; startTimestamp = campaign.startTimestamp; endTimestamp = campaign.endTimestamp; totalKNCSupply = campaign.totalKNCSupply; minPercentageInPrecision = campaign.formulaData.minPercentageInPrecision; cInPrecision = campaign.formulaData.cInPrecision; tInPrecision = campaign.formulaData.tInPrecision; link = campaign.link; options = campaign.options; } function getCampaignVoteCountData(uint256 campaignID) external view returns (uint256[] memory voteCounts, uint256 totalVoteCount) { CampaignVoteData memory voteData = campaignData[campaignID].campaignVoteData; totalVoteCount = voteData.totalVotes; voteCounts = voteData.votePerOption; } /** * @dev return staker's reward percentage in precision for a past epoch only * fee handler should call this function when a staker wants to claim reward * return 0 if staker has no votes or stakes */ function getPastEpochRewardPercentageInPrecision(address staker, uint256 epoch) external view override returns (uint256) { // return 0 if epoch is not past epoch uint256 curEpoch = getCurrentEpochNumber(); if (epoch >= curEpoch) { return 0; } return getRewardPercentageInPrecision(staker, epoch); } /** * @dev return staker's reward percentage in precision for the current epoch */ function getCurrentEpochRewardPercentageInPrecision(address staker) external view override returns (uint256) { uint256 curEpoch = getCurrentEpochNumber(); return getRewardPercentageInPrecision(staker, curEpoch); } /** * @dev return campaign winning option and its value * return (0, 0) if campaign does not exist * return (0, 0) if campaign has not ended yet * return (0, 0) if campaign has no winning option based on the formula * @param campaignID id of campaign to get result */ function getCampaignWinningOptionAndValue(uint256 campaignID) public view returns (uint256 optionID, uint256 value) { Campaign storage campaign = campaignData[campaignID]; if (!campaign.campaignExists) { return (0, 0); } // not exist // campaign has not ended yet, return 0 as winning option if (campaign.endTimestamp > now) { return (0, 0); } uint256 totalSupply = campaign.totalKNCSupply; // something is wrong here, total KNC supply shouldn't be 0 if (totalSupply == 0) { return (0, 0); } uint256 totalVotes = campaign.campaignVoteData.totalVotes; uint256[] memory voteCounts = campaign.campaignVoteData.votePerOption; // Finding option with most votes uint256 winningOption = 0; uint256 maxVotedCount = 0; for (uint256 i = 0; i < voteCounts.length; i++) { if (voteCounts[i] > maxVotedCount) { winningOption = i + 1; maxVotedCount = voteCounts[i]; } else if (voteCounts[i] == maxVotedCount) { winningOption = 0; } } // more than 1 options have same vote count if (winningOption == 0) { return (0, 0); } FormulaData memory formulaData = campaign.formulaData; // compute voted percentage (in precision) uint256 votedPercentage = totalVotes.mul(PRECISION).div(campaign.totalKNCSupply); // total voted percentage is below min acceptable percentage, no winning option if (formulaData.minPercentageInPrecision > votedPercentage) { return (0, 0); } // as we already limit value for c & t, no need to check for overflow here uint256 x = formulaData.tInPrecision.mul(votedPercentage).div(PRECISION); if (x <= formulaData.cInPrecision) { // threshold is not negative, need to compare with voted count uint256 y = formulaData.cInPrecision.sub(x); // (most voted option count / total votes) is below threshold, no winining option if (maxVotedCount.mul(PRECISION) < y.mul(totalVotes)) { return (0, 0); } } optionID = winningOption; value = campaign.options[optionID - 1]; } /** * @dev return latest network fee and expiry timestamp */ function getLatestNetworkFeeData() public view override returns (uint256 feeInBps, uint256 expiryTimestamp) { uint256 curEpoch = getCurrentEpochNumber(); feeInBps = latestNetworkFeeResult; // expiryTimestamp = firstEpochStartTimestamp + curEpoch * epochPeriodInSeconds - 1; expiryTimestamp = firstEpochStartTimestamp.add(curEpoch.mul(epochPeriodInSeconds)).sub(1); if (curEpoch == 0) { return (feeInBps, expiryTimestamp); } uint256 campaignID = networkFeeCampaigns[curEpoch.sub(1)]; if (campaignID == 0) { // don't have network fee campaign, return latest result return (feeInBps, expiryTimestamp); } uint256 winningOption; (winningOption, feeInBps) = getCampaignWinningOptionAndValue(campaignID); if (winningOption == 0) { // fallback to previous result feeInBps = latestNetworkFeeResult; } return (feeInBps, expiryTimestamp); } /** * @dev return latest brr result, conclude brr campaign if needed */ function getLatestBRRData() public view returns ( uint256 burnInBps, uint256 rewardInBps, uint256 rebateInBps, uint256 epoch, uint256 expiryTimestamp ) { epoch = getCurrentEpochNumber(); // expiryTimestamp = firstEpochStartTimestamp + epoch * epochPeriodInSeconds - 1; expiryTimestamp = firstEpochStartTimestamp.add(epoch.mul(epochPeriodInSeconds)).sub(1); rewardInBps = latestBrrData.rewardInBps; rebateInBps = latestBrrData.rebateInBps; if (epoch > 0) { uint256 campaignID = brrCampaigns[epoch.sub(1)]; if (campaignID != 0) { uint256 winningOption; uint256 brrData; (winningOption, brrData) = getCampaignWinningOptionAndValue(campaignID); if (winningOption > 0) { // has winning option, update reward and rebate value (rebateInBps, rewardInBps) = getRebateAndRewardFromData(brrData); } } } burnInBps = BPS.sub(rebateInBps).sub(rewardInBps); } // Helper functions for squeezing data function getRebateAndRewardFromData(uint256 data) public pure returns (uint256 rebateInBps, uint256 rewardInBps) { rewardInBps = data & (POWER_128.sub(1)); rebateInBps = (data.div(POWER_128)) & (POWER_128.sub(1)); } /** * @dev helper func to get encoded reward and rebate * revert if validation failed */ function getDataFromRewardAndRebateWithValidation(uint256 rewardInBps, uint256 rebateInBps) public pure returns (uint256 data) { require(rewardInBps.add(rebateInBps) <= BPS, "reward plus rebate high"); data = (rebateInBps.mul(POWER_128)).add(rewardInBps); } /** * @dev options are indexed from 1 */ function validateVoteOption(uint256 campaignID, uint256 option) internal view { Campaign storage campaign = campaignData[campaignID]; require(campaign.campaignExists, "vote: campaign doesn't exist"); require(campaign.startTimestamp <= now, "vote: campaign not started"); require(campaign.endTimestamp >= now, "vote: campaign already ended"); // option is indexed from 1 to options.length require(option > 0, "vote: option is 0"); require(option <= campaign.options.length, "vote: option is not in range"); } /** * @dev Validate params to check if we could submit a new campaign with these params */ function validateCampaignParams( CampaignType campaignType, uint256 startTimestamp, uint256 endTimestamp, uint256 minPercentageInPrecision, uint256 cInPrecision, uint256 tInPrecision, uint256[] memory options ) internal view { // now <= start timestamp < end timestamp require(startTimestamp >= now, "validateParams: start in the past"); // campaign duration must be at least min campaign duration // endTimestamp - startTimestamp + 1 >= minCampaignDurationInSeconds, require( endTimestamp.add(1) >= startTimestamp.add(minCampaignDurationInSeconds), "validateParams: campaign duration is low" ); uint256 startEpoch = getEpochNumber(startTimestamp); uint256 endEpoch = getEpochNumber(endTimestamp); require( epochCampaigns[startEpoch].length < MAX_EPOCH_CAMPAIGNS, "validateParams: too many campaigns" ); // start timestamp and end timestamp must be in the same epoch require(startEpoch == endEpoch, "validateParams: start & end not same epoch"); uint256 currentEpoch = getCurrentEpochNumber(); require( startEpoch <= currentEpoch.add(1), "validateParams: only for current or next epochs" ); // verify number of options uint256 numOptions = options.length; require( numOptions > 1 && numOptions <= MAX_CAMPAIGN_OPTIONS, "validateParams: invalid number of options" ); // Validate option values based on campaign type if (campaignType == CampaignType.General) { // option must be positive number for (uint256 i = 0; i < options.length; i++) { require(options[i] > 0, "validateParams: general campaign option is 0"); } } else if (campaignType == CampaignType.NetworkFee) { require( networkFeeCampaigns[startEpoch] == 0, "validateParams: already had network fee campaign for this epoch" ); // network fee campaign, option must be fee in bps for (uint256 i = 0; i < options.length; i++) { // in Network, maximum fee that can be taken from 1 tx is (platform fee + 2 * network fee) // so network fee should be less than 50% require( options[i] < BPS / 2, "validateParams: network fee must be smaller then BPS / 2" ); } } else { require( brrCampaigns[startEpoch] == 0, "validateParams: already had brr campaign for this epoch" ); // brr fee handler campaign, option must be combined for reward + rebate % for (uint256 i = 0; i < options.length; i++) { // rebate (left most 128 bits) + reward (right most 128 bits) (uint256 rebateInBps, uint256 rewardInBps) = getRebateAndRewardFromData(options[i]); require( rewardInBps.add(rebateInBps) <= BPS, "validateParams: rebate + reward can't be bigger than BPS" ); } } // percentage should be smaller than or equal 100% require(minPercentageInPrecision <= PRECISION, "validateParams: min percentage is high"); // limit value of c and t to avoid overflow require(cInPrecision < POWER_128, "validateParams: c is high"); require(tInPrecision < POWER_128, "validateParams: t is high"); } /** * @dev return staker's reward percentage in precision for an epoch * return 0 if staker has no votes or stakes * called by 2 functions in KyberDao */ function getRewardPercentageInPrecision(address staker, uint256 epoch) internal view returns (uint256) { uint256 numVotes = numberVotes[staker][epoch]; // no votes, no rewards if (numVotes == 0) { return 0; } (uint256 stake, uint256 delegatedStake, address representative) = staking.getStakerRawData(staker, epoch); uint256 totalStake = representative == staker ? stake.add(delegatedStake) : delegatedStake; if (totalStake == 0) { return 0; } uint256 points = numVotes.mul(totalStake); uint256 totalPts = totalEpochPoints[epoch]; // staker's reward percentage should be <= 100% assert(points <= totalPts); return points.mul(PRECISION).div(totalPts); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_epochPeriod","type":"uint256"},{"internalType":"uint256","name":"_startTimestamp","type":"uint256"},{"internalType":"contract IERC20","name":"_knc","type":"address"},{"internalType":"uint256","name":"_defaultNetworkFeeBps","type":"uint256"},{"internalType":"uint256","name":"_defaultRewardBps","type":"uint256"},{"internalType":"uint256","name":"_defaultRebateBps","type":"uint256"},{"internalType":"address","name":"_daoOperator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignID","type":"uint256"}],"name":"CancelledCampaign","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum KyberDao.CampaignType","name":"campaignType","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"campaignID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minPercentageInPrecision","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cInPrecision","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tInPrecision","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"options","type":"uint256[]"},{"indexed":false,"internalType":"bytes","name":"link","type":"bytes"}],"name":"NewCampaignCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"campaignID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"option","type":"uint256"}],"name":"Voted","type":"event"},{"inputs":[],"name":"MAX_CAMPAIGN_OPTIONS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_EPOCH_CAMPAIGNS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"brrCampaigns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignID","type":"uint256"}],"name":"cancelCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"daoOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochPeriodInSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"firstEpochStartTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignID","type":"uint256"}],"name":"getCampaignDetails","outputs":[{"internalType":"enum KyberDao.CampaignType","name":"campaignType","type":"uint8"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"totalKNCSupply","type":"uint256"},{"internalType":"uint256","name":"minPercentageInPrecision","type":"uint256"},{"internalType":"uint256","name":"cInPrecision","type":"uint256"},{"internalType":"uint256","name":"tInPrecision","type":"uint256"},{"internalType":"bytes","name":"link","type":"bytes"},{"internalType":"uint256[]","name":"options","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignID","type":"uint256"}],"name":"getCampaignVoteCountData","outputs":[{"internalType":"uint256[]","name":"voteCounts","type":"uint256[]"},{"internalType":"uint256","name":"totalVoteCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignID","type":"uint256"}],"name":"getCampaignWinningOptionAndValue","outputs":[{"internalType":"uint256","name":"optionID","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEpochNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getCurrentEpochRewardPercentageInPrecision","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rewardInBps","type":"uint256"},{"internalType":"uint256","name":"rebateInBps","type":"uint256"}],"name":"getDataFromRewardAndRebateWithValidation","outputs":[{"internalType":"uint256","name":"data","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getEpochNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestBRRData","outputs":[{"internalType":"uint256","name":"burnInBps","type":"uint256"},{"internalType":"uint256","name":"rewardInBps","type":"uint256"},{"internalType":"uint256","name":"rebateInBps","type":"uint256"},{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestBRRDataWithCache","outputs":[{"internalType":"uint256","name":"burnInBps","type":"uint256"},{"internalType":"uint256","name":"rewardInBps","type":"uint256"},{"internalType":"uint256","name":"rebateInBps","type":"uint256"},{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getLatestNetworkFeeData","outputs":[{"internalType":"uint256","name":"feeInBps","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestNetworkFeeDataWithCache","outputs":[{"internalType":"uint256","name":"feeInBps","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getListCampaignIDs","outputs":[{"internalType":"uint256[]","name":"campaignIDs","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getPastEpochRewardPercentageInPrecision","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"data","type":"uint256"}],"name":"getRebateAndRewardFromData","outputs":[{"internalType":"uint256","name":"rebateInBps","type":"uint256"},{"internalType":"uint256","name":"rewardInBps","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getTotalEpochPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint256","name":"reduceAmount","type":"uint256"}],"name":"handleWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"kncToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minCampaignDurationInSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"networkFeeCampaigns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberCampaigns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"numberVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"shouldBurnRewardForEpoch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakerVotedOption","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"staking","outputs":[{"internalType":"contract IKyberStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum KyberDao.CampaignType","name":"campaignType","type":"uint8"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"minPercentageInPrecision","type":"uint256"},{"internalType":"uint256","name":"cInPrecision","type":"uint256"},{"internalType":"uint256","name":"tInPrecision","type":"uint256"},{"internalType":"uint256[]","name":"options","type":"uint256[]"},{"internalType":"bytes","name":"link","type":"bytes"}],"name":"submitNewCampaign","outputs":[{"internalType":"uint256","name":"campaignID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignID","type":"uint256"},{"internalType":"uint256","name":"option","type":"uint256"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040526205460060055560006006553480156200001d57600080fd5b5060405162004dee38038062004dee833981810160405260e08110156200004357600080fd5b508051602082015160408301516060840151608085015160a086015160c0909601516002805460ff191660011790559495939492939192909190806001600160a01b038116620000cd576040805162461bcd60e51b815260206004820152601060248201526f064616f4f70657261746f7220697320360841b604482015290519081900360640190fd5b600480546001600160a01b0319166001600160a01b03929092169190911790558662000140576040805162461bcd60e51b815260206004820152601760248201527f63746f723a2065706f636820706572696f642069732030000000000000000000604482015290519081900360640190fd5b4286101562000196576040805162461bcd60e51b815260206004820152601760248201527f63746f723a20737461727420696e207468652070617374000000000000000000604482015290519081900360640190fd5b6001600160a01b038516620001e6576040805162461bcd60e51b8152602060048201526011602482015270063746f723a206b6e6320746f6b656e203607c1b604482015290519081900360640190fd5b61138884106200023d576040805162461bcd60e51b815260206004820152601660248201527f63746f723a206e6574776f726b20666565206869676800000000000000000000604482015290519081900360640190fd5b6127106200025a83856200036460201b62001dd91790919060201c565b1115620002ae576040805162461bcd60e51b815260206004820152601760248201527f72657761726420706c7573207265626174652068696768000000000000000000604482015290519081900360640190fd5b600087905560018690556001600160601b0319606086901b16608052600c849055604080518082018252848152602001839052600e849055600f839055518590889088903090620002ff90620003c6565b6001600160a01b03948516815260208101939093526040808401929092529092166060820152905190819003608001906000f08015801562000345573d6000803e3d6000fd5b5060601b6001600160601b03191660a05250620003d495505050505050565b600082820183811015620003bf576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b611da6806200304883390190565b60805160601c60a05160601c612c366200041260003980610c8e528061137152806118a052806123da525080610f5452806112165250612c366000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c8063811c7fe21161011a578063b384abef116100ad578063d60d6bd41161007c578063d60d6bd414610672578063d993de621461067a578063e2346d711461078f578063ec0a7cc2146107bb578063f63e7811146107d8576101fb565b8063b384abef14610604578063b484f72614610627578063c70d7b6c1461064d578063d60079bf14610655576101fb565b806399e30ba8116100e957806399e30ba8146105c0578063a81ff705146105ec578063a910d096146105f4578063adea6960146105fc576101fb565b8063811c7fe2146105875780638c9bc2081461058f5780639010984e146105975780639833afaf1461059f576101fb565b806345598b4a11610192578063588df33a11610161578063588df33a1461043f5780636695c981146104475780636fbf12ad1461047a578063809e2c621461049d576101fb565b806345598b4a1461035e57806345bd004e1461037d5780634650e3ab146103ae5780634cf088d91461041b576101fb565b80631c552f00116101ce5780631c552f00146102f0578063220046781461030d57806342322250146103395780634408d2ba14610356576101fb565b80630b4defe4146102005780630bff230a1461022f5780631248a166146102a7578063166b4997146102c4575b600080fd5b61021d6004803603602081101561021657600080fd5b50356107e0565b60408051918252519081900360200190f35b61024c6004803603602081101561024557600080fd5b50356107f2565b6040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561029257818101518382015260200161027a565b50505050905001935050505060405180910390f35b61021d600480360360208110156102bd57600080fd5b5035610895565b61021d600480360360408110156102da57600080fd5b506001600160a01b0381351690602001356108aa565b61021d6004803603602081101561030657600080fd5b50356108c7565b61021d6004803603604081101561032357600080fd5b506001600160a01b038135169060200135610924565b61021d6004803603602081101561034f57600080fd5b5035610941565b61021d610953565b61037b6004803603602081101561037457600080fd5b5035610964565b005b61039a6004803603602081101561039357600080fd5b5035610bf7565b604080519115158252519081900360200190f35b6103cb600480360360208110156103c457600080fd5b5035610c2a565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104075781810151838201526020016103ef565b505050509050019250505060405180910390f35b610423610c8c565b604080516001600160a01b039092168252519081900360200190f35b61021d610cb0565b61044f610cb6565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b61021d6004803603604081101561049057600080fd5b5080359060200135610ce1565b61021d60048036036101008110156104b457600080fd5b60ff8235169160208101359160408201359160608101359160808201359160a08101359181019060e0810160c08201356401000000008111156104f657600080fd5b82018360208201111561050857600080fd5b8035906020019184602083028401116401000000008311171561052a57600080fd5b91939092909160208101903564010000000081111561054857600080fd5b82018360208201111561055a57600080fd5b8035906020019184600183028401116401000000008311171561057c57600080fd5b509092509050610d68565b610423611214565b610423611238565b61021d611247565b6105a761124d565b6040805192835260208301919091528051918290030190f35b61021d600480360360408110156105d657600080fd5b506001600160a01b038135169060200135611266565b61021d611296565b61021d61129b565b6105a76112a0565b61037b6004803603604081101561061a57600080fd5b5080359060200135611353565b61021d6004803603602081101561063d57600080fd5b50356001600160a01b0316611639565b61021d611650565b6105a76004803603602081101561066b57600080fd5b5035611656565b61044f6116a3565b6106976004803603602081101561069057600080fd5b503561175d565b604051808a60028111156106a757fe5b60ff1681526020018981526020018881526020018781526020018681526020018581526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156107105781810151838201526020016106f8565b50505050905090810190601f16801561073d5780820380516001836020036101000a031916815260200191505b508381038252845181528451602091820191808701910280838360005b8381101561077257818101518382015260200161075a565b505050509050019b50505050505050505050505060405180910390f35b61037b600480360360408110156107a557600080fd5b506001600160a01b038135169060200135611895565b6105a7600480360360208110156107d157600080fd5b5035611acc565b61021d611d4f565b60106020526000908152604090205481565b606060006107fe6127f8565b60076000858152602001908152602001600020600901604051806040016040529081600082015481526020016001820180548060200260200160405190810160405280929190818152602001828054801561087857602002820191906000526020600020905b815481526020019060010190808311610864575b505050919092525050815160209092015196919550909350505050565b6000818152600960205260409020545b919050565b600b60209081526000928352604080842090915290825290205481565b60006001548210806108d95750600054155b156108e6575060006108a5565b61091e600161091260005461090660015487611d5590919063ffffffff16565b9063ffffffff611d9716565b9063ffffffff611dd916565b92915050565b600a60209081526000928352604080842090915290825290205481565b600d6020526000908152604090205481565b600061095e426108c7565b90505b90565b6004546001600160a01b031633146109b6576040805162461bcd60e51b815260206004820152601060248201526f37b7363c903230b7a7b832b930ba37b960811b604482015290519081900360640190fd5b60008181526007602052604090208054610100900460ff16610a095760405162461bcd60e51b8152600401808060200182810382526028815260200180612bd96028913960400191505060405180910390fd5b42816001015411610a4b5760405162461bcd60e51b8152600401808060200182810382526028815260200180612a256028913960400191505060405180910390fd5b6000610a5a82600101546108c7565b90506001825460ff166002811115610a6e57fe5b1415610a88576000818152600d6020526040812055610ab0565b6002825460ff166002811115610a9a57fe5b1415610ab0576000818152601060205260408120555b60008381526007602081905260408220805461ffff191681556001810183905560028101839055600381018390556004810183905560058101839055600681018390559190610b0190830182612812565b610b0f600883016000612859565b60006009830181815590610b26600a850182612859565b505050600082815260086020526040812091505b8154811015610bc55784828281548110610b5057fe5b90600052602060002001541415610bbd57815482906000198101908110610b7357fe5b9060005260206000200154828281548110610b8a57fe5b906000526020600020018190555081805480610ba257fe5b60019003818190600052602060002001600090559055610bc5565b600101610b3a565b5060405184907fef29bb5bcfd2b2ff4bc50d710898467757ff87aad1031fc953907b65127f86fc90600090a250505050565b600080610c02610953565b9050808310610c155760009150506108a5565b50506000908152600960205260409020541590565b600081815260086020908152604091829020805483518184028101840190945280845260609392830182828015610c8057602002820191906000526020600020905b815481526020019060010190808311610c6c575b50505050509050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60065481565b6000806000806000610cc66116a3565b600e849055600f839055939992985090965094509092509050565b6000612710610cf6848463ffffffff611dd916565b1115610d49576040805162461bcd60e51b815260206004820152601760248201527f72657761726420706c7573207265626174652068696768000000000000000000604482015290519081900360640190fd5b610d618361091284600160801b63ffffffff611e3316565b9392505050565b6004546000906001600160a01b03163314610dbd576040805162461bcd60e51b815260206004820152601060248201526f37b7363c903230b7a7b832b930ba37b960811b604482015290519081900360640190fd5b6000610dc88b6108c7565b9050610e0c8c8c8c8c8c8c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611e8c92505050565b600654610e2090600163ffffffff611dd916565b60068190556000828152600860209081526040822080546001818101835591845291909220018290559092508c6002811115610e5857fe5b1415610e74576000818152600d60205260409020829055610e9a565b60028c6002811115610e8257fe5b1415610e9a5760008181526010602052604090208290555b610ea2612877565b60405180606001604052808b81526020018a8152602001898152509050610ec76127f8565b6040805180820190915260008152602081018867ffffffffffffffff81118015610ef057600080fd5b50604051908082528060200260200182016040528015610f1a578160200160208202803683370190505b5081525090506040518061012001604052808f6002811115610f3857fe5b81526020016001151581526020018e81526020018d81526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b505afa158015610fbf573d6000803e3d6000fd5b505050506040513d6020811015610fd557600080fd5b50518152602081810185905260408051601f8a0183900483028101830182528981529201919089908990819084018382808284376000920191909152505050908252506040805160208b810282810182019093528b82529283019290918c918c9182918501908490808284376000920182905250938552505050602091820184905286815260079091526040902081518154829060ff1916600183600281111561107b57fe5b021790555060208281015182549015156101000261ff00199091161782556040808401516001840155606084015160028401556080840151600384015560a0840151805160048501558083015160058501550151600683015560c083015180516110eb9260078501920190612898565b5060e08201518051611107916008840191602090910190612916565b50610100820151805160098301908155602080830151805161112f92600a8701920190612916565b505050905050837fba908e34477602dcf3b8b10115cb9ba1f56c512e94a0beb561ad0245026cda138f8f8f8f8f8f8f8f8f8f604051808b600281111561117157fe5b60ff1681526020018a815260200189815260200188815260200187815260200186815260200180602001806020018381038352878782818152602001925060200280828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039e50909c50505050505050505050505050a25050509a9950505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6004546001600160a01b031681565b60055481565b6000806112586112a0565b600c82905590939092509050565b600080611271610953565b905080831061128457600091505061091e565b61128e84846123a0565b949350505050565b600881565b600a81565b60008060006112ad610953565b9050600c5492506112ec60016112e06112d160005485611e3390919063ffffffff16565b6001549063ffffffff611dd916565b9063ffffffff611d5516565b9150806112f9575061134f565b6000600d8161130f84600163ffffffff611d5516565b81526020019081526020016000205490508060001415611331575061134f9050565b600061133c82611acc565b955090508061134b57600c5494505b5050505b9091565b61135d828261252e565b336000611368610953565b905060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b7a13c4c866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050606060405180830381600087803b1580156113e757600080fd5b505af11580156113fb573d6000803e3d6000fd5b505050506040513d606081101561141157600080fd5b5080516020820151604090920151909450909250905060006001600160a01b03808316908716146114425782611452565b611452848463ffffffff611dd916565b6001600160a01b0387166000908152600b602090815260408083208c845282528083205460079092529091209192509060090181611545576001600160a01b0388166000908152600a602090815260408083208a845282528083208054600101905560099091529020546114cc908463ffffffff611dd916565b60008881526009602052604090205560018101805461150e9185916000198d019081106114f557fe5b9060005260206000200154611dd990919063ffffffff16565b8160010160018b038154811061152057fe5b600091825260209091200155805461153e908463ffffffff611dd916565b81556115d0565b8882146115d05761157b8382600101600185038154811061156257fe5b9060005260206000200154611d5590919063ffffffff16565b81600101600184038154811061158d57fe5b90600052602060002001819055506115b1838260010160018c03815481106114f557fe5b8160010160018b03815481106115c357fe5b6000918252602090912001555b6001600160a01b0388166000818152600b602090815260408083208e84528252918290208c905581518c815291518d938b9390927fc32b42768a47a585121e9b8d7a2ab9d3f34c326a192dee11ee1732e3d18313f392918290030190a450505050505050505050565b600080611644610953565b9050610d6183826123a0565b60015481565b60008061166e600160801b600163ffffffff611d5516565b83169050611687600160801b600163ffffffff611d5516565b61169b84600160801b63ffffffff611d9716565b169150915091565b60008060008060006116b3610953565b91506116d260016112e06112d160005486611e3390919063ffffffff16565b600e54600f5490955093509050811561173e5760006010816116fb85600163ffffffff611d5516565b81526020019081526020016000205490508060001461173c5760008061172083611acc565b909250905081156117395761173481611656565b975095505b50505b505b611754846112e06127108663ffffffff611d5516565b94509091929394565b600081815260076020818152604092839020805460018083015460028085015460038601546004870154600588015460068901549a890180548d516101009982161599909902600019011695909504601f81018b90048b0288018b01909c528b875260ff9097169a94999298919790969592946060948594929390919083018282801561182b5780601f106118005761010080835404028352916020019161182b565b820191906000526020600020905b81548152906001019060200180831161180e57829003601f168201915b505050505092508060080180548060200260200160405190810160405280929190818152602001828054801561188057602002820191906000526020600020905b81548152602001906001019080831161186c575b50505050509150509193959799909294969850565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611912576040805162461bcd60e51b815260206004820152601560248201527f6f6e6c79207374616b696e6720636f6e74726163740000000000000000000000604482015290519081900360640190fd5b8061191c57611ac8565b6000611926610953565b6001600160a01b0384166000908152600a6020908152604080832084845290915290205490915080611959575050611ac8565b61198761196c828563ffffffff611e3316565b6000848152600960205260409020549063ffffffff611d5516565b60008381526009602090815260408083209390935560088152908290208054835181840281018401909452808452606093928301828280156119e857602002820191906000526020600020905b8154815260200190600101908083116119d4575b50939450600093505050505b8151811015611ac3576000828281518110611a0b57fe5b6020908102919091018101516001600160a01b0389166000908152600b83526040808220838352909352919091205490915080611a49575050611abb565b600082815260076020526040902060028101544211611ab7576009810154611a77908963ffffffff611d5516565b6009820155600a81018054611a96918a91600019860190811061156257fe5b600a820180546000198501908110611aaa57fe5b6000918252602090912001555b5050505b6001016119f4565b505050505b5050565b60008181526007602052604081208054829190610100900460ff16611af8575060009150819050611d4a565b4281600201541115611b11575060009150819050611d4a565b600381015480611b2a575060009250829150611d4a9050565b6009820154600a830180546040805160208084028201810190925282815260609390929091830182828015611b7e57602002820191906000526020600020905b815481526020019060010190808311611b6a575b5093945060009350839250829150505b8351811015611bfb5781848281518110611ba457fe5b60200260200101511115611bd357806001019250838181518110611bc457fe5b60200260200101519150611bf3565b81848281518110611be057fe5b60200260200101511415611bf357600092505b600101611b8e565b5081611c14575060009650869550611d4a945050505050565b611c1c612877565b506040805160608101825260048801548152600588015460208201526006880154918101919091526003870154600090611c689061090688670de0b6b3a764000063ffffffff611e3316565b90508082600001511115611c8b575060009850889750611d4a9650505050505050565b6000611cb0670de0b6b3a7640000610906848660400151611e3390919063ffffffff16565b905082602001518111611d1e576020830151600090611cd5908363ffffffff611d5516565b9050611ce7818963ffffffff611e3316565b611cff86670de0b6b3a764000063ffffffff611e3316565b1015611d1c575060009a508a9950611d4a98505050505050505050565b505b849a508860080160018c0381548110611d3357fe5b906000526020600020015499505050505050505050505b915091565b60005481565b6000610d6183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506126fc565b6000610d6183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612793565b600082820183811015610d61576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082611e425750600061091e565b82820282848281611e4f57fe5b0414610d615760405162461bcd60e51b8152600401808060200182810382526021815260200180612a4d6021913960400191505060405180910390fd5b42861015611ecb5760405162461bcd60e51b815260040180806020018281038252602181526020018061296b6021913960400191505060405180910390fd5b600554611edf90879063ffffffff611dd916565b611ef086600163ffffffff611dd916565b1015611f2d5760405162461bcd60e51b8152600401808060200182810382526028815260200180612acf6028913960400191505060405180910390fd5b6000611f38876108c7565b90506000611f45876108c7565b600083815260086020526040902054909150600a11611f955760405162461bcd60e51b815260040180806020018281038252602281526020018061298c6022913960400191505060405180910390fd5b808214611fd35760405162461bcd60e51b815260040180806020018281038252602a815260200180612a6e602a913960400191505060405180910390fd5b6000611fdd610953565b9050611ff081600163ffffffff611dd916565b83111561202e5760405162461bcd60e51b815260040180806020018281038252602f815260200180612baa602f913960400191505060405180910390fd5b8351600181118015612041575060088111155b61207c5760405162461bcd60e51b8152600401808060200182810382526029815260200180612b816029913960400191505060405180910390fd5b60008b600281111561208a57fe5b14156120fc5760005b85518110156120f65760008682815181106120aa57fe5b6020026020010151116120ee5760405162461bcd60e51b815260040180806020018281038252602c815260200180612af7602c913960400191505060405180910390fd5b600101612093565b5061229c565b60018b600281111561210a57fe5b14156121c5576000848152600d60205260409020541561215b5760405162461bcd60e51b815260040180806020018281038252603f8152602001806129ae603f913960400191505060405180910390fd5b60005b85518110156120f65760026127100486828151811061217957fe5b6020026020010151106121bd5760405162461bcd60e51b8152600401808060200182810382526038815260200180612b496038913960400191505060405180910390fd5b60010161215e565b600084815260106020526040902054156122105760405162461bcd60e51b8152600401808060200182810382526037815260200180612a986037913960400191505060405180910390fd5b60005b855181101561229a5760008061223b88848151811061222e57fe5b6020026020010151611656565b9092509050612710612253828463ffffffff611dd916565b11156122905760405162461bcd60e51b81526004018080602001828103825260388152602001806129ed6038913960400191505060405180910390fd5b5050600101612213565b505b670de0b6b3a76400008811156122e35760405162461bcd60e51b8152600401808060200182810382526026815260200180612b236026913960400191505060405180910390fd5b600160801b871061233b576040805162461bcd60e51b815260206004820152601960248201527f76616c6964617465506172616d733a2063206973206869676800000000000000604482015290519081900360640190fd5b600160801b8610612393576040805162461bcd60e51b815260206004820152601960248201527f76616c6964617465506172616d733a2074206973206869676800000000000000604482015290519081900360640190fd5b5050505050505050505050565b6001600160a01b0382166000908152600a60209081526040808320848452909152812054806123d357600091505061091e565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166316554d6288886040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060606040518083038186803b15801561245657600080fd5b505afa15801561246a573d6000803e3d6000fd5b505050506040513d606081101561248057600080fd5b5080516020820151604090920151909450909250905060006001600160a01b03808316908916146124b157826124c1565b6124c1848463ffffffff611dd916565b9050806124d65760009550505050505061091e565b60006124e8868363ffffffff611e3316565b6000898152600960205260409020549091508082111561250457fe5b6125208161090684670de0b6b3a764000063ffffffff611e3316565b9a9950505050505050505050565b60008281526007602052604090208054610100900460ff16612597576040805162461bcd60e51b815260206004820152601c60248201527f766f74653a2063616d706169676e20646f65736e277420657869737400000000604482015290519081900360640190fd5b42816001015411156125f0576040805162461bcd60e51b815260206004820152601a60248201527f766f74653a2063616d706169676e206e6f742073746172746564000000000000604482015290519081900360640190fd5b4281600201541015612649576040805162461bcd60e51b815260206004820152601c60248201527f766f74653a2063616d706169676e20616c726561647920656e64656400000000604482015290519081900360640190fd5b6000821161269e576040805162461bcd60e51b815260206004820152601160248201527f766f74653a206f7074696f6e2069732030000000000000000000000000000000604482015290519081900360640190fd5b60088101548211156126f7576040805162461bcd60e51b815260206004820152601c60248201527f766f74653a206f7074696f6e206973206e6f7420696e2072616e676500000000604482015290519081900360640190fd5b505050565b6000818484111561278b5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612750578181015183820152602001612738565b50505050905090810190601f16801561277d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836127e25760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612750578181015183820152602001612738565b5060008385816127ee57fe5b0495945050505050565b604051806040016040528060008152602001606081525090565b50805460018160011615610100020316600290046000825580601f106128385750612856565b601f0160209004906000526020600020908101906128569190612950565b50565b50805460008255906000526020600020908101906128569190612950565b60405180606001604052806000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106128d957805160ff1916838001178555612906565b82800160010185558215612906579182015b828111156129065782518255916020019190600101906128eb565b50612912929150612950565b5090565b82805482825590600052602060002090810192821561290657916020028201828111156129065782518255916020019190600101906128eb565b61096191905b80821115612912576000815560010161295656fe76616c6964617465506172616d733a20737461727420696e20746865207061737476616c6964617465506172616d733a20746f6f206d616e792063616d706169676e7376616c6964617465506172616d733a20616c726561647920686164206e6574776f726b206665652063616d706169676e20666f7220746869732065706f636876616c6964617465506172616d733a20726562617465202b207265776172642063616e277420626520626967676572207468616e2042505363616e63656c43616d706169676e3a2063616d706169676e20616c72656164792073746172746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7776616c6964617465506172616d733a207374617274202620656e64206e6f742073616d652065706f636876616c6964617465506172616d733a20616c726561647920686164206272722063616d706169676e20666f7220746869732065706f636876616c6964617465506172616d733a2063616d706169676e206475726174696f6e206973206c6f7776616c6964617465506172616d733a2067656e6572616c2063616d706169676e206f7074696f6e206973203076616c6964617465506172616d733a206d696e2070657263656e74616765206973206869676876616c6964617465506172616d733a206e6574776f726b20666565206d75737420626520736d616c6c6572207468656e20425053202f203276616c6964617465506172616d733a20696e76616c6964206e756d626572206f66206f7074696f6e7376616c6964617465506172616d733a206f6e6c7920666f722063757272656e74206f72206e6578742065706f63687363616e63656c43616d706169676e3a2063616d706169676e494420646f65736e2774206578697374a2646970667358221220313c6142437875dcaf3f6546db75663d187e82ca7247be8fa4039cdd632f8a2864736f6c6343000606003360c060405234801561001057600080fd5b50604051611da6380380611da68339818101604052608081101561003357600080fd5b508051602082015160408301516060909301516002805460ff1916600117905591929091826100a9576040805162461bcd60e51b815260206004820152601760248201527f63746f723a2065706f636820706572696f642069732030000000000000000000604482015290519081900360640190fd5b428210156100fe576040805162461bcd60e51b815260206004820152601760248201527f63746f723a20737461727420696e207468652070617374000000000000000000604482015290519081900360640190fd5b6001600160a01b03841661014c576040805162461bcd60e51b815260206004820152601060248201526f063746f723a206b6e63546f6b656e20360841b604482015290519081900360640190fd5b6001600160a01b03811661019a576040805162461bcd60e51b815260206004820152601060248201526f063746f723a206b7962657244616f20360841b604482015290519081900360640190fd5b6000929092556001556001600160601b0319606092831b8116608052911b1660a05260805160601c60a05160601c611ba86101fe6000398061095d5280610f125280610f87528061154d525080610786528061117552806112c65250611ba86000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063711bbfd9116100ad578063c70d7b6c11610071578063c70d7b6c1461036b578063cfd4766314610373578063d42b72541461039f578063d46684b2146103c5578063f63e7811146103f15761012c565b8063711bbfd9146102c2578063811c7fe2146102f4578063901ab5b2146102fc578063b6b55f2514610328578063b7a13c4c146103455761012c565b80634408d2ba116100f45780634408d2ba146102245780634d8f51051461022c5780635c19a95c146102505780635ee5b4771461027657806360e4f2e01461029c5761012c565b8063072b77f11461013157806316554d62146101695780631c552f00146101bc5780632e1a7d4d146101d957806342ce39cb146101f8575b600080fd5b6101576004803603602081101561014757600080fd5b50356001600160a01b03166103f9565b60408051918252519081900360200190f35b6101956004803603604081101561017f57600080fd5b506001600160a01b038135169060200135610418565b6040805193845260208401929092526001600160a01b031682820152519081900360600190f35b610157600480360360208110156101d257600080fd5b503561047c565b6101f6600480360360208110156101ef57600080fd5b50356104d9565b005b6101956004803603604081101561020e57600080fd5b506001600160a01b03813516906020013561089e565b61015761094b565b61023461095b565b604080516001600160a01b039092168252519081900360200190f35b6101f66004803603602081101561026657600080fd5b50356001600160a01b031661097f565b6102346004803603602081101561028c57600080fd5b50356001600160a01b0316610c95565b610195600480360360208110156102b257600080fd5b50356001600160a01b0316610ce1565b6101f6600480360360608110156102d857600080fd5b506001600160a01b038135169060208101359060400135610d3f565b610234611173565b6102346004803603604081101561031257600080fd5b506001600160a01b038135169060200135611197565b6101f66004803603602081101561033e57600080fd5b5035611233565b6101956004803603602081101561035b57600080fd5b50356001600160a01b031661153e565b610157611635565b6101576004803603604081101561038957600080fd5b506001600160a01b03813516906020013561163b565b610157600480360360208110156103b557600080fd5b50356001600160a01b03166116d4565b610157600480360360408110156103db57600080fd5b506001600160a01b0381351690602001356116f2565b610157611783565b6001600160a01b0381166000908152600460205260409020545b919050565b6000806000610425611b16565b5050506000918252506003602090815260408083206001600160a01b039485168452825291829020825160608101845281548082526001830154938201849052600290920154909416939092018390529092909190565b600060015482108061048e5750600054155b1561049b57506000610413565b6104d360016104c76000546104bb6001548761178990919063ffffffff16565b9063ffffffff6117d216565b9063ffffffff61181416565b92915050565b60025460ff16610530576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002805460ff191690558061058c576040805162461bcd60e51b815260206004820152601560248201527f77697468647261773a20616d6f756e7420697320300000000000000000000000604482015290519081900360640190fd5b600061059661094b565b33600081815260046020526040902054919250908311156105e85760405162461bcd60e51b8152600401808060200182810382526032815260200180611b416032913960400191505060405180910390fd5b604080516001600160a01b038316602482015260448101859052606480820185905282518083039091018152608490910182526020810180516001600160e01b031663711bbfd960e01b17815291518151600093309392918291908083835b602083106106665780518252601f199092019160209182019101610647565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146106c8576040519150601f19603f3d011682016040523d82523d6000602084013e6106cd565b606091505b505090508061071f57604080518481526001600160a01b038416602082015280820186905290517fa412eef5316d3cbf9e2b4ba3d1cf3e482b40dc8946fd919b7f5053450fa621fb9181900360600190a15b6001600160a01b038216600090815260046020526040902054610748908563ffffffff61178916565b6001600160a01b03808416600081815260046020818152604080842096909655855163a9059cbb60e01b8152918201939093526024810189905293517f00000000000000000000000000000000000000000000000000000000000000009093169363a9059cbb936044808301949391928390030190829087803b1580156107ce57600080fd5b505af11580156107e2573d6000803e3d6000fd5b505050506040513d60208110156107f857600080fd5b505161084b576040805162461bcd60e51b815260206004820152601e60248201527f77697468647261773a2063616e206e6f74207472616e73666572206b6e630000604482015290519081900360640190fd5b6040805185815290516001600160a01b0384169185917f9da6493a92039daf47d1f2d7a782299c5994c6323eb1e972f69c432089ec52bf9181900360200190a350506002805460ff191660011790555050565b60008080806108ab61094b565b9050806001018511156108be5750610944565b845b60008181526005602090815260408083206001600160a01b038b16845290915290205460ff161561092b5760009081526003602090815260408083206001600160a01b038a811685529252909120805460018201546002909201549096509094501691506109449050565b806109355761093e565b600019016108c0565b86925050505b9250925092565b60006109564261047c565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b0381166109da576040805162461bcd60e51b815260206004820152601a60248201527f64656c65676174653a20726570726573656e7461746976652030000000000000604482015290519081900360640190fd5b3360006109e561094b565b90506109f1828261186e565b6001810160009081526003602090815260408083206001600160a01b0380871685529252909120600201548116908416811415610a3057505050610c92565b6001820160009081526003602090815260408083206001600160a01b03808816808652919093529220549190831614610b4757610a6d828461186e565b600180840160009081526003602090815260408083206001600160a01b038716845290915290200154610aa6908263ffffffff61178916565b600180850160009081526003602090815260408083206001600160a01b0388168452825280832084019490945560049052919091200154610aed908263ffffffff61178916565b6001600160a01b0380841660008181526004602090815260408083206001019590955584519182529351879492938916927ffbb976ae5268347766b726bd1edba29af0fe16f9c505fbd3b9a10cb6d00cfa3d928290030190a45b6001600160a01b03808516600081815260046020908152604080832060029081018054968c166001600160a01b0319978816811790915560018a0185526003845282852086865290935292209091018054909316811790925514610c8d57610baf858461186e565b600180840160009081526003602090815260408083206001600160a01b038a16845290915290200154610be8908263ffffffff61181416565b600180850160009081526003602090815260408083206001600160a01b038b168452825280832084019490945560049052919091200154610c2f908263ffffffff61181416565b6001600160a01b0380871660008181526004602090815260409182902060019081019590955581519485529051879492938916927ffbb976ae5268347766b726bd1edba29af0fe16f9c505fbd3b9a10cb6d00cfa3d92908290030190a45b505050505b50565b6001600160a01b0381811660009081526004602052604081206002015490911615610cdd576001600160a01b03808316600090815260046020526040902060020154166104d3565b5090565b6001600160a01b0380821660009081526004602052604081208054600182015460029092015490939192911615610d35576001600160a01b0380851660009081526004602052604090206002015416610d37565b835b929491935050565b333014610d93576040805162461bcd60e51b815260206004820152601560248201527f6f6e6c79207374616b696e6720636f6e74726163740000000000000000000000604482015290519081900360640190fd5b610d9d838261186e565b6001810160009081526003602090815260408083206001600160a01b0387168452909152902054610dd4908363ffffffff61178916565b6001820160009081526003602081815260408084206001600160a01b03808a16808752918452828620969096558685529282528084208385528252808420600281015493855254600490925283205491909316929190610e3a908663ffffffff61178916565b90506000610e4e838363ffffffff611a0416565b90506000610e62848363ffffffff61178916565b9050801561108c57876001600160a01b0316856001600160a01b031614610eea57610e8d858761186e565b60008681526003602090815260408083206001600160a01b0389168452909152902060010154610ec3908263ffffffff61178916565b60008781526003602090815260408083206001600160a01b038a1684529091529020600101555b60008681526003602090815260408083206001600160a01b03808d16855292529091208390557f0000000000000000000000000000000000000000000000000000000000000000161561108c57604080516001600160a01b038781166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663e2346d7160e01b178152925182516000947f000000000000000000000000000000000000000000000000000000000000000093909316939282918083835b60208310610fd15780518252601f199092019160209182019101610fb2565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611033576040519150601f19603f3d011682016040523d82523d6000602084013e611038565b606091505b505090508061108a57604080518881526001600160a01b038b1660208201528082018a905290517fa412eef5316d3cbf9e2b4ba3d1cf3e482b40dc8946fd919b7f5053450fa621fb9181900360600190a15b505b6001860160009081526003602090815260408083206001600160a01b03808d16808652919093529220600201541695508514611169576110cc858761186e565b600180870160009081526003602090815260408083206001600160a01b038a16845290915290200154611105908863ffffffff61178916565b600180880160009081526003602090815260408083206001600160a01b038b16845282528083208401949094556004905291909120015461114c908863ffffffff61178916565b6001600160a01b0386166000908152600460205260409020600101555b5050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806111a261094b565b9050806001018311156111b95760009150506104d3565b825b60008181526005602090815260408083206001600160a01b038916845290915290205460ff16156112175760009081526003602090815260408083206001600160a01b0380891685529252909120600201541691506104d39050565b806112215761122a565b600019016111bb565b50929392505050565b60008111611288576040805162461bcd60e51b815260206004820152601460248201527f6465706f7369743a20616d6f756e742069732030000000000000000000000000604482015290519081900360640190fd5b600061129261094b565b604080516323b872dd60e01b8152336004820181905230602483015260448201869052915192935090916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd9160648083019260209291908290030181600087803b15801561130e57600080fd5b505af1158015611322573d6000803e3d6000fd5b505050506040513d602081101561133857600080fd5b505161138b576040805162461bcd60e51b815260206004820152601a60248201527f6465706f7369743a2063616e206e6f742067657420746f6b656e000000000000604482015290519081900360640190fd5b611395818361186e565b6001820160009081526003602090815260408083206001600160a01b03851684529091529020546113cc908463ffffffff61181416565b6001830160009081526003602090815260408083206001600160a01b038616845282528083209390935560049052205461140c908463ffffffff61181416565b6001600160a01b038083166000818152600460209081526040808320959095556001870182526003815284822083835290529290922060020154169081146114f557611458818461186e565b600180840160009081526003602090815260408083206001600160a01b038616845290915290200154611491908563ffffffff61181416565b600180850160009081526003602090815260408083206001600160a01b03871684528252808320840194909455600490529190912001546114d8908563ffffffff61181416565b6001600160a01b0382166000908152600460205260409020600101555b604080518481526020810186905281516001600160a01b038516927f1599c0fcf897af5babc2bfcf707f5dc050f841b044d97c3251ecec35b9abf80b928290030190a250505050565b60008080336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146115bf576040805162461bcd60e51b815260206004820181905260248201527f696e6974416e6452657475726e446174613a206f6e6c79206b7962657244616f604482015290519081900360640190fd5b60006115c961094b565b90506115d5858261186e565b6115dd611b16565b5060009081526003602090815260408083206001600160a01b03978816845282529182902082516060810184528154808252600183015493820184905260029092015490971696909201869052909590949350915050565b60015481565b60008061164661094b565b90508060010183111561165d5760009150506104d3565b825b60008181526005602090815260408083206001600160a01b038916845290915290205460ff16156116b65760009081526003602090815260408083206001600160a01b038816845290915290205491506104d39050565b806116c0576116c9565b6000190161165f565b506000949350505050565b6001600160a01b031660009081526004602052604090206001015490565b6000806116fd61094b565b9050806001018311156117145760009150506104d3565b825b60008181526005602090815260408083206001600160a01b038916845290915290205460ff16156117705760009081526003602090815260408083206001600160a01b038816845290915290206001015491506104d39050565b8061177a576116c9565b60001901611716565b60005481565b60006117cb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611a1a565b9392505050565b60006117cb83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611ab1565b6000828201838110156117cb576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b0380831660009081526004602052604090206002015416806118c057506001600160a01b038216600081815260046020526040902060020180546001600160a01b0319169091179055815b6001600160a01b03831660008181526004602090815260408083206001810154905487855260058452828520958552949092529091205490919060ff1661196c5760008481526005602090815260408083206001600160a01b038981168086529184528285208054600160ff199091168117909155898652600385528386209286529190935292206002810180546001600160a01b031916928716929092179091559081018390558190555b6001840160009081526005602090815260408083206001600160a01b038916845290915290205460ff16610c8d57600193840160008181526005602090815260408083206001600160a01b03998a16808552908352818420805460ff19168a17905593835260038252808320938352929052206002810180546001600160a01b03191694909616939093179094559181019190915555565b6000818310611a1357816117cb565b5090919050565b60008184841115611aa95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a6e578181015183820152602001611a56565b50505050905090810190601f168015611a9b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008183611b005760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611a6e578181015183820152602001611a56565b506000838581611b0c57fe5b0495945050505050565b6040518060600160405280600081526020016000815260200160006001600160a01b03168152509056fe77697468647261773a206c617465737420616d6f756e74207374616b6564203c207769746864726177616c20616d6f756e74a2646970667358221220e226a6302b84b358849f5b5e0f541d9614dcdad0cedb6d983293d343b124399564736f6c634300060600330000000000000000000000000000000000000000000000000000000000127500000000000000000000000000000000000000000000000000000000005f0d599b000000000000000000000000dd974d5c2e2928dea5f71b9825b8b646686bd200000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000019640000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000e6a7338cba0a1070adfb22c07115299605454713
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c8063811c7fe21161011a578063b384abef116100ad578063d60d6bd41161007c578063d60d6bd414610672578063d993de621461067a578063e2346d711461078f578063ec0a7cc2146107bb578063f63e7811146107d8576101fb565b8063b384abef14610604578063b484f72614610627578063c70d7b6c1461064d578063d60079bf14610655576101fb565b806399e30ba8116100e957806399e30ba8146105c0578063a81ff705146105ec578063a910d096146105f4578063adea6960146105fc576101fb565b8063811c7fe2146105875780638c9bc2081461058f5780639010984e146105975780639833afaf1461059f576101fb565b806345598b4a11610192578063588df33a11610161578063588df33a1461043f5780636695c981146104475780636fbf12ad1461047a578063809e2c621461049d576101fb565b806345598b4a1461035e57806345bd004e1461037d5780634650e3ab146103ae5780634cf088d91461041b576101fb565b80631c552f00116101ce5780631c552f00146102f0578063220046781461030d57806342322250146103395780634408d2ba14610356576101fb565b80630b4defe4146102005780630bff230a1461022f5780631248a166146102a7578063166b4997146102c4575b600080fd5b61021d6004803603602081101561021657600080fd5b50356107e0565b60408051918252519081900360200190f35b61024c6004803603602081101561024557600080fd5b50356107f2565b6040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561029257818101518382015260200161027a565b50505050905001935050505060405180910390f35b61021d600480360360208110156102bd57600080fd5b5035610895565b61021d600480360360408110156102da57600080fd5b506001600160a01b0381351690602001356108aa565b61021d6004803603602081101561030657600080fd5b50356108c7565b61021d6004803603604081101561032357600080fd5b506001600160a01b038135169060200135610924565b61021d6004803603602081101561034f57600080fd5b5035610941565b61021d610953565b61037b6004803603602081101561037457600080fd5b5035610964565b005b61039a6004803603602081101561039357600080fd5b5035610bf7565b604080519115158252519081900360200190f35b6103cb600480360360208110156103c457600080fd5b5035610c2a565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104075781810151838201526020016103ef565b505050509050019250505060405180910390f35b610423610c8c565b604080516001600160a01b039092168252519081900360200190f35b61021d610cb0565b61044f610cb6565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b61021d6004803603604081101561049057600080fd5b5080359060200135610ce1565b61021d60048036036101008110156104b457600080fd5b60ff8235169160208101359160408201359160608101359160808201359160a08101359181019060e0810160c08201356401000000008111156104f657600080fd5b82018360208201111561050857600080fd5b8035906020019184602083028401116401000000008311171561052a57600080fd5b91939092909160208101903564010000000081111561054857600080fd5b82018360208201111561055a57600080fd5b8035906020019184600183028401116401000000008311171561057c57600080fd5b509092509050610d68565b610423611214565b610423611238565b61021d611247565b6105a761124d565b6040805192835260208301919091528051918290030190f35b61021d600480360360408110156105d657600080fd5b506001600160a01b038135169060200135611266565b61021d611296565b61021d61129b565b6105a76112a0565b61037b6004803603604081101561061a57600080fd5b5080359060200135611353565b61021d6004803603602081101561063d57600080fd5b50356001600160a01b0316611639565b61021d611650565b6105a76004803603602081101561066b57600080fd5b5035611656565b61044f6116a3565b6106976004803603602081101561069057600080fd5b503561175d565b604051808a60028111156106a757fe5b60ff1681526020018981526020018881526020018781526020018681526020018581526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156107105781810151838201526020016106f8565b50505050905090810190601f16801561073d5780820380516001836020036101000a031916815260200191505b508381038252845181528451602091820191808701910280838360005b8381101561077257818101518382015260200161075a565b505050509050019b50505050505050505050505060405180910390f35b61037b600480360360408110156107a557600080fd5b506001600160a01b038135169060200135611895565b6105a7600480360360208110156107d157600080fd5b5035611acc565b61021d611d4f565b60106020526000908152604090205481565b606060006107fe6127f8565b60076000858152602001908152602001600020600901604051806040016040529081600082015481526020016001820180548060200260200160405190810160405280929190818152602001828054801561087857602002820191906000526020600020905b815481526020019060010190808311610864575b505050919092525050815160209092015196919550909350505050565b6000818152600960205260409020545b919050565b600b60209081526000928352604080842090915290825290205481565b60006001548210806108d95750600054155b156108e6575060006108a5565b61091e600161091260005461090660015487611d5590919063ffffffff16565b9063ffffffff611d9716565b9063ffffffff611dd916565b92915050565b600a60209081526000928352604080842090915290825290205481565b600d6020526000908152604090205481565b600061095e426108c7565b90505b90565b6004546001600160a01b031633146109b6576040805162461bcd60e51b815260206004820152601060248201526f37b7363c903230b7a7b832b930ba37b960811b604482015290519081900360640190fd5b60008181526007602052604090208054610100900460ff16610a095760405162461bcd60e51b8152600401808060200182810382526028815260200180612bd96028913960400191505060405180910390fd5b42816001015411610a4b5760405162461bcd60e51b8152600401808060200182810382526028815260200180612a256028913960400191505060405180910390fd5b6000610a5a82600101546108c7565b90506001825460ff166002811115610a6e57fe5b1415610a88576000818152600d6020526040812055610ab0565b6002825460ff166002811115610a9a57fe5b1415610ab0576000818152601060205260408120555b60008381526007602081905260408220805461ffff191681556001810183905560028101839055600381018390556004810183905560058101839055600681018390559190610b0190830182612812565b610b0f600883016000612859565b60006009830181815590610b26600a850182612859565b505050600082815260086020526040812091505b8154811015610bc55784828281548110610b5057fe5b90600052602060002001541415610bbd57815482906000198101908110610b7357fe5b9060005260206000200154828281548110610b8a57fe5b906000526020600020018190555081805480610ba257fe5b60019003818190600052602060002001600090559055610bc5565b600101610b3a565b5060405184907fef29bb5bcfd2b2ff4bc50d710898467757ff87aad1031fc953907b65127f86fc90600090a250505050565b600080610c02610953565b9050808310610c155760009150506108a5565b50506000908152600960205260409020541590565b600081815260086020908152604091829020805483518184028101840190945280845260609392830182828015610c8057602002820191906000526020600020905b815481526020019060010190808311610c6c575b50505050509050919050565b7f000000000000000000000000ecf0bdb7b3f349abfd68c3563678124c5e8aaea381565b60065481565b6000806000806000610cc66116a3565b600e849055600f839055939992985090965094509092509050565b6000612710610cf6848463ffffffff611dd916565b1115610d49576040805162461bcd60e51b815260206004820152601760248201527f72657761726420706c7573207265626174652068696768000000000000000000604482015290519081900360640190fd5b610d618361091284600160801b63ffffffff611e3316565b9392505050565b6004546000906001600160a01b03163314610dbd576040805162461bcd60e51b815260206004820152601060248201526f37b7363c903230b7a7b832b930ba37b960811b604482015290519081900360640190fd5b6000610dc88b6108c7565b9050610e0c8c8c8c8c8c8c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611e8c92505050565b600654610e2090600163ffffffff611dd916565b60068190556000828152600860209081526040822080546001818101835591845291909220018290559092508c6002811115610e5857fe5b1415610e74576000818152600d60205260409020829055610e9a565b60028c6002811115610e8257fe5b1415610e9a5760008181526010602052604090208290555b610ea2612877565b60405180606001604052808b81526020018a8152602001898152509050610ec76127f8565b6040805180820190915260008152602081018867ffffffffffffffff81118015610ef057600080fd5b50604051908082528060200260200182016040528015610f1a578160200160208202803683370190505b5081525090506040518061012001604052808f6002811115610f3857fe5b81526020016001151581526020018e81526020018d81526020017f000000000000000000000000dd974d5c2e2928dea5f71b9825b8b646686bd2006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b505afa158015610fbf573d6000803e3d6000fd5b505050506040513d6020811015610fd557600080fd5b50518152602081810185905260408051601f8a0183900483028101830182528981529201919089908990819084018382808284376000920191909152505050908252506040805160208b810282810182019093528b82529283019290918c918c9182918501908490808284376000920182905250938552505050602091820184905286815260079091526040902081518154829060ff1916600183600281111561107b57fe5b021790555060208281015182549015156101000261ff00199091161782556040808401516001840155606084015160028401556080840151600384015560a0840151805160048501558083015160058501550151600683015560c083015180516110eb9260078501920190612898565b5060e08201518051611107916008840191602090910190612916565b50610100820151805160098301908155602080830151805161112f92600a8701920190612916565b505050905050837fba908e34477602dcf3b8b10115cb9ba1f56c512e94a0beb561ad0245026cda138f8f8f8f8f8f8f8f8f8f604051808b600281111561117157fe5b60ff1681526020018a815260200189815260200188815260200187815260200186815260200180602001806020018381038352878782818152602001925060200280828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039e50909c50505050505050505050505050a25050509a9950505050505050505050565b7f000000000000000000000000dd974d5c2e2928dea5f71b9825b8b646686bd20081565b6004546001600160a01b031681565b60055481565b6000806112586112a0565b600c82905590939092509050565b600080611271610953565b905080831061128457600091505061091e565b61128e84846123a0565b949350505050565b600881565b600a81565b60008060006112ad610953565b9050600c5492506112ec60016112e06112d160005485611e3390919063ffffffff16565b6001549063ffffffff611dd916565b9063ffffffff611d5516565b9150806112f9575061134f565b6000600d8161130f84600163ffffffff611d5516565b81526020019081526020016000205490508060001415611331575061134f9050565b600061133c82611acc565b955090508061134b57600c5494505b5050505b9091565b61135d828261252e565b336000611368610953565b905060008060007f000000000000000000000000ecf0bdb7b3f349abfd68c3563678124c5e8aaea36001600160a01b031663b7a13c4c866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050606060405180830381600087803b1580156113e757600080fd5b505af11580156113fb573d6000803e3d6000fd5b505050506040513d606081101561141157600080fd5b5080516020820151604090920151909450909250905060006001600160a01b03808316908716146114425782611452565b611452848463ffffffff611dd916565b6001600160a01b0387166000908152600b602090815260408083208c845282528083205460079092529091209192509060090181611545576001600160a01b0388166000908152600a602090815260408083208a845282528083208054600101905560099091529020546114cc908463ffffffff611dd916565b60008881526009602052604090205560018101805461150e9185916000198d019081106114f557fe5b9060005260206000200154611dd990919063ffffffff16565b8160010160018b038154811061152057fe5b600091825260209091200155805461153e908463ffffffff611dd916565b81556115d0565b8882146115d05761157b8382600101600185038154811061156257fe5b9060005260206000200154611d5590919063ffffffff16565b81600101600184038154811061158d57fe5b90600052602060002001819055506115b1838260010160018c03815481106114f557fe5b8160010160018b03815481106115c357fe5b6000918252602090912001555b6001600160a01b0388166000818152600b602090815260408083208e84528252918290208c905581518c815291518d938b9390927fc32b42768a47a585121e9b8d7a2ab9d3f34c326a192dee11ee1732e3d18313f392918290030190a450505050505050505050565b600080611644610953565b9050610d6183826123a0565b60015481565b60008061166e600160801b600163ffffffff611d5516565b83169050611687600160801b600163ffffffff611d5516565b61169b84600160801b63ffffffff611d9716565b169150915091565b60008060008060006116b3610953565b91506116d260016112e06112d160005486611e3390919063ffffffff16565b600e54600f5490955093509050811561173e5760006010816116fb85600163ffffffff611d5516565b81526020019081526020016000205490508060001461173c5760008061172083611acc565b909250905081156117395761173481611656565b975095505b50505b505b611754846112e06127108663ffffffff611d5516565b94509091929394565b600081815260076020818152604092839020805460018083015460028085015460038601546004870154600588015460068901549a890180548d516101009982161599909902600019011695909504601f81018b90048b0288018b01909c528b875260ff9097169a94999298919790969592946060948594929390919083018282801561182b5780601f106118005761010080835404028352916020019161182b565b820191906000526020600020905b81548152906001019060200180831161180e57829003601f168201915b505050505092508060080180548060200260200160405190810160405280929190818152602001828054801561188057602002820191906000526020600020905b81548152602001906001019080831161186c575b50505050509150509193959799909294969850565b336001600160a01b037f000000000000000000000000ecf0bdb7b3f349abfd68c3563678124c5e8aaea31614611912576040805162461bcd60e51b815260206004820152601560248201527f6f6e6c79207374616b696e6720636f6e74726163740000000000000000000000604482015290519081900360640190fd5b8061191c57611ac8565b6000611926610953565b6001600160a01b0384166000908152600a6020908152604080832084845290915290205490915080611959575050611ac8565b61198761196c828563ffffffff611e3316565b6000848152600960205260409020549063ffffffff611d5516565b60008381526009602090815260408083209390935560088152908290208054835181840281018401909452808452606093928301828280156119e857602002820191906000526020600020905b8154815260200190600101908083116119d4575b50939450600093505050505b8151811015611ac3576000828281518110611a0b57fe5b6020908102919091018101516001600160a01b0389166000908152600b83526040808220838352909352919091205490915080611a49575050611abb565b600082815260076020526040902060028101544211611ab7576009810154611a77908963ffffffff611d5516565b6009820155600a81018054611a96918a91600019860190811061156257fe5b600a820180546000198501908110611aaa57fe5b6000918252602090912001555b5050505b6001016119f4565b505050505b5050565b60008181526007602052604081208054829190610100900460ff16611af8575060009150819050611d4a565b4281600201541115611b11575060009150819050611d4a565b600381015480611b2a575060009250829150611d4a9050565b6009820154600a830180546040805160208084028201810190925282815260609390929091830182828015611b7e57602002820191906000526020600020905b815481526020019060010190808311611b6a575b5093945060009350839250829150505b8351811015611bfb5781848281518110611ba457fe5b60200260200101511115611bd357806001019250838181518110611bc457fe5b60200260200101519150611bf3565b81848281518110611be057fe5b60200260200101511415611bf357600092505b600101611b8e565b5081611c14575060009650869550611d4a945050505050565b611c1c612877565b506040805160608101825260048801548152600588015460208201526006880154918101919091526003870154600090611c689061090688670de0b6b3a764000063ffffffff611e3316565b90508082600001511115611c8b575060009850889750611d4a9650505050505050565b6000611cb0670de0b6b3a7640000610906848660400151611e3390919063ffffffff16565b905082602001518111611d1e576020830151600090611cd5908363ffffffff611d5516565b9050611ce7818963ffffffff611e3316565b611cff86670de0b6b3a764000063ffffffff611e3316565b1015611d1c575060009a508a9950611d4a98505050505050505050565b505b849a508860080160018c0381548110611d3357fe5b906000526020600020015499505050505050505050505b915091565b60005481565b6000610d6183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506126fc565b6000610d6183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612793565b600082820183811015610d61576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082611e425750600061091e565b82820282848281611e4f57fe5b0414610d615760405162461bcd60e51b8152600401808060200182810382526021815260200180612a4d6021913960400191505060405180910390fd5b42861015611ecb5760405162461bcd60e51b815260040180806020018281038252602181526020018061296b6021913960400191505060405180910390fd5b600554611edf90879063ffffffff611dd916565b611ef086600163ffffffff611dd916565b1015611f2d5760405162461bcd60e51b8152600401808060200182810382526028815260200180612acf6028913960400191505060405180910390fd5b6000611f38876108c7565b90506000611f45876108c7565b600083815260086020526040902054909150600a11611f955760405162461bcd60e51b815260040180806020018281038252602281526020018061298c6022913960400191505060405180910390fd5b808214611fd35760405162461bcd60e51b815260040180806020018281038252602a815260200180612a6e602a913960400191505060405180910390fd5b6000611fdd610953565b9050611ff081600163ffffffff611dd916565b83111561202e5760405162461bcd60e51b815260040180806020018281038252602f815260200180612baa602f913960400191505060405180910390fd5b8351600181118015612041575060088111155b61207c5760405162461bcd60e51b8152600401808060200182810382526029815260200180612b816029913960400191505060405180910390fd5b60008b600281111561208a57fe5b14156120fc5760005b85518110156120f65760008682815181106120aa57fe5b6020026020010151116120ee5760405162461bcd60e51b815260040180806020018281038252602c815260200180612af7602c913960400191505060405180910390fd5b600101612093565b5061229c565b60018b600281111561210a57fe5b14156121c5576000848152600d60205260409020541561215b5760405162461bcd60e51b815260040180806020018281038252603f8152602001806129ae603f913960400191505060405180910390fd5b60005b85518110156120f65760026127100486828151811061217957fe5b6020026020010151106121bd5760405162461bcd60e51b8152600401808060200182810382526038815260200180612b496038913960400191505060405180910390fd5b60010161215e565b600084815260106020526040902054156122105760405162461bcd60e51b8152600401808060200182810382526037815260200180612a986037913960400191505060405180910390fd5b60005b855181101561229a5760008061223b88848151811061222e57fe5b6020026020010151611656565b9092509050612710612253828463ffffffff611dd916565b11156122905760405162461bcd60e51b81526004018080602001828103825260388152602001806129ed6038913960400191505060405180910390fd5b5050600101612213565b505b670de0b6b3a76400008811156122e35760405162461bcd60e51b8152600401808060200182810382526026815260200180612b236026913960400191505060405180910390fd5b600160801b871061233b576040805162461bcd60e51b815260206004820152601960248201527f76616c6964617465506172616d733a2063206973206869676800000000000000604482015290519081900360640190fd5b600160801b8610612393576040805162461bcd60e51b815260206004820152601960248201527f76616c6964617465506172616d733a2074206973206869676800000000000000604482015290519081900360640190fd5b5050505050505050505050565b6001600160a01b0382166000908152600a60209081526040808320848452909152812054806123d357600091505061091e565b60008060007f000000000000000000000000ecf0bdb7b3f349abfd68c3563678124c5e8aaea36001600160a01b03166316554d6288886040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060606040518083038186803b15801561245657600080fd5b505afa15801561246a573d6000803e3d6000fd5b505050506040513d606081101561248057600080fd5b5080516020820151604090920151909450909250905060006001600160a01b03808316908916146124b157826124c1565b6124c1848463ffffffff611dd916565b9050806124d65760009550505050505061091e565b60006124e8868363ffffffff611e3316565b6000898152600960205260409020549091508082111561250457fe5b6125208161090684670de0b6b3a764000063ffffffff611e3316565b9a9950505050505050505050565b60008281526007602052604090208054610100900460ff16612597576040805162461bcd60e51b815260206004820152601c60248201527f766f74653a2063616d706169676e20646f65736e277420657869737400000000604482015290519081900360640190fd5b42816001015411156125f0576040805162461bcd60e51b815260206004820152601a60248201527f766f74653a2063616d706169676e206e6f742073746172746564000000000000604482015290519081900360640190fd5b4281600201541015612649576040805162461bcd60e51b815260206004820152601c60248201527f766f74653a2063616d706169676e20616c726561647920656e64656400000000604482015290519081900360640190fd5b6000821161269e576040805162461bcd60e51b815260206004820152601160248201527f766f74653a206f7074696f6e2069732030000000000000000000000000000000604482015290519081900360640190fd5b60088101548211156126f7576040805162461bcd60e51b815260206004820152601c60248201527f766f74653a206f7074696f6e206973206e6f7420696e2072616e676500000000604482015290519081900360640190fd5b505050565b6000818484111561278b5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612750578181015183820152602001612738565b50505050905090810190601f16801561277d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836127e25760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612750578181015183820152602001612738565b5060008385816127ee57fe5b0495945050505050565b604051806040016040528060008152602001606081525090565b50805460018160011615610100020316600290046000825580601f106128385750612856565b601f0160209004906000526020600020908101906128569190612950565b50565b50805460008255906000526020600020908101906128569190612950565b60405180606001604052806000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106128d957805160ff1916838001178555612906565b82800160010185558215612906579182015b828111156129065782518255916020019190600101906128eb565b50612912929150612950565b5090565b82805482825590600052602060002090810192821561290657916020028201828111156129065782518255916020019190600101906128eb565b61096191905b80821115612912576000815560010161295656fe76616c6964617465506172616d733a20737461727420696e20746865207061737476616c6964617465506172616d733a20746f6f206d616e792063616d706169676e7376616c6964617465506172616d733a20616c726561647920686164206e6574776f726b206665652063616d706169676e20666f7220746869732065706f636876616c6964617465506172616d733a20726562617465202b207265776172642063616e277420626520626967676572207468616e2042505363616e63656c43616d706169676e3a2063616d706169676e20616c72656164792073746172746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7776616c6964617465506172616d733a207374617274202620656e64206e6f742073616d652065706f636876616c6964617465506172616d733a20616c726561647920686164206272722063616d706169676e20666f7220746869732065706f636876616c6964617465506172616d733a2063616d706169676e206475726174696f6e206973206c6f7776616c6964617465506172616d733a2067656e6572616c2063616d706169676e206f7074696f6e206973203076616c6964617465506172616d733a206d696e2070657263656e74616765206973206869676876616c6964617465506172616d733a206e6574776f726b20666565206d75737420626520736d616c6c6572207468656e20425053202f203276616c6964617465506172616d733a20696e76616c6964206e756d626572206f66206f7074696f6e7376616c6964617465506172616d733a206f6e6c7920666f722063757272656e74206f72206e6578742065706f63687363616e63656c43616d706169676e3a2063616d706169676e494420646f65736e2774206578697374a2646970667358221220313c6142437875dcaf3f6546db75663d187e82ca7247be8fa4039cdd632f8a2864736f6c63430006060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000127500000000000000000000000000000000000000000000000000000000005F0D599B000000000000000000000000dd974d5c2e2928dea5f71b9825b8b646686bd200000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000019640000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000e6a7338cba0a1070adfb22c07115299605454713
-----Decoded View---------------
Arg [0] : _epochPeriod (uint256): 1209600
Arg [1] : _startTimestamp (uint256): 1594710427
Arg [2] : _knc (address): 0xdd974D5C2e2928deA5F71b9825b8b646686BD200
Arg [3] : _defaultNetworkFeeBps (uint256): 20
Arg [4] : _defaultRewardBps (uint256): 6500
Arg [5] : _defaultRebateBps (uint256): 3000
Arg [6] : _daoOperator (address): 0xE6A7338cba0A1070AdfB22c07115299605454713
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000127500
Arg [1] : 000000000000000000000000000000000000000000000000000000005F0D599B
Arg [2] : 000000000000000000000000dd974d5c2e2928dea5f71b9825b8b646686bd200
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [4] : 0000000000000000000000000000000000000000000000000000000000001964
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000bb8
Arg [6] : 000000000000000000000000e6a7338cba0a1070adfb22c07115299605454713
Deployed Bytecode Sourcemap
37530:28781:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;37530:28781:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;40029:47:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;40029:47:0;;:::i;:::-;;;;;;;;;;;;;;;;53343:350;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;53343:350:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;53343:350:0;;;;;;;;;;;;;;;;;;52215:125;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;52215:125:0;;:::i;39653:72::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;39653:72:0;;;;;;;;:::i;6357:381::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;6357:381:0;;:::i;39493:66::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;39493:66:0;;;;;;;;:::i;39834:54::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;39834:54:0;;:::i;6232:117::-;;;:::i;47280:1111::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;47280:1111:0;;:::i;:::-;;51671:266;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;51671:266:0;;:::i;:::-;;;;;;;;;;;;;;;;;;52016:150;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;52016:150:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;52016:150:0;;;;;;;;;;;;;;;;;38916:38;;;:::i;:::-;;;;-1:-1:-1;;;;;38916:38:0;;;;;;;;;;;;;;39010:34;;;:::i;50980:474::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60410:312;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;60410:312:0;;;;;;;:::i;44641:2418::-;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;44641:2418:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;44641:2418:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;44641:2418:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;44641:2418:0;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;44641:2418:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;44641:2418:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;44641:2418:0;;-1:-1:-1;44641:2418:0;-1:-1:-1;44641:2418:0;:::i;38877:32::-;;;:::i;6848:26::-;;;:::i;38818:52::-;;;:::i;50485:294::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;53946:404;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;53946:404:0;;;;;;;;:::i;37770:50::-;;;:::i;37665:::-;;;:::i;57599:1068::-;;;:::i;48627:1683::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;48627:1683:0;;;;;;;:::i;54459:277::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;54459:277:0;-1:-1:-1;;;;;54459:277:0;;:::i;6175:48::-;;;:::i;60013:270::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;60013:270:0;;:::i;58764:1197::-;;;:::i;52348:987::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;52348:987:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;52348:987:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52348:987:0;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;52348:987:0;;;;;;;;;;;;;;;;;;;;;;;;;;42246:1700;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;42246:1700:0;;;;;;;;:::i;55068:2445::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;55068:2445:0;;:::i;6124:44::-;;;:::i;40029:47::-;;;;;;;;;;;;;:::o;53343:350::-;53447:27;53476:22;53516:32;;:::i;:::-;53551:12;:24;53564:10;53551:24;;;;;;;;;;;:41;;53516:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;53516:76:0;;;;-1:-1:-1;;53620:19:0;;53663:22;;;;;;53620:19;;-1:-1:-1;53343:350:0;;-1:-1:-1;;;;53343:350:0:o;52215:125::-;52282:7;52309:23;;;:16;:23;;;;;;52215:125;;;;:::o;39653:72::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;6357:381::-;6430:7;6466:24;;6454:9;:36;:65;;;-1:-1:-1;6494:20:0;;:25;6454:65;6450:106;;;-1:-1:-1;6543:1:0;6536:8;;6450:106;6654:76;6728:1;6655:67;6701:20;;6656:39;6670:24;;6656:9;:13;;:39;;;;:::i;:::-;6655:45;:67;:45;:67;:::i;:::-;6654:73;:76;:73;:76;:::i;:::-;6647:83;6357:381;-1:-1:-1;;6357:381:0:o;39493:66::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;39834:54::-;;;;;;;;;;;;;:::o;6232:117::-;6295:7;6322:19;6337:3;6322:14;:19::i;:::-;6315:26;;6232:117;;:::o;47280:1111::-;7103:11;;-1:-1:-1;;;;;7103:11:0;7089:10;:25;7081:54;;;;;-1:-1:-1;;;7081:54:0;;;;;;;;;;;;-1:-1:-1;;;7081:54:0;;;;;;;;;;;;;;;47360:25:::1;47388:24:::0;;;:12:::1;:24;::::0;;;;47431:23;;::::1;::::0;::::1;;;47423:76;;;;-1:-1:-1::0;;;47423:76:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47546:3;47520:8;:23;;;:29;47512:82;;;;-1:-1:-1::0;;;47512:82:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47607:13;47623:39;47638:8;:23;;;47623:14;:39::i;:::-;47607:55:::0;-1:-1:-1;47704:23:0::1;47679:21:::0;;::::1;;:48;::::0;::::1;;;;;;;47675:230;;;47751:26;::::0;;;:19:::1;:26;::::0;;;;47744:33;47675:230:::1;;;47824:26;47799:21:::0;;::::1;;:51;::::0;::::1;;;;;;;47795:110;;;47874:19;::::0;;;:12:::1;:19;::::0;;;;47867:26;47795:110:::1;47924:24;::::0;;;:12:::1;:24;::::0;;;;;;47917:31;;-1:-1:-1;;47917:31:0;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;47924:24;;47917:31:::1;::::0;;::::1;47924:24:::0;47917:31:::1;:::i;:::-;;;::::0;::::1;;;:::i;:::-;;;::::0;::::1;::::0;;;;::::1;::::0;;;;::::1;:::i;:::-;-1:-1:-1::0;;;47961:29:0::1;47993:21:::0;;;:14:::1;:21;::::0;;;;;-1:-1:-1;48025:312:0::1;48049:18:::0;;48045:22;::::1;48025:312;;;48111:10;48093:11;48105:1;48093:14;;;;;;;;;;;;;;;;:28;48089:237;;;48227:18:::0;;48215:11;;-1:-1:-1;;48227:22:0;;;48215:35;::::1;;;;;;;;;;;;;48198:11;48210:1;48198:14;;;;;;;;;;;;;;;:52;;;;48269:11;:17;;;;;;;;;;;;;;;;;;;;;;;;48305:5;;48089:237;48069:3;;48025:312;;;-1:-1:-1::0;48354:29:0::1;::::0;48372:10;;48354:29:::1;::::0;;;::::1;7146:1;;;47280:1111:::0;:::o;51671:266::-;51752:4;51769:16;51788:23;:21;:23::i;:::-;51769:42;;51835:8;51826:5;:17;51822:62;;51867:5;51860:12;;;;;51822:62;-1:-1:-1;;51901:23:0;;;;:16;:23;;;;;;:28;;51671:266::o;52016:150::-;52137:21;;;;:14;:21;;;;;;;;;52123:35;;;;;;;;;;;;;;;;;52082:28;;52123:35;;;52137:21;52123:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52016:150;;;:::o;38916:38::-;;;:::o;39010:34::-;;;;:::o;50980:474::-;51085:17;51117:19;51151;51185:13;51213:23;51328:18;:16;:18::i;:::-;51357:13;:39;;;51407:25;:39;;;51264:82;;;;-1:-1:-1;51264:82:0;;-1:-1:-1;51264:82:0;-1:-1:-1;51264:82:0;;-1:-1:-1;50980:474:0;-1:-1:-1;50980:474:0:o;60410:312::-;60550:12;32102:5;60588:28;:11;60604;60588:28;:15;:28;:::i;:::-;:35;;60580:71;;;;;-1:-1:-1;;;60580:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;60669:45;60702:11;60670:26;:11;-1:-1:-1;;;60670:26:0;:15;:26;:::i;60669:45::-;60662:52;60410:312;-1:-1:-1;;;60410:312:0:o;44641:2418::-;7103:11;;44981:18;;-1:-1:-1;;;;;7103:11:0;7089:10;:25;7081:54;;;;;-1:-1:-1;;;7081:54:0;;;;;;;;;;;;-1:-1:-1;;;7081:54:0;;;;;;;;;;;;;;;45142:21:::1;45166:30;45181:14;45166;:30::i;:::-;45142:54;;45209:231;45246:12;45273:14;45302:12;45329:24;45368:12;45395;45422:7;;45209:231;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16:::0;::::1;74:27:::0;;;;-1:-1;45209:22:0::1;::::0;-1:-1:-1;;;45209:231:0:i:1;:::-;45471:15;::::0;:22:::1;::::0;45491:1:::1;45471:22;:19;:22;:::i;:::-;45453:15;:40:::0;;;45599:29:::1;::::0;;;:14:::1;:29;::::0;;;;;;27:10:-1;;39:1:::1;23:18:::0;;::::1;45:23:::0;;45599:46:0;;;;;;;::::1;::::0;;;45453:40;;-1:-1:-1;45720:12:0::1;:39;;;;;;;;;45716:240;;;45776:34;::::0;;;:19:::1;:34;::::0;;;;:47;;;45716:240:::1;;;45861:26;45845:12;:42;;;;;;;;;45841:115;;;45904:27;::::0;;;:12:::1;:27;::::0;;;;:40;;;45841:115:::1;45968:30;;:::i;:::-;46001:171;;;;;;;;46054:24;46001:171;;;;46107:12;46001:171;;;;46148:12;46001:171;;::::0;45968:204:::1;;46183:40;;:::i;:::-;46226:116;::::0;;;;::::1;::::0;;;-1:-1:-1;46226:116:0;;::::1;::::0;::::1;46315:7:::0;46301:29:::1;::::0;::::1;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;46301:29:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;::::0;-1:-1;46301:29:0::1;;46226:116;;::::0;46183:159:::1;;46382:380;;;;;;;;46455:12;46382:380;;;;;;;;;;;;46422:4;46382:380;;;;;;46498:14;46382:380;;;;46541:12;46382:380;;;;46584:8;-1:-1:-1::0;;;;;46584:20:0::1;;:22;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;46584:22:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;46584:22:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;46584:22:0;46382:380;;46584:22:::1;46382:380:::0;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;46627:4;;;;;;46382:380;::::1;46627:4:::0;;;;46382:380;1:33:-1::1;99:1;81:16:::0;::::1;74:27:::0;;;;-1:-1;;;46382:380:0;;;-1:-1:-1;46382:380:0::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;;;;;;;::::1;::::0;;;46694:7;;;;;;46382:380;::::1;::::0;46694:7;;46382:380;46694:7;46382:380;1:33:-1::1;99:1;81:16:::0;::::1;74:27:::0;;;-1:-1;46382:380:0;;;-1:-1:-1;;;46382:380:0::1;::::0;;::::1;::::0;;;46355:24;;;:12:::1;:24:::0;;;;;;:407;;;;:24;;-1:-1:-1;;46355:407:0::1;::::0;;::::1;::::0;::::1;;;;;;;;::::0;;-1:-1:-1;46355:407:0::1;::::0;;::::1;::::0;;;;::::1;;;;-1:-1:-1::0;;46355:407:0;;::::1;;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;46355:407:0::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;46355:407:0::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;;::::1;::::0;::::1;:::i;:::-;;;;;;;46840:10;46780:271;46813:12;46865:14;46894:12;46921:24;46960:12;46987;47014:7;;47036:4;;46780:271;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16:::0;;::::1;74:27:::0;137:4:::1;117:14;-1:-1:::0;;113:30:::1;157:16:::0;;::::1;46780:271:0::0;;::::1;::::0;;;;;::::1;;::::0;-1:-1:-1;46780:271:0;;;;;1:33:-1::1;99:1;81:16:::0;;::::1;74:27:::0;46780:271:0::1;::::0;137:4:-1::1;117:14:::0;;::::1;-1:-1:::0;;113:30:::1;157:16:::0;;::::1;46780:271:0::0;;::::1;::::0;-1:-1:-1;46780:271:0;;-1:-1:-1;;;;;;;;;;;;;46780:271:0::1;7146:1;;;44641:2418:::0;;;;;;;;;;;;:::o;38877:32::-;;;:::o;6848:26::-;;;-1:-1:-1;;;;;6848:26:0;;:::o;38818:52::-;;;;:::o;50485:294::-;50583:16;50601:23;50672:25;:23;:25::i;:::-;50738:22;:33;;;50642:55;;;;-1:-1:-1;50485:294:0;-1:-1:-1;50485:294:0:o;53946:404::-;54094:7;54167:16;54186:23;:21;:23::i;:::-;54167:42;;54233:8;54224:5;:17;54220:58;;54265:1;54258:8;;;;;54220:58;54297:45;54328:6;54336:5;54297:30;:45::i;:::-;54290:52;53946:404;-1:-1:-1;;;;53946:404:0:o;37770:50::-;37819:1;37770:50;:::o;37665:::-;37713:2;37665:50;:::o;57599:1068::-;57700:16;57718:23;57759:16;57778:23;:21;:23::i;:::-;57759:42;;57823:22;;57812:33;;57968:71;58037:1;57968:64;57997:34;58010:20;;57997:8;:12;;:34;;;;:::i;:::-;57968:24;;;:64;:28;:64;:::i;:::-;:68;:71;:68;:71;:::i;:::-;57950:89;-1:-1:-1;58054:13:0;58050:80;;-1:-1:-1;58084:34:0;;58050:80;58140:18;58161:19;58140:18;58181:15;:8;58194:1;58181:15;:12;:15;:::i;:::-;58161:36;;;;;;;;;;;;58140:57;;58212:10;58226:1;58212:15;58208:152;;;-1:-1:-1;58314:34:0;;-1:-1:-1;58314:34:0;58208:152;58372:21;58432:44;58465:10;58432:32;:44::i;:::-;58404:72;-1:-1:-1;58404:72:0;-1:-1:-1;58491:18:0;58487:128;;58581:22;;58570:33;;58487:128;-1:-1:-1;;;57599:1068:0;;;:::o;48627:1683::-;48706:38;48725:10;48737:6;48706:18;:38::i;:::-;48772:10;48755:14;48814:23;:21;:23::i;:::-;48795:42;;48849:13;48864:14;48880:22;48919:7;-1:-1:-1;;;;;48919:46:0;;48966:6;48919:54;;;;;;;;;;;;;-1:-1:-1;;;;;48919:54:0;-1:-1:-1;;;;;48919:54:0;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;48919:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48919:54:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;48919:54:0;;;;;;;;;;;;;-1:-1:-1;48919:54:0;;-1:-1:-1;48919:54:0;-1:-1:-1;48986:18:0;-1:-1:-1;;;;;49007:24:0;;;;;;;:53;;49054:6;49007:53;;;49034:17;:5;49044:6;49034:17;:9;:17;:::i;:::-;-1:-1:-1;;;;;49097:25:0;;49071:23;49097:25;;;:17;:25;;;;;;;;:37;;;;;;;;;49183:12;:24;;;;;;48986:74;;-1:-1:-1;49097:37:0;49183:41;;49241:20;49237:946;;-1:-1:-1;;;;;49367:19:0;;;;;;:11;:19;;;;;;;;:29;;;;;;;;:31;;;;;;49444:16;:26;;;;;;:42;;49475:10;49444:42;:30;:42;:::i;:::-;49415:26;;;;:16;:26;;;;;:71;49608:22;;;:34;;:50;;49647:10;;-1:-1:-1;;49631:10:0;;;49608:34;;;;;;;;;;;;;;:38;;:50;;;;:::i;:::-;49554:8;:22;;49586:1;49577:6;:10;49554:34;;;;;;;;;;;;;;;;;:104;49732:19;;:35;;49756:10;49732:35;:23;:35;:::i;:::-;49710:57;;49237:946;;;49808:6;49789:15;:25;49785:398;;49945:59;49993:10;49945:8;:22;;49986:1;49968:15;:19;49945:43;;;;;;;;;;;;;;;;:47;;:59;;;;:::i;:::-;49882:8;:22;;49923:1;49905:15;:19;49882:43;;;;;;;;;;;;;;;:122;;;;50121:50;50160:10;50121:8;:22;;50153:1;50144:6;:10;50121:34;;;;;;;:50;50067:8;:22;;50099:1;50090:6;:10;50067:34;;;;;;;;;;;;;;;;;:104;49785:398;-1:-1:-1;;;;;50195:25:0;;;;;;:17;:25;;;;;;;;:37;;;;;;;;;:46;;;50259:43;;;;;;;50221:10;;50273:8;;50195:25;;50259:43;;;;;;;;;48627:1683;;;;;;;;;;:::o;54459:277::-;54595:7;54620:16;54639:23;:21;:23::i;:::-;54620:42;;54680:48;54711:6;54719:8;54680:30;:48::i;6175:::-;;;;:::o;60013:270::-;60111:19;;60191:16;-1:-1:-1;;;60205:1:0;60191:16;:13;:16;:::i;:::-;60183:25;;;-1:-1:-1;60258:16:0;-1:-1:-1;;;60272:1:0;60258:16;:13;:16;:::i;:::-;60234:19;:4;-1:-1:-1;;;60234:19:0;:8;:19;:::i;:::-;60233:42;60219:56;;60013:270;;;:::o;58764:1197::-;58854:17;58886:19;58920;58954:13;58982:23;59041;:21;:23::i;:::-;59033:31;;59184:68;59250:1;59184:61;59213:31;59223:20;;59213:5;:9;;:31;;;;:::i;59184:68::-;59277:13;:25;59327;;59277;;-1:-1:-1;59327:25:0;-1:-1:-1;59166:86:0;-1:-1:-1;59369:9:0;;59365:527;;59395:18;59416:12;59395:18;59429:12;:5;59439:1;59429:12;:9;:12;:::i;:::-;59416:26;;;;;;;;;;;;59395:47;;59461:10;59475:1;59461:15;59457:424;;59497:21;59537:15;59598:44;59631:10;59598:32;:44::i;:::-;59571:71;;-1:-1:-1;59571:71:0;-1:-1:-1;59665:17:0;;59661:205;;59811:35;59838:7;59811:26;:35::i;:::-;59782:64;-1:-1:-1;59782:64:0;-1:-1:-1;59661:205:0;59457:424;;;59365:527;;59916:37;59941:11;59916:20;32102:5;59924:11;59916:20;:7;:20;:::i;:37::-;59904:49;;58764:1197;;;;;:::o;52348:987::-;52460:25;52838:24;;;:12;:24;;;;;;;;;52888:21;;;52937:23;;;;52986:21;;;;;53035:23;;;;53096:20;;;:45;53167:33;;;;53226;;;;53277:13;;;53270:20;;;;52888:21;53270:20;;;;;;;;-1:-1:-1;;53270:20:0;;;;;;;;;;;;;;;;;;;;;;;;52888:21;;;;;52937:23;;52986:21;;53035:23;;53096:45;;53167:33;53226;;52726:17;;;;52838:24;;53277:13;;53270:20;;;53277:13;53270:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53311:8;:16;;53301:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52348:987;;;;;;;;;;;;:::o;42246:1700::-;41905:10;-1:-1:-1;;;;;41927:7:0;41905:30;;41897:64;;;;;-1:-1:-1;;;41897:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;42431:17;42427:56:::1;;42465:7;;42427:56;42493:16;42512:23;:21;:23::i;:::-;-1:-1:-1::0;;;;;42567:19:0;::::1;42548:16;42567:19:::0;;;:11:::1;:19;::::0;;;;;;;:29;;;;;;;;;42493:42;;-1:-1:-1;42689:13:0;42685:52:::1;;42719:7;;;;42685:52;42828:58;42859:26;:8:::0;42872:12;42859:26:::1;:12;:26;:::i;:::-;42828;::::0;;;:16:::1;:26;::::0;;;;;;:58:::1;:30;:58;:::i;:::-;42799:26;::::0;;;:16:::1;:26;::::0;;;;;;;:87;;;;42996:14:::1;:24:::0;;;;;;42965:55;;;;;;::::1;::::0;;;;;;;;;;:28:::1;::::0;:55;;::::1;42996:24:::0;42965:55;;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;42965:55:0;;-1:-1:-1;43038:9:0::1;::::0;-1:-1:-1;;;;43033:906:0::1;43057:11;:18;43053:1;:22;43033:906;;;43097:18;43118:11;43130:1;43118:14;;;;;;;;;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;;;43171:25:0;::::1;43149:19;43171:25:::0;;;:17:::1;:25:::0;;;;;;:37;;;;;;;;;;;43118:14;;-1:-1:-1;43227:16:0;43223:65:::1;;43264:8;;;;43223:65;43332:25;43360:24:::0;;;:12:::1;:24;::::0;;;;43403:21:::1;::::0;::::1;::::0;43428:3:::1;-1:-1:-1::0;43399:529:0::1;;43685:25;::::0;::::1;:36:::0;:54:::1;::::0;43726:12;43685:54:::1;:40;:54;:::i;:::-;43625:25;::::0;::::1;:114:::0;43838:39;;;:56;;:74:::1;::::0;43899:12;;-1:-1:-1;;43878:15:0;;;43838:56;::::1;;;;:74;43758:39:::0;;;:56;;-1:-1:-1;;43798:15:0;;;43758:56;::::1;;;;;;::::0;;;::::1;::::0;;;::::1;:154:::0;43399:529:::1;43033:906;;;;43077:3;;43033:906;;;;41972:1;;;;42246:1700:::0;;:::o;55068:2445::-;55178:16;55255:24;;;:12;:24;;;;;55295:23;;55178:16;;55255:24;55295:23;;;;;55290:70;;-1:-1:-1;55343:1:0;;-1:-1:-1;55343:1:0;;-1:-1:-1;55335:13:0;;55290:70;55480:3;55456:8;:21;;;:27;55452:73;;;-1:-1:-1;55508:1:0;;-1:-1:-1;55508:1:0;;-1:-1:-1;55500:13:0;;55452:73;55559:23;;;;55666:16;55662:62;;-1:-1:-1;55707:1:0;;-1:-1:-1;55707:1:0;;-1:-1:-1;55699:13:0;;-1:-1:-1;55699:13:0;55662:62;55757:25;;;:36;55834:39;;;55804:69;;;;;;;;;;;;;;;;;;;:27;;:69;;55834:39;;55804:69;;55834:39;55804:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;55804:69:0;;-1:-1:-1;55929:21:0;;-1:-1:-1;55929:21:0;;-1:-1:-1;55929:21:0;;-1:-1:-1;;56001:307:0;56025:10;:17;56021:1;:21;56001:307;;;56084:13;56068:10;56079:1;56068:13;;;;;;;;;;;;;;:29;56064:233;;;56134:1;56138;56134:5;56118:21;;56174:10;56185:1;56174:13;;;;;;;;;;;;;;56158:29;;56064:233;;;56230:13;56213:10;56224:1;56213:13;;;;;;;;;;;;;;:30;56209:88;;;56280:1;56264:17;;56209:88;56044:3;;56001:307;;;-1:-1:-1;56377:18:0;56373:64;;-1:-1:-1;56420:1:0;;-1:-1:-1;56420:1:0;;-1:-1:-1;56412:13:0;;-1:-1:-1;;;;;56412:13:0;56373:64;56449:30;;:::i;:::-;-1:-1:-1;56449:53:0;;;;;;;;56482:20;;;56449:53;;;;;;;;;;;;;;;;;;;;;;56623:23;;;;-1:-1:-1;;56593:54:0;;:25;:10;31809:6;56593:25;:14;:25;:::i;:54::-;56567:80;;56792:15;56753:11;:36;;;:54;56749:100;;;-1:-1:-1;56832:1:0;;-1:-1:-1;56832:1:0;;-1:-1:-1;56824:13:0;;-1:-1:-1;;;;;;;56824:13:0;56749:100;56945:9;56957:60;31809:6;56957:45;56986:15;56957:11;:24;;;:28;;:45;;;;:::i;:60::-;56945:72;;57037:11;:24;;;57032:1;:29;57028:392;;57166:24;;;;57154:9;;57166:31;;57195:1;57166:31;:28;:31;:::i;:::-;57154:43;-1:-1:-1;57342:17:0;57154:43;57348:10;57342:17;:5;:17;:::i;:::-;57311:28;:13;31809:6;57311:28;:17;:28;:::i;:::-;:48;57307:102;;;-1:-1:-1;57388:1:0;;-1:-1:-1;57388:1:0;;-1:-1:-1;57380:13:0;;-1:-1:-1;;;;;;;;;57380:13:0;57307:102;57028:392;;57443:13;57432:24;;57475:8;:16;;57503:1;57492:8;:12;57475:30;;;;;;;;;;;;;;;;57467:38;;55068:2445;;;;;;;;;;;;;:::o;6124:44::-;;;;:::o;1369:136::-;1427:7;1454:43;1458:1;1461;1454:43;;;;;;;;;;;;;;;;;:3;:43::i;3182:132::-;3240:7;3267:39;3271:1;3274;3267:39;;;;;;;;;;;;;;;;;:3;:39::i;913:181::-;971:7;1003:5;;;1027:6;;;;1019:46;;;;;-1:-1:-1;;;1019:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;2243:471;2301:7;2546:6;2542:47;;-1:-1:-1;2576:1:0;2569:8;;2542:47;2613:5;;;2617:1;2613;:5;:1;2637:5;;;;;:10;2629:56;;;;-1:-1:-1;;;2629:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61483:3767;61864:3;61846:14;:21;;61838:67;;;;-1:-1:-1;;;61838:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62128:28;;62109:48;;:14;;:48;:18;:48;:::i;:::-;62086:19;:12;62103:1;62086:19;:16;:19;:::i;:::-;:71;;62064:161;;;;-1:-1:-1;;;62064:161:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62238:18;62259:30;62274:14;62259;:30::i;:::-;62238:51;;62300:16;62319:28;62334:12;62319:14;:28::i;:::-;62382:26;;;;:14;:26;;;;;:33;62300:47;;-1:-1:-1;37713:2:0;-1:-1:-1;62360:139:0;;;;-1:-1:-1;;;62360:139:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62606:8;62592:10;:22;62584:77;;;;-1:-1:-1;;;62584:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62674:20;62697:23;:21;:23::i;:::-;62674:46;-1:-1:-1;62767:19:0;62674:46;62784:1;62767:19;:16;:19;:::i;:::-;62753:10;:33;;62731:130;;;;-1:-1:-1;;;62731:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62932:14;;62992:1;62979:14;;:52;;;;;37819:1;62997:10;:34;;62979:52;62957:143;;;;-1:-1:-1;;;62957:143:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63191:20;63175:12;:36;;;;;;;;;63171:1708;;;63280:9;63275:151;63299:7;:14;63295:1;:18;63275:151;;;63360:1;63347:7;63355:1;63347:10;;;;;;;;;;;;;;:14;63339:71;;;;-1:-1:-1;;;63339:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63315:3;;63275:151;;;;63171:1708;;;63463:23;63447:12;:39;;;;;;;;;63443:1436;;;63529:31;;;;:19;:31;;;;;;:36;63503:161;;;;-1:-1:-1;;;63503:161:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63748:9;63743:397;63767:7;:14;63763:1;:18;63743:397;;;64023:1;32102:5;64017:7;64004;64012:1;64004:10;;;;;;;;;;;;;;:20;63974:150;;;;-1:-1:-1;;;63974:150:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63783:3;;63743:397;;63443:1436;64198:24;;;;:12;:24;;;;;;:29;64172:146;;;;-1:-1:-1;;;64172:146:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64426:9;64421:447;64445:7;:14;64441:1;:18;64421:447;;;64565:19;64586;64630:38;64657:7;64665:1;64657:10;;;;;;;;;;;;;;64630:26;:38::i;:::-;64564:104;;-1:-1:-1;64564:104:0;-1:-1:-1;32102:5:0;64717:28;64564:104;;64717:28;:15;:28;:::i;:::-;:35;;64687:165;;;;-1:-1:-1;;;64687:165:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;64461:3:0;;64421:447;;;;63443:1436;31809:6;64959:24;:37;;64951:88;;;;-1:-1:-1;;;64951:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;65113:12:0;:24;65105:62;;;;;-1:-1:-1;;;65105:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;65188:12:0;:24;65180:62;;;;;-1:-1:-1;;;65180:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61483:3767;;;;;;;;;;;:::o;65454:854::-;-1:-1:-1;;;;;65619:19:0;;65575:7;65619:19;;;:11;:19;;;;;;;;:26;;;;;;;;;65693:13;65689:54;;65730:1;65723:8;;;;;65689:54;65756:13;65771:22;65795;65834:7;-1:-1:-1;;;;;65834:24:0;;65859:6;65867:5;65834:39;;;;;;;;;;;;;-1:-1:-1;;;;;65834:39:0;-1:-1:-1;;;;;65834:39:0;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;65834:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65834:39:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;65834:39:0;;;;;;;;;;;;;-1:-1:-1;65834:39:0;;-1:-1:-1;65834:39:0;-1:-1:-1;65886:18:0;-1:-1:-1;;;;;65907:24:0;;;;;;;:69;;65962:14;65907:69;;;65934:25;:5;65944:14;65934:25;:9;:25;:::i;:::-;65886:90;-1:-1:-1;65991:15:0;65987:56;;66030:1;66023:8;;;;;;;;;65987:56;66055:14;66072:24;:8;66085:10;66072:24;:12;:24;:::i;:::-;66107:16;66126:23;;;:16;:23;;;;;;66055:41;;-1:-1:-1;66226:18:0;;;;66219:26;;;;66265:35;66291:8;66265:21;:6;31809;66265:21;:10;:21;:::i;:35::-;66258:42;65454:854;-1:-1:-1;;;;;;;;;;65454:854:0:o;60788:579::-;60877:25;60905:24;;;:12;:24;;;;;60948:23;;;;;;;60940:64;;;;;-1:-1:-1;;;60940:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61052:3;61025:8;:23;;;:30;;61017:69;;;;;-1:-1:-1;;;61017:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61130:3;61105:8;:21;;;:28;;61097:69;;;;;-1:-1:-1;;;61097:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61251:1;61242:6;:10;61234:40;;;;;-1:-1:-1;;;61234:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61303:16;;;:23;61293:33;;;61285:74;;;;;-1:-1:-1;;;61285:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;60788:579;;;:::o;1800:192::-;1886:7;1922:12;1914:6;;;;1906:29;;;;-1:-1:-1;;;1906:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;1906:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1958:5:0;;;1800:192::o;3802:345::-;3888:7;3990:12;3983:5;3975:28;;;;-1:-1:-1;;;3975:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;3975:28:0;;4014:9;4030:1;4026;:5;;;;;;;3802:345;-1:-1:-1;;;;;3802:345:0:o;37530:28781::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;37530:28781:0;;;-1:-1:-1;37530:28781:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Swarm Source
ipfs://e226a6302b84b358849f5b5e0f541d9614dcdad0cedb6d983293d343b1243995
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.