More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x61018060 | 6912999 | 81 days ago | IN | 0 ETH | 0.00100802 |
Loading...
Loading
Contract Name:
DAO
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 10000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "openzeppelin-contracts/contracts/security/ReentrancyGuard.sol"; import "../rewards/interfaces/IRewardsEmitter.sol"; import "../rewards/interfaces/IRewardsConfig.sol"; import "../interfaces/IExchangeConfig.sol"; import "../staking/interfaces/IStaking.sol"; import "../interfaces/IAccessManager.sol"; import "./interfaces/ICalledContract.sol"; import "./interfaces/IProposals.sol"; import "./interfaces/IDAO.sol"; import "../pools/PoolUtils.sol"; import "./Parameters.sol"; import "../Upkeep.sol"; // Allows users to propose and vote on various governance actions such as changing parameters, whitelisting/unwhitelisting tokens, sending tokens, calling other contracts, and updating the website. // It handles proposing ballots, tracking votes, enforcing voting requirements, and executing approved proposals. contract DAO is IDAO, Parameters, ReentrancyGuard { event ParameterBallotFinalized(uint256 indexed ballotID, Vote winningVote); event SetAccessManager(address indexed contractAddress); event SetWebsiteURL(string newURL); event WhitelistToken(IERC20 indexed token); event UnwhitelistToken(IERC20 indexed token); event GeoExclusionUpdated(string country, bool excluded, uint256 geoVersion); event TokensWithdrawn(address indexed upkeepContract, IERC20 indexed token, uint256 withdrawnAmount); event ZeroSent(address indexed to, uint256 amount); event ContractCalled(address indexed contractAddress, uint256 indexed intArg); event TeamRewardsTransferred(uint256 teamAmount); using SafeERC20 for IZero; using SafeERC20 for IERC20; uint256 constant SEND_ZERO_COOLDOWN = 1 weeks; IPools immutable public pools; IProposals immutable public proposals; IExchangeConfig immutable public exchangeConfig; IPoolsConfig immutable public poolsConfig; IStakingConfig immutable public stakingConfig; IRewardsConfig immutable public rewardsConfig; IDAOConfig immutable public daoConfig; IRewardsEmitter immutable public liquidityRewardsEmitter; // The default IPFS URL for the website content (can be changed with a setWebsiteURL proposal) string public websiteURL; // Countries that have been excluded from access to the DEX (used by AccessManager.sol) // Keys as ISO 3166 Alpha-2 Codes mapping(string=>bool) public excludedCountries; // The timestamp that ZERO tokens were last sent from the DAO uint256 public nextValidTimestampSendZERO; constructor( IPools _pools, IProposals _proposals, IExchangeConfig _exchangeConfig, IPoolsConfig _poolsConfig, IStakingConfig _stakingConfig, IRewardsConfig _rewardsConfig, IDAOConfig _daoConfig, IRewardsEmitter _liquidityRewardsEmitter ) { pools = _pools; proposals = _proposals; exchangeConfig = _exchangeConfig; poolsConfig = _poolsConfig; stakingConfig = _stakingConfig; rewardsConfig = _rewardsConfig; daoConfig = _daoConfig; liquidityRewardsEmitter = _liquidityRewardsEmitter; // Excluded by default: United States, Canada, United Kingdom, China, India, Pakistan, Russia, Afghanistan, Cuba, Iran, North Korea, Syria, Venezuela // Note that the DAO can remove any of these exclusions - or open up access completely to the exchange as it sees fit. excludedCountries["US"] = true; excludedCountries["CA"] = true; excludedCountries["GB"] = true; excludedCountries["CN"] = true; excludedCountries["IN"] = true; excludedCountries["PK"] = true; excludedCountries["RU"] = true; excludedCountries["AF"] = true; excludedCountries["CU"] = true; excludedCountries["IR"] = true; excludedCountries["KP"] = true; excludedCountries["SY"] = true; excludedCountries["VE"] = true; } // Finalize the vote for a parameter ballot (increase, decrease or no_change) for a given parameter function _finalizeParameterBallot( uint256 ballotID ) internal { Ballot memory ballot = proposals.ballotForID(ballotID); Vote winningVote = proposals.winningParameterVote(ballotID); if ( winningVote == Vote.INCREASE ) _executeParameterChange( ParameterTypes(ballot.number1), true, poolsConfig, stakingConfig, rewardsConfig, daoConfig ); else if ( winningVote == Vote.DECREASE ) _executeParameterChange( ParameterTypes(ballot.number1), false, poolsConfig, stakingConfig, rewardsConfig, daoConfig ); emit ParameterBallotFinalized(ballotID, winningVote); } function _executeSetAccessManager( Ballot memory ballot ) internal { exchangeConfig.setAccessManager( IAccessManager(ballot.address1) ); emit SetAccessManager(ballot.address1); } function _executeSetWebsiteURL( Ballot memory ballot ) internal { websiteURL = ballot.string1; emit SetWebsiteURL(ballot.string1); } function _executeApproval( Ballot memory ballot ) internal { if ( ballot.ballotType == BallotType.UNWHITELIST_TOKEN ) { // All tokens are paired with both WETH and ZERO so unwhitelist those pools poolsConfig.unwhitelistPool(IERC20(ballot.address1), exchangeConfig.weth() ); poolsConfig.unwhitelistPool(IERC20(ballot.address1), exchangeConfig.zero() ); // Make sure that the cached arbitrage indicies in PoolStats are updated pools.updateArbitrageIndicies(); emit UnwhitelistToken(IERC20(ballot.address1)); } else if ( ballot.ballotType == BallotType.SEND_ZERO ) { // Make sure the contract has the ZERO token balance before trying to send it. // This should not happen but is here just in case - to prevent approved proposals from reverting on finalization. if ( exchangeConfig.zero().balanceOf(address(this)) >= ballot.number1 ) { IERC20(exchangeConfig.zero()).safeTransfer( ballot.address1, ballot.number1 ); nextValidTimestampSendZERO = block.timestamp + SEND_ZERO_COOLDOWN; emit ZeroSent(ballot.address1, ballot.number1); } } else if ( ballot.ballotType == BallotType.CALL_CONTRACT ) { try ICalledContract(ballot.address1).callFromDAO(ballot.number1) { } catch (bytes memory) { } emit ContractCalled(ballot.address1, ballot.number1); } else if ( ballot.ballotType == BallotType.INCLUDE_COUNTRY ) { excludedCountries[ ballot.string1 ] = false; emit GeoExclusionUpdated(ballot.string1, false, exchangeConfig.accessManager().geoVersion()); } else if ( ballot.ballotType == BallotType.EXCLUDE_COUNTRY ) { excludedCountries[ ballot.string1 ] = true; // If the AccessManager doesn't implement excludedCountriesUpdated, this will revert and countries will not be able to be excluded until the AccessManager is working properly. exchangeConfig.accessManager().excludedCountriesUpdated(); emit GeoExclusionUpdated(ballot.string1, true, exchangeConfig.accessManager().geoVersion()); } // Once an initial setAccessManager proposal passes, it automatically starts a second confirmation ballot (to prevent last minute approvals) else if ( ballot.ballotType == BallotType.SET_ACCESS_MANAGER ) proposals.createConfirmationProposal( string.concat("confirm_", ballot.ballotName), BallotType.CONFIRM_SET_ACCESS_MANAGER, ballot.address1, "", ballot.description ); // Once an initial setWebsiteURL proposal passes, it automatically starts a second confirmation ballot (to prevent last minute approvals) else if ( ballot.ballotType == BallotType.SET_WEBSITE_URL ) proposals.createConfirmationProposal( string.concat("confirm_", ballot.ballotName), BallotType.CONFIRM_SET_WEBSITE_URL, address(0), ballot.string1, ballot.description ); else if ( ballot.ballotType == BallotType.CONFIRM_SET_ACCESS_MANAGER ) _executeSetAccessManager( ballot ); else if ( ballot.ballotType == BallotType.CONFIRM_SET_WEBSITE_URL ) _executeSetWebsiteURL( ballot ); } // Finalize the vote for an approval ballot (yes or no) for a given proposal function _finalizeApprovalBallot( uint256 ballotID ) internal { if ( proposals.ballotIsApproved(ballotID ) ) { Ballot memory ballot = proposals.ballotForID(ballotID); _executeApproval( ballot ); } } // Finalize and execute a token whitelisting ballot. // If NO > YES than the proposal is removed immediately (quorum would already have been determined - in canFinalizeBallot as called from finalizeBallot). function _finalizeTokenWhitelisting( uint256 ballotID ) internal { if ( proposals.ballotIsApproved(ballotID ) ) { // The ballot is approved. Any reversions below will allow the ballot to be attemped to be finalized later - as the ballot won't be finalized on reversion. Ballot memory ballot = proposals.ballotForID(ballotID); uint256 bootstrappingRewards = daoConfig.bootstrappingRewards(); // Make sure that the DAO contract holds the required amount of ZERO tokens for bootstrappingRewards. // Twice the bootstrapping rewards are needed (for both the token/WETH and token/ZERO pools) uint256 zeroBalance = exchangeConfig.zero().balanceOf( address(this) ); require( zeroBalance >= bootstrappingRewards * 2, "Whitelisting is not currently possible due to insufficient bootstrapping rewards" ); // All tokens are paired with both WETH and ZERO, so whitelist both pairings poolsConfig.whitelistPool( IERC20(ballot.address1), exchangeConfig.weth() ); poolsConfig.whitelistPool( IERC20(ballot.address1), exchangeConfig.zero() ); // Make sure that the cached arbitrage indicies in PoolStats are updated pools.updateArbitrageIndicies(); bytes32 pool1 = PoolUtils._poolID( IERC20(ballot.address1), exchangeConfig.weth() ); bytes32 pool2 = PoolUtils._poolID( IERC20(ballot.address1), exchangeConfig.zero() ); // Send the initial bootstrappingRewards to promote initial liquidity on these two newly whitelisted pools AddedReward[] memory addedRewards = new AddedReward[](2); addedRewards[0] = AddedReward( pool1, bootstrappingRewards ); addedRewards[1] = AddedReward( pool2, bootstrappingRewards ); exchangeConfig.zero().approve( address(liquidityRewardsEmitter), bootstrappingRewards * 2 ); liquidityRewardsEmitter.addZERORewards( addedRewards ); emit WhitelistToken(IERC20(ballot.address1)); } } // Finalize the vote on a specific ballot. // Can be called by anyone, but only actually finalizes the ballot if it can be finalized. function finalizeBallot( uint256 ballotID ) external nonReentrant { // Checks that ballot is live, and minimumEndTime and quorum have both been reached require( proposals.canFinalizeBallot(ballotID), "The ballot is not yet able to be finalized" ); Ballot memory ballot = proposals.ballotForID(ballotID); if ( ballot.ballotType == BallotType.PARAMETER ) _finalizeParameterBallot(ballotID); else if ( ballot.ballotType == BallotType.WHITELIST_TOKEN ) _finalizeTokenWhitelisting(ballotID); else { // ZERO tokens can only be sent from the DAO once a week to combat DAO reserve draining attacks. if ( ballot.ballotType == BallotType.SEND_ZERO ) if ( block.timestamp < nextValidTimestampSendZERO ) return; // return and allow the Send ZERO to be executed later _finalizeApprovalBallot(ballotID); } // Mark the ballot as no longer votable and remove it from the list of open ballots proposals.markBallotAsFinalized(ballotID); } // Remove a ballot from voting which has existed for longer than the DAOConfig.ballotMaximumDuration function manuallyRemoveBallot( uint256 ballotID ) external nonReentrant { Ballot memory ballot = proposals.ballotForID(ballotID); require( block.timestamp >= ballot.ballotMaximumEndTime, "The ballot is not yet able to be manually removed" ); // Mark the ballot as no longer votable and remove it from the list of open ballots proposals.markBallotAsFinalized(ballotID); } // Withdraw deposited tokens in the Pools contract and send them to the caller (the Upkeep contract). function withdrawFromDAO( IERC20 token ) external returns (uint256 withdrawnAmount) { require( msg.sender == address(exchangeConfig.upkeep()), "DAO.withdrawFromDAO is only callable from the Upkeep contract" ); withdrawnAmount = pools.depositedUserBalance(address(this), token ); if ( withdrawnAmount <= ( PoolUtils.DUST + 1 ) ) return 0; // Don't withdraw all profits to avoid the increased gas cost of overwriting zero withdrawnAmount -= 1; pools.withdraw( token, withdrawnAmount ); token.safeTransfer( msg.sender, withdrawnAmount ); emit TokensWithdrawn(msg.sender, token, withdrawnAmount); } // === VIEWS === function countryIsExcluded( string calldata country ) external view returns (bool) { return excludedCountries[country]; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "../../staking/interfaces/IStakingRewards.sol"; interface IRewardsEmitter { function addZERORewards( AddedReward[] calldata addedRewards ) external; function performUpkeep( uint256 timeSinceLastUpkeep ) external; // Views function pendingRewardsForPools( bytes32[] calldata pools ) external view returns (uint256[] calldata); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IRewardsConfig { function changeRewardsEmitterDailyPercent(bool increase) external; // onlyOwner function changeEmissionsWeeklyPercent(bool increase) external; // onlyOwner function changeStakingRewardsPercent(bool increase) external; // onlyOwner // Views function emissionsWeeklyPercentTimes1000() external view returns (uint256); function rewardsEmitterDailyPercentTimes1000() external view returns (uint256); function stakingRewardsPercent() external view returns (uint256); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "openzeppelin-contracts/contracts/finance/VestingWallet.sol"; import "../staking/interfaces/ILiquidity.sol"; import "../launch/interfaces/IInitialDistribution.sol"; import "../rewards/interfaces/IRewardsEmitter.sol"; import "../rewards/interfaces/IZeroRewards.sol"; import "../rewards/interfaces/IEmissions.sol"; import "../interfaces/IAccessManager.sol"; import "../launch/interfaces/IAirdrop.sol"; import "../dao/interfaces/IDAO.sol"; import "../interfaces/IZero.sol"; import "./IUpkeep.sol"; interface IExchangeConfig { function setContracts( IDAO _dao, IUpkeep _upkeep, IInitialDistribution _initialDistribution, VestingWallet _teamVestingWallet, VestingWallet _daoVestingWallet ) external; // onlyOwner function setAccessManager( IAccessManager _accessManager ) external; // onlyOwner // Views function zero() external view returns (IZero); function wbtc() external view returns (IERC20); function weth() external view returns (IERC20); function usdc() external view returns (IERC20); function usdt() external view returns (IERC20); function daoVestingWallet() external view returns (VestingWallet); function teamVestingWallet() external view returns (VestingWallet); function initialDistribution() external view returns (IInitialDistribution); function accessManager() external view returns (IAccessManager); function dao() external view returns (IDAO); function upkeep() external view returns (IUpkeep); function teamWallet() external view returns (address); function walletHasAccess( address wallet ) external view returns (bool); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "./IStakingRewards.sol"; // Enum representing the possible states of an unstake request: // NONE: The default state, indicating that no unstake request has been made. // PENDING: The state indicating that an unstake request has been made, but has not yet completed. // CANCELLED: The state indicating that a pending unstake request has been cancelled by the user. // CLAIMED: The state indicating that a pending unstake request has been completed and the user can claim their ZERO tokens. enum UnstakeState { NONE, PENDING, CANCELLED, CLAIMED } struct Unstake { UnstakeState status; // see above address wallet; // the wallet of the user performing the unstake uint256 unstakedVeZERO; // the amount of veZERO that was unstaked uint256 claimableZERO; // claimable ZERO tokens at completion time uint256 completionTime; // the timestamp when the unstake completes uint256 unstakeID; // the unstake ID } interface IStaking is IStakingRewards { function stakeZERO( uint256 amountToStake ) external; function unstake( uint256 amountUnstaked, uint256 numWeeks ) external returns (uint256 unstakeID); function cancelUnstake( uint256 unstakeID ) external; function recoverZERO( uint256 unstakeID ) external; // Views function userVeZERO( address wallet ) external view returns (uint256); function unstakesForUser( address wallet, uint256 start, uint256 end ) external view returns (Unstake[] calldata); function unstakesForUser( address wallet ) external view returns (Unstake[] calldata); function userUnstakeIDs( address user ) external view returns (uint256[] calldata); function unstakeByID(uint256 id) external view returns (Unstake calldata); function calculateUnstake( uint256 unstakedVeZERO, uint256 numWeeks ) external view returns (uint256); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IAccessManager { function excludedCountriesUpdated() external; function grantAccess(bytes calldata signature) external; // Views function geoVersion() external view returns (uint256); function walletHasAccess(address wallet) external view returns (bool); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface ICalledContract { function callFromDAO(uint256) external; }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; enum Vote { INCREASE, DECREASE, NO_CHANGE, YES, NO } enum BallotType { PARAMETER, WHITELIST_TOKEN, UNWHITELIST_TOKEN, SEND_ZERO, CALL_CONTRACT, INCLUDE_COUNTRY, EXCLUDE_COUNTRY, SET_ACCESS_MANAGER, SET_WEBSITE_URL, CONFIRM_SET_ACCESS_MANAGER, CONFIRM_SET_WEBSITE_URL } struct UserVote { Vote vote; uint256 votingPower; // Voting power at the time the vote was cast } struct Ballot { uint256 ballotID; bool ballotIsLive; BallotType ballotType; string ballotName; address address1; uint256 number1; string string1; string description; // The earliest timestamp at which a ballot can end. Can be open longer if the quorum has not yet been reached for instance. uint256 ballotMinimumEndTime; // The time at which any user can end the ballot - even if it hasn't been successfully finalized. uint256 ballotMaximumEndTime; // The requiredQuorum for the ballot uint256 requiredQuorum; } interface IProposals { function createConfirmationProposal( string calldata ballotName, BallotType ballotType, address address1, string calldata string1, string calldata description ) external returns (uint256 ballotID); function markBallotAsFinalized( uint256 ballotID ) external; function proposeParameterBallot( uint256 parameterType, string calldata description ) external returns (uint256 ballotID); function proposeTokenWhitelisting( IERC20 token, string calldata tokenIconURL, string calldata description ) external returns (uint256 ballotID); function proposeTokenUnwhitelisting( IERC20 token, string calldata tokenIconURL, string calldata description ) external returns (uint256 ballotID); function proposeSendZERO( address wallet, uint256 amount, string calldata description ) external returns (uint256 ballotID); function proposeCallContract( address contractAddress, uint256 number, string calldata description ) external returns (uint256 ballotID); function proposeCountryInclusion( string calldata country, string calldata description ) external returns (uint256 ballotID); function proposeCountryExclusion( string calldata country, string calldata description ) external returns (uint256 ballotID); function proposeSetAccessManager( address newAddress, string calldata description ) external returns (uint256 ballotID); function proposeWebsiteUpdate( string calldata newWebsiteURL, string calldata description ) external returns (uint256 ballotID); function castVote( uint256 ballotID, Vote vote ) external; // Views function nextBallotID() external view returns (uint256); function openBallotsByName( string calldata name ) external view returns (uint256); function ballotForID( uint256 ballotID ) external view returns (Ballot calldata); function lastUserVoteForBallot( uint256 ballotID, address user ) external view returns (UserVote calldata); function votesCastForBallot( uint256 ballotID, Vote vote ) external view returns (uint256); function requiredQuorumForBallotType( BallotType ballotType ) external view returns (uint256 requiredQuorum); function totalVotesCastForBallot( uint256 ballotID ) external view returns (uint256); function ballotIsApproved( uint256 ballotID ) external view returns (bool); function winningParameterVote( uint256 ballotID ) external view returns (Vote); function canFinalizeBallot( uint256 ballotID ) external view returns (bool); function openBallots() external view returns (uint256[] memory); function openBallotsForTokenWhitelisting() external view returns (uint256[] memory); function userHasActiveProposal( address user ) external view returns (bool); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "../../rewards/interfaces/IZeroRewards.sol"; import "../../pools/interfaces/IPools.sol"; import "../../interfaces/IZero.sol"; interface IDAO { function finalizeBallot( uint256 ballotID ) external; function manuallyRemoveBallot( uint256 ballotID ) external; function withdrawFromDAO( IERC20 token ) external returns (uint256 withdrawnAmount); // Views function pools() external view returns (IPools); function websiteURL() external view returns (string memory); function countryIsExcluded( string calldata country ) external view returns (bool); }
pragma solidity =0.8.22; import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; library PoolUtils { // Token reserves less than dust are treated as if they don't exist at all. // With the 18 decimals that are used for most tokens, DUST has a value of 0.0000000000000001 uint256 constant public DUST = 100; // A special pool that represents staked ZERO tokens that are not associated with any actual liquidity pool. bytes32 constant public STAKED_ZERO = bytes32(0); // Return the unique poolID for the given two tokens. // Tokens are sorted before being hashed to make reversed pairs equivalent. function _poolID( IERC20 tokenA, IERC20 tokenB ) internal pure returns (bytes32 poolID) { // See if the token orders are flipped if ( uint160(address(tokenB)) < uint160(address(tokenA)) ) return keccak256(abi.encodePacked(address(tokenB), address(tokenA))); return keccak256(abi.encodePacked(address(tokenA), address(tokenB))); } // Return the unique poolID and whether or not it is flipped function _poolIDAndFlipped( IERC20 tokenA, IERC20 tokenB ) internal pure returns (bytes32 poolID, bool flipped) { // See if the token orders are flipped if ( uint160(address(tokenB)) < uint160(address(tokenA)) ) return (keccak256(abi.encodePacked(address(tokenB), address(tokenA))), true); return (keccak256(abi.encodePacked(address(tokenA), address(tokenB))), false); } }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "../rewards/interfaces/IRewardsConfig.sol"; import "../staking/interfaces/IStakingConfig.sol"; import "../pools/interfaces/IPoolsConfig.sol"; import "./interfaces/IDAOConfig.sol"; abstract contract Parameters { enum ParameterTypes { // PoolsConfig maximumWhitelistedPools, // StakingConfig minUnstakeWeeks, maxUnstakeWeeks, minUnstakePercent, modificationCooldown, // RewardsConfig rewardsEmitterDailyPercentTimes1000, emissionsWeeklyPercentTimes1000, stakingRewardsPercent, // DAOConfig bootstrappingRewards, percentRewardsBurned, baseBallotQuorumPercentTimes1000, ballotDuration, requiredProposalPercentStakeTimes1000, percentRewardsForReserve, upkeepRewardPercent, ballotMaximumDuration } // If the parameter has an invalid parameterType then the call is a no-op function _executeParameterChange( ParameterTypes parameterType, bool increase, IPoolsConfig poolsConfig, IStakingConfig stakingConfig, IRewardsConfig rewardsConfig, IDAOConfig daoConfig ) internal { // PoolsConfig if ( parameterType == ParameterTypes.maximumWhitelistedPools ) poolsConfig.changeMaximumWhitelistedPools( increase ); // StakingConfig else if ( parameterType == ParameterTypes.minUnstakeWeeks ) stakingConfig.changeMinUnstakeWeeks(increase); else if ( parameterType == ParameterTypes.maxUnstakeWeeks ) stakingConfig.changeMaxUnstakeWeeks(increase); else if ( parameterType == ParameterTypes.minUnstakePercent ) stakingConfig.changeMinUnstakePercent(increase); else if ( parameterType == ParameterTypes.modificationCooldown ) stakingConfig.changeModificationCooldown(increase); // RewardsConfig else if ( parameterType == ParameterTypes.rewardsEmitterDailyPercentTimes1000 ) rewardsConfig.changeRewardsEmitterDailyPercent(increase); else if ( parameterType == ParameterTypes.emissionsWeeklyPercentTimes1000 ) rewardsConfig.changeEmissionsWeeklyPercent(increase); else if ( parameterType == ParameterTypes.stakingRewardsPercent ) rewardsConfig.changeStakingRewardsPercent(increase); // DAOConfig else if ( parameterType == ParameterTypes.bootstrappingRewards ) daoConfig.changeBootstrappingRewards(increase); else if ( parameterType == ParameterTypes.percentRewardsBurned ) daoConfig.changePercentRewardsBurned(increase); else if ( parameterType == ParameterTypes.baseBallotQuorumPercentTimes1000 ) daoConfig.changeBaseBallotQuorumPercent(increase); else if ( parameterType == ParameterTypes.ballotDuration ) daoConfig.changeBallotDuration(increase); else if ( parameterType == ParameterTypes.requiredProposalPercentStakeTimes1000 ) daoConfig.changeRequiredProposalPercentStake(increase); else if ( parameterType == ParameterTypes.percentRewardsForReserve ) daoConfig.changePercentRewardsForReserve(increase); else if ( parameterType == ParameterTypes.upkeepRewardPercent ) daoConfig.changeUpkeepRewardPercent(increase); else if ( parameterType == ParameterTypes.ballotMaximumDuration ) daoConfig.changeBallotMaximumDuration(increase); } }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import "openzeppelin-contracts/contracts/security/ReentrancyGuard.sol"; import "openzeppelin-contracts/contracts/finance/VestingWallet.sol"; import "./rewards/interfaces/IEmissions.sol"; import "./pools/interfaces/IPoolsConfig.sol"; import "./interfaces/IExchangeConfig.sol"; import "./dao/interfaces/IDAOConfig.sol"; import "./pools/interfaces/IPools.sol"; import "./dao/interfaces/IDAO.sol"; // Performs the following upkeep for each call to performUpkeep(): // (Uses a maximum of 1.1 million gas with 100 whitelisted pools according to UpkeepGasUsage.t.sol) // 1. Withdraws deposited ZERO token arbitrage profits from the Pools contract and rewards the caller of performUpkeep() with 5% of the withdrawn ZERO tokens // 2. Burns 10% of the remaining withdrawn ZERO tokens and sends 10% to the DAO's reserve. // 3. Sends the remaining ZERO tokens to ZeroRewards. // 4. Sends ZERO token Emissions to the ZeroRewards contract. // 5. Distributes ZERO tokens from ZeroRewards to the stakingRewardsEmitter and liquidityRewardsEmitter. // 6. Distributes ZERO token rewards from the stakingRewardsEmitter and liquidityRewardsEmitter. // 7. Sends ZERO tokens from the DAO vesting wallet to the DAO (linear distribution over 10 years). // 8. Sends ZERO tokens from the team vesting wallet to the team (linear distribution over 10 years). contract Upkeep is IUpkeep, ReentrancyGuard { using SafeERC20 for IZero; using SafeERC20 for IERC20; event UpkeepError(string description, bytes error); IPools immutable public pools; IExchangeConfig immutable public exchangeConfig; IPoolsConfig immutable public poolsConfig; IDAOConfig immutable public daoConfig; IZeroRewards immutable public zeroRewards; IEmissions immutable public emissions; IDAO immutable public dao; IZero immutable public zero; uint256 public lastUpkeepTimeEmissions; uint256 public lastUpkeepTimeRewardsEmitters; constructor( IPools _pools, IExchangeConfig _exchangeConfig, IPoolsConfig _poolsConfig, IDAOConfig _daoConfig, IZeroRewards _zeroRewards, IEmissions _emissions, IDAO _dao ) { pools = _pools; exchangeConfig = _exchangeConfig; poolsConfig = _poolsConfig; daoConfig = _daoConfig; zeroRewards = _zeroRewards; emissions = _emissions; dao = _dao; // Cached for efficiency zero = _exchangeConfig.zero(); lastUpkeepTimeEmissions = block.timestamp; lastUpkeepTimeRewardsEmitters = block.timestamp; } modifier onlySameContract() { require(msg.sender == address(this), "Only callable from within the same contract"); _; } // Note - while the following steps are public so that they can be wrapped in a try/catch, they are all still only callable from this same contract. // 1. Withdraw deposited ZERO token arbitrage profits from the Pools contract and reward the caller of performUpkeep() with 5% of the withdrawn ZERO tokens function step1(address receiver) public onlySameContract { uint256 withdrawnZERO = dao.withdrawFromDAO(zero); if ( withdrawnZERO == 0 ) return; // Default 5% of the original ZERO token arbitrage profits should be rewarded to the caller of performUpkeep. uint256 rewardAmount = withdrawnZERO * daoConfig.upkeepRewardPercent() / 100; // Send the reward zero.safeTransfer(receiver, rewardAmount); } // 2. Burn 10% of the remaining withdrawn ZERO tokens and send 10% to the DAO's reserve. function step2() public onlySameContract { uint256 zeroBalance = zero.balanceOf( address(this) ); if ( zeroBalance == 0 ) return; // Default 10% of the remaining ZERO token profits should be burned uint256 burnAmount = zeroBalance * daoConfig.percentRewardsBurned() / 100; zero.transfer( address(zero), burnAmount); zero.burnTokensInContract(); // Default 10% of the remaining ZERO token profits should be sent to the DAO's reserve uint256 reserveAmount = zeroBalance * daoConfig.percentRewardsForReserve() / 100; zero.transfer( address(dao), reserveAmount); } // 3. Send the remaining ZERO tokens to ZeroRewards function step3() public onlySameContract { uint256 zeroBalance = zero.balanceOf( address(this) ); if ( zeroBalance == 0 ) return; zero.safeTransfer(address(zeroRewards), zeroBalance); } // 4. Send ZERO token Emissions to the ZeroRewards contract. function step4() public onlySameContract { uint256 timeSinceLastUpkeep = block.timestamp - lastUpkeepTimeEmissions; emissions.performUpkeep(timeSinceLastUpkeep); lastUpkeepTimeEmissions = block.timestamp; } // 5. Distribute ZERO tokens from ZeroRewards to the stakingRewardsEmitter and liquidityRewardsEmitter. function step5() public onlySameContract { uint256[] memory profitsForPools = pools.profitsForWhitelistedPools(); bytes32[] memory poolIDs = poolsConfig.whitelistedPools(); zeroRewards.performUpkeep(poolIDs, profitsForPools ); pools.clearProfitsForPools(); } // 6. Distribute ZERO tokens rewards from the stakingRewardsEmitter and liquidityRewardsEmitter. function step6() public onlySameContract { uint256 timeSinceLastUpkeep = block.timestamp - lastUpkeepTimeRewardsEmitters; zeroRewards.stakingRewardsEmitter().performUpkeep(timeSinceLastUpkeep); zeroRewards.liquidityRewardsEmitter().performUpkeep(timeSinceLastUpkeep); lastUpkeepTimeRewardsEmitters = block.timestamp; } // 7. Send ZERO tokens from the DAO vesting wallet to the DAO (linear distribution over 10 years). function step7() public onlySameContract { exchangeConfig.daoVestingWallet().release(address(zero)); } // 8. Sends ZERO tokens from the team vesting wallet to the team (linear distribution over 10 years). function step8() public onlySameContract { exchangeConfig.teamVestingWallet().release(address(zero)); } // Perform the various steps of performUpkeep as outlined at the top of the contract. // Each step is wrapped in a try/catch to prevent reversions from cascading through the performUpkeep. function performUpkeep() public nonReentrant { require(lastUpkeepTimeEmissions != block.timestamp, "No time since elapsed since last upkeep"); // Perform the multiple steps of performUpkeep() try this.step1(msg.sender) {} catch (bytes memory error) { emit UpkeepError("Step 1", error); } try this.step2() {} catch (bytes memory error) { emit UpkeepError("Step 2", error); } try this.step3() {} catch (bytes memory error) { emit UpkeepError("Step 3", error); } try this.step4() {} catch (bytes memory error) { emit UpkeepError("Step 4", error); } try this.step5() {} catch (bytes memory error) { emit UpkeepError("Step 5", error); } try this.step6() {} catch (bytes memory error) { emit UpkeepError("Step 6", error); } try this.step7() {} catch (bytes memory error) { emit UpkeepError("Step 7", error); } try this.step8() {} catch (bytes memory error) { emit UpkeepError("Step 8", error); } } // ==== VIEWS ==== // Returns the amount of WETH that will currently be rewarded for calling performUpkeep(). // Useful for potential callers to know if calling the function will be profitable in comparison to current gas costs. function currentRewardsForCallingPerformUpkeep() public view returns (uint256) { uint256 depositedZERO = pools.depositedUserBalance(address(dao), zero); // Default 5% of the original ZERO token arbitrage profits should be rewarded to the caller of performUpkeep. return depositedZERO * daoConfig.upkeepRewardPercent() / 100; } }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; struct AddedReward { bytes32 poolID; // The pool to add rewards to uint256 amountToAdd; // The amount of rewards (as ZERO) to add } struct UserShareInfo { uint256 userShare; // A user's share for a given poolID uint256 virtualRewards; // The amount of rewards that were added to maintain proper rewards/share ratio - and will be deducted from a user's pending rewards. uint256 cooldownExpiration; // The timestamp when the user can modify their share } interface IStakingRewards { function claimAllRewards( bytes32[] calldata poolIDs ) external returns (uint256 rewardsAmount); function addZERORewards( AddedReward[] calldata addedRewards ) external; // Views function totalShares(bytes32 poolID) external view returns (uint256); function totalSharesForPools( bytes32[] calldata poolIDs ) external view returns (uint256[] calldata shares); function totalRewardsForPools( bytes32[] calldata poolIDs ) external view returns (uint256[] calldata rewards); function userRewardForPool( address wallet, bytes32 poolID ) external view returns (uint256); function userShareForPool( address wallet, bytes32 poolID ) external view returns (uint256); function userVirtualRewardsForPool( address wallet, bytes32 poolID ) external view returns (uint256); function userRewardsForPools( address wallet, bytes32[] calldata poolIDs ) external view returns (uint256[] calldata rewards); function userShareForPools( address wallet, bytes32[] calldata poolIDs ) external view returns (uint256[] calldata shares); function userCooldowns( address wallet, bytes32[] calldata poolIDs ) external view returns (uint256[] calldata cooldowns); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (finance/VestingWallet.sol) pragma solidity ^0.8.0; import "../token/ERC20/utils/SafeERC20.sol"; import "../utils/Address.sol"; import "../utils/Context.sol"; /** * @title VestingWallet * @dev This contract handles the vesting of Eth and ERC20 tokens for a given beneficiary. Custody of multiple tokens * can be given to this contract, which will release the token to the beneficiary following a given vesting schedule. * The vesting schedule is customizable through the {vestedAmount} function. * * Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning. * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly) * be immediately releasable. */ contract VestingWallet is Context { event EtherReleased(uint256 amount); event ERC20Released(address indexed token, uint256 amount); uint256 private _released; mapping(address => uint256) private _erc20Released; address private immutable _beneficiary; uint64 private immutable _start; uint64 private immutable _duration; /** * @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet. */ constructor(address beneficiaryAddress, uint64 startTimestamp, uint64 durationSeconds) payable { require(beneficiaryAddress != address(0), "VestingWallet: beneficiary is zero address"); _beneficiary = beneficiaryAddress; _start = startTimestamp; _duration = durationSeconds; } /** * @dev The contract should be able to receive Eth. */ receive() external payable virtual {} /** * @dev Getter for the beneficiary address. */ function beneficiary() public view virtual returns (address) { return _beneficiary; } /** * @dev Getter for the start timestamp. */ function start() public view virtual returns (uint256) { return _start; } /** * @dev Getter for the vesting duration. */ function duration() public view virtual returns (uint256) { return _duration; } /** * @dev Amount of eth already released */ function released() public view virtual returns (uint256) { return _released; } /** * @dev Amount of token already released */ function released(address token) public view virtual returns (uint256) { return _erc20Released[token]; } /** * @dev Getter for the amount of releasable eth. */ function releasable() public view virtual returns (uint256) { return vestedAmount(uint64(block.timestamp)) - released(); } /** * @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an * IERC20 contract. */ function releasable(address token) public view virtual returns (uint256) { return vestedAmount(token, uint64(block.timestamp)) - released(token); } /** * @dev Release the native token (ether) that have already vested. * * Emits a {EtherReleased} event. */ function release() public virtual { uint256 amount = releasable(); _released += amount; emit EtherReleased(amount); Address.sendValue(payable(beneficiary()), amount); } /** * @dev Release the tokens that have already vested. * * Emits a {ERC20Released} event. */ function release(address token) public virtual { uint256 amount = releasable(token); _erc20Released[token] += amount; emit ERC20Released(token, amount); SafeERC20.safeTransfer(IERC20(token), beneficiary(), amount); } /** * @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve. */ function vestedAmount(uint64 timestamp) public view virtual returns (uint256) { return _vestingSchedule(address(this).balance + released(), timestamp); } /** * @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve. */ function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) { return _vestingSchedule(IERC20(token).balanceOf(address(this)) + released(token), timestamp); } /** * @dev Virtual implementation of the vesting formula. This returns the amount vested, as a function of time, for * an asset given its total historical allocation. */ function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) { if (timestamp < start()) { return 0; } else if (timestamp > start() + duration()) { return totalAllocation; } else { return (totalAllocation * (timestamp - start())) / duration(); } } }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import "./IStakingRewards.sol"; interface ILiquidity is IStakingRewards { function depositLiquidityAndIncreaseShare( IERC20 tokenA, IERC20 tokenB, uint256 maxAmountA, uint256 maxAmountB, uint256 minAddedAmountA, uint256 minAddedAmountB, uint256 minAddedLiquidity, uint256 deadline, bool useZapping ) external returns (uint256 addedLiquidity); function withdrawLiquidityAndClaim( IERC20 tokenA, IERC20 tokenB, uint256 liquidityToWithdraw, uint256 minReclaimedA, uint256 minReclaimedB, uint256 deadline ) external returns (uint256 reclaimedA, uint256 reclaimedB); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "./IBootstrapBallot.sol"; import "./IAirdrop.sol"; interface IInitialDistribution { function distributionApproved( IAirdrop airdrop1, IAirdrop airdrop2 ) external; // Views function bootstrapBallot() external view returns (IBootstrapBallot); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "./IRewardsEmitter.sol"; interface IZeroRewards { function sendInitialZERORewards( uint256 liquidityBootstrapAmount, bytes32[] calldata poolIDs ) external; function performUpkeep( bytes32[] calldata poolIDs, uint256[] calldata profitsForPools ) external; // Views function stakingRewardsEmitter() external view returns (IRewardsEmitter); function liquidityRewardsEmitter() external view returns (IRewardsEmitter); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IEmissions { function performUpkeep( uint256 timeSinceLastUpkeep ) external; }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IAirdrop { function authorizeWallet( address wallet, uint256 zeroAmount ) external; function allowClaiming() external; function claim() external; // Views function claimedByUser( address wallet) external view returns (uint256); function claimingAllowed() external view returns (bool); function claimingStartTimestamp() external view returns (uint256); function claimableAmount(address wallet) external view returns (uint256); function airdropForUser( address wallet ) external view returns (uint256); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; interface IZero is IERC20 { function burnTokensInContract() external; // Views function totalBurned() external view returns (uint256); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IUpkeep { function performUpkeep() external; // Views function currentRewardsForCallingPerformUpkeep() external view returns (uint256); function lastUpkeepTimeEmissions() external view returns (uint256); function lastUpkeepTimeRewardsEmitters() external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "../../staking/interfaces/ILiquidity.sol"; import "../../dao/interfaces/IDAO.sol"; import "./IPoolStats.sol"; interface IPools is IPoolStats { function startExchangeApproved() external; function setContracts( IDAO _dao, ILiquidity _liquidity ) external; // onlyOwner function addLiquidity( IERC20 tokenA, IERC20 tokenB, uint256 maxAmountA, uint256 maxAmountB, uint256 minAddedAmountA, uint256 minAddedAmountB, uint256 totalLiquidity ) external returns (uint256 addedAmountA, uint256 addedAmountB, uint256 addedLiquidity); function removeLiquidity( IERC20 tokenA, IERC20 tokenB, uint256 liquidityToRemove, uint256 minReclaimedA, uint256 minReclaimedB, uint256 totalLiquidity ) external returns (uint256 reclaimedA, uint256 reclaimedB); function deposit( IERC20 token, uint256 amount ) external; function withdraw( IERC20 token, uint256 amount ) external; function swap( IERC20 swapTokenIn, IERC20 swapTokenOut, uint256 swapAmountIn, uint256 minAmountOut, uint256 deadline ) external returns (uint256 swapAmountOut); function depositSwapWithdraw(IERC20 swapTokenIn, IERC20 swapTokenOut, uint256 swapAmountIn, uint256 minAmountOut, uint256 deadline ) external returns (uint256 swapAmountOut); function depositDoubleSwapWithdraw( IERC20 swapTokenIn, IERC20 swapTokenMiddle, IERC20 swapTokenOut, uint256 swapAmountIn, uint256 minAmountOut, uint256 deadline ) external returns (uint256 swapAmountOut); function depositZapSwapWithdraw(IERC20 swapTokenIn, IERC20 swapTokenOut, uint256 swapAmountIn ) external returns (uint256 swapAmountOut); // Views function exchangeIsLive() external view returns (bool); function getPoolReserves(IERC20 tokenA, IERC20 tokenB) external view returns (uint256 reserveA, uint256 reserveB); function depositedUserBalance(address user, IERC20 token) external view returns (uint256); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IStakingConfig { function changeMinUnstakeWeeks(bool increase) external; // onlyOwner function changeMaxUnstakeWeeks(bool increase) external; // onlyOwner function changeMinUnstakePercent(bool increase) external; // onlyOwner function changeModificationCooldown(bool increase) external; // onlyOwner // Views function minUnstakeWeeks() external view returns (uint256); function maxUnstakeWeeks() external view returns (uint256); function minUnstakePercent() external view returns (uint256); function modificationCooldown() external view returns (uint256); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import "./IPools.sol"; interface IPoolsConfig { function whitelistPool( IERC20 tokenA, IERC20 tokenB ) external; // onlyOwner function unwhitelistPool( IERC20 tokenA, IERC20 tokenB ) external; // onlyOwner function changeMaximumWhitelistedPools(bool increase) external; // onlyOwner // Views function maximumWhitelistedPools() external view returns (uint256); function numberOfWhitelistedPools() external view returns (uint256); function isWhitelisted( bytes32 poolID ) external view returns (bool); function whitelistedPools() external view returns (bytes32[] calldata); function underlyingTokenPair( bytes32 poolID ) external view returns (IERC20 tokenA, IERC20 tokenB); // Returns true if the token has been whitelisted (meaning it has been pooled with either WETH and ZERO) function tokenHasBeenWhitelisted( IERC20 token, IERC20 weth, IERC20 zero ) external view returns (bool); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IDAOConfig { function changeBootstrappingRewards(bool increase) external; // onlyOwner function changePercentRewardsBurned(bool increase) external; // onlyOwner function changeBaseBallotQuorumPercent(bool increase) external; // onlyOwner function changeBallotDuration(bool increase) external; // onlyOwner function changeBallotMaximumDuration(bool increase) external; // onlyOwner function changeRequiredProposalPercentStake(bool increase) external; // onlyOwner function changePercentRewardsForReserve(bool increase) external; // onlyOwner function changeUpkeepRewardPercent(bool increase) external; // onlyOwner // Views function bootstrappingRewards() external view returns (uint256); function percentRewardsBurned() external view returns (uint256); function baseBallotQuorumPercentTimes1000() external view returns (uint256); function ballotMinimumDuration() external view returns (uint256); function ballotMaximumDuration() external view returns (uint256); function requiredProposalPercentStakeTimes1000() external view returns (uint256); function percentRewardsForReserve() external view returns (uint256); function upkeepRewardPercent() external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IBootstrapBallot { function vote( bool voteStartExchangeYes, uint256 zeroAmount, bytes calldata signature ) external; function finalizeBallot() external; function authorizeAirdrop2( uint256 zeroAmount, bytes calldata signature ) external; function finalizeAirdrop2() external; // Views function claimableTimestamp1() external view returns (uint256); function claimableTimestamp2() external view returns (uint256); function hasVoted(address user) external view returns (bool); function ballotFinalized() external view returns (bool); function startExchangeYes() external view returns (uint256); function startExchangeNo() external view returns (uint256); }
// SPDX-License-Identifier: BUSL 1.1 pragma solidity =0.8.22; interface IPoolStats { // These are the indicies (in terms of a poolIDs location in the current whitelistedPoolIDs array) of pools involved in an arbitrage path struct ArbitrageIndicies { uint64 index1; uint64 index2; uint64 index3; } function clearProfitsForPools() external; function updateArbitrageIndicies() external; // Views function profitsForWhitelistedPools() external view returns (uint256[] memory _calculatedProfits); function arbitrageIndicies(bytes32 poolID) external view returns (ArbitrageIndicies memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
{ "remappings": [ "chainlink/=lib/chainlink/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/openzeppelin-contracts/lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "v3-core/=lib/v3-core/contracts/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IPools","name":"_pools","type":"address"},{"internalType":"contract IProposals","name":"_proposals","type":"address"},{"internalType":"contract IExchangeConfig","name":"_exchangeConfig","type":"address"},{"internalType":"contract IPoolsConfig","name":"_poolsConfig","type":"address"},{"internalType":"contract IStakingConfig","name":"_stakingConfig","type":"address"},{"internalType":"contract IRewardsConfig","name":"_rewardsConfig","type":"address"},{"internalType":"contract IDAOConfig","name":"_daoConfig","type":"address"},{"internalType":"contract IRewardsEmitter","name":"_liquidityRewardsEmitter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"intArg","type":"uint256"}],"name":"ContractCalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"country","type":"string"},{"indexed":false,"internalType":"bool","name":"excluded","type":"bool"},{"indexed":false,"internalType":"uint256","name":"geoVersion","type":"uint256"}],"name":"GeoExclusionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"ballotID","type":"uint256"},{"indexed":false,"internalType":"enum Vote","name":"winningVote","type":"uint8"}],"name":"ParameterBallotFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"SetAccessManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newURL","type":"string"}],"name":"SetWebsiteURL","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"teamAmount","type":"uint256"}],"name":"TeamRewardsTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"upkeepContract","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawnAmount","type":"uint256"}],"name":"TokensWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"}],"name":"UnwhitelistToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"}],"name":"WhitelistToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ZeroSent","type":"event"},{"inputs":[{"internalType":"string","name":"country","type":"string"}],"name":"countryIsExcluded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"daoConfig","outputs":[{"internalType":"contract IDAOConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exchangeConfig","outputs":[{"internalType":"contract IExchangeConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"excludedCountries","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ballotID","type":"uint256"}],"name":"finalizeBallot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidityRewardsEmitter","outputs":[{"internalType":"contract IRewardsEmitter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ballotID","type":"uint256"}],"name":"manuallyRemoveBallot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nextValidTimestampSendZERO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pools","outputs":[{"internalType":"contract IPools","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolsConfig","outputs":[{"internalType":"contract IPoolsConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposals","outputs":[{"internalType":"contract IProposals","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsConfig","outputs":[{"internalType":"contract IRewardsConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingConfig","outputs":[{"internalType":"contract IStakingConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"websiteURL","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"withdrawFromDAO","outputs":[{"internalType":"uint256","name":"withdrawnAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101806040523480156200001257600080fd5b5060405162003ec438038062003ec4833981016040819052620000359162000247565b600160008190556001600160a01b0398891660805296881660a05294871660c05292861660e05290851661010052841661012052831661014052909116610160526040805161555360f01b81526002808201819052825160229281900383018120805460ff19908116871790915561434160f01b82528183018390528451918290038401822080548216871790556123a160f11b82528183018390528451918290038401822080548216871790556121a760f11b82528183018390528451918290038401822080548216871790556124a760f11b825281830183905284519182900384018220805482168717905561504b60f01b825281830183905284519182900384018220805482168717905561525560f01b82528183018390528451918290038401822080548216871790556120a360f11b825281830183905284519182900384018220805482168717905561435560f01b82528183018390528451918290038401822080548216871790556124a960f11b82528183018390528451918290038401822080548216871790556104b560f41b825281830183905284519182900384018220805482168717905561535960f01b825281830183905284519182900384018220805482168717905561564560f01b8252818301929092529251928390039091019091208054909116909117905562000308565b6001600160a01b03811681146200024457600080fd5b50565b600080600080600080600080610100898b0312156200026557600080fd5b885162000272816200022e565b60208a015190985062000285816200022e565b60408a015190975062000298816200022e565b60608a0151909650620002ab816200022e565b60808a0151909550620002be816200022e565b60a08a0151909450620002d1816200022e565b60c08a0151909350620002e4816200022e565b60e08a0151909250620002f7816200022e565b809150509295985092959890939650565b60805160a05160c05160e05161010051610120516101405161016051613a15620004af6000396000818161022f015281816117c201526118a40152600081816102e501528181610df701528181610eb9015261107001526000818161026901528181610dd60152610e9801526000818161017d01528181610db50152610e770152600081816101b701528181610d9401528181610e56015281816112bd015281816113eb01528181612306015261243401526000818160ff0152818161033b015281816110f6015281816112f10152818161141f0152818161159601528181611629015281816117320152818161233a01528181612468015281816126340152818161274b015281816129d001528181612b2501528181612c210152612e990152600081816101de01528181610664015281816107a1015281816108d801528181610a0901528181610c3d01528181610cf101528181610f4901528181610ff30152818161197d01528181611a2701528181612c9c0152612d7a0152600081816102900152818161049e015281816105720152818161151901526125620152613a156000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806363eab1801161009757806396ceac341161006657806396ceac3414610264578063c5c51dca1461028b578063d3f22ec1146102b2578063fa05dd00146102e057600080fd5b806363eab18014610200578063779f6350146102155780637af0eb391461022a5780637b3ef6161461025157600080fd5b806336829dfc116100d357806336829dfc146101785780634e4cce731461019f57806352c19b5a146101b257806355ef20e6146101d957600080fd5b80630e2789bb146100fa57806313ea84a71461013e578063304591c414610161575b600080fd5b6101217f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61015161014c366004613158565b610307565b6040519015158152602001610135565b61016a60035481565b604051908152602001610135565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b61016a6101ad3660046131df565b610337565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b61021361020e366004613203565b61062a565b005b61021d610813565b604051610135919061326c565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b61021361025f366004613203565b6108a1565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b6101516102c0366004613331565b805160208183018101805160028252928201919093012091525460ff1681565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b60006002838360405161031b9291906133b1565b9081526040519081900360200190205460ff1690505b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632cf4704a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103bb91906133c1565b6001600160a01b0316336001600160a01b031614610460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f44414f2e776974686472617746726f6d44414f206973206f6e6c792063616c6c60448201527f61626c652066726f6d207468652055706b65657020636f6e747261637400000060648201526084015b60405180910390fd5b6040517f2c6628570000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301527f00000000000000000000000000000000000000000000000000000000000000001690632c66285790604401602060405180830381865afa1580156104e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050991906133de565b905061051760646001613426565b811161052557506000919050565b610530600182613439565b6040517ff3fef3a30000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063f3fef3a390604401600060405180830381600087803b1580156105b857600080fd5b505af11580156105cc573d6000803e3d6000fd5b506105e5925050506001600160a01b0383163383610b13565b6040518181526001600160a01b0383169033907f6337ed398c0e8467698c581374fdce4db14922df487b5a39483079f5f59b60a49060200160405180910390a3919050565b610632610b98565b6040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634507488790602401600060405180830381865afa1580156106b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106db91908101906134c0565b9050806101200151421015610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5468652062616c6c6f74206973206e6f74207965742061626c6520746f20626560448201527f206d616e75616c6c792072656d6f7665640000000000000000000000000000006064820152608401610457565b6040517f568d86d7000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063568d86d790602401600060405180830381600087803b1580156107ed57600080fd5b505af1158015610801573d6000803e3d6000fd5b50505050506108106001600055565b50565b60018054610820906135e0565b80601f016020809104026020016040519081016040528092919081815260200182805461084c906135e0565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b505050505081565b6108a9610b98565b6040517f880d266c000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063880d266c90602401602060405180830381865afa158015610927573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094b9190613633565b6109d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5468652062616c6c6f74206973206e6f74207965742061626c6520746f20626560448201527f2066696e616c697a6564000000000000000000000000000000000000000000006064820152608401610457565b6040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634507488790602401600060405180830381865afa158015610a58573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a8091908101906134c0565b905060008160400151600a811115610a9a57610a9a61364e565b03610aad57610aa882610c0b565b610772565b60018160400151600a811115610ac557610ac561364e565b03610ad357610aa882610f1a565b60038160400151600a811115610aeb57610aeb61364e565b03610b0057600354421015610b005750610b09565b6107728261194e565b6108106001600055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610b93908490611aad565b505050565b600260005403610c04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610457565b6002600055565b6040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634507488790602401600060405180830381865afa158015610c8c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cb491908101906134c0565b6040517f0bb44e76000000000000000000000000000000000000000000000000000000008152600481018490529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630bb44e7690602401602060405180830381865afa158015610d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5c919061367d565b90506000816004811115610d7257610d7261364e565b03610e2057610e1b8260a00151600f811115610d9057610d9061364e565b60017f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611baf565b610edd565b6001816004811115610e3457610e3461364e565b03610edd57610edd8260a00151600f811115610e5257610e5261364e565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611baf565b827f787fae0daaaa02dbd66a0760a849b186c8a2e5ab9b46ed6790a0558329f8a1c982604051610f0d919061369e565b60405180910390a2505050565b6040517f84526cec000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906384526cec90602401602060405180830381865afa158015610f98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbc9190613633565b15610810576040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634507488790602401600060405180830381865afa158015611042573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261106a91908101906134c0565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ada4442d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f091906133de565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117691906133c1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f991906133de565b90506112068260026136b8565b8110156112bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f57686974656c697374696e67206973206e6f742063757272656e746c7920706f60448201527f737369626c652064756520746f20696e73756666696369656e7420626f6f747360648201527f7472617070696e67207265776172647300000000000000000000000000000000608482015260a401610457565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bf18543e84608001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633fc8cef36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561134d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137191906133c1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381600087803b1580156113d157600080fd5b505af11580156113e5573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bf18543e84608001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561147b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149f91906133c1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381600087803b1580156114ff57600080fd5b505af1158015611513573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385876e956040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561157257600080fd5b505af1158015611586573d6000803e3d6000fd5b50505050600061161b84608001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633fc8cef36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161691906133c1565b612218565b9050600061168585608001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b6040805160028082526060820190925291925060009190816020015b60408051808201909152600080825260208201528152602001906001900390816116a1579050509050604051806040016040528084815260200186815250816000815181106116f2576116f26136cf565b602002602001018190525060405180604001604052808381526020018681525081600181518110611725576117256136cf565b60200260200101819052507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561178e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b291906133c1565b6001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006117ec8860026136b8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af115801561184f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118739190613633565b506040517fd106dae10000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d106dae1906118d99084906004016136fe565b600060405180830381600087803b1580156118f357600080fd5b505af1158015611907573d6000803e3d6000fd5b5050505085608001516001600160a01b03167f135fa382eab99c8178b56314eb5b6dff1763d35fdb177c8332f18e0a4ff32e4f60405160405180910390a250505050505050565b6040517f84526cec000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906384526cec90602401602060405180830381865afa1580156119cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f09190613633565b15610810576040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634507488790602401600060405180830381865afa158015611a76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a9e91908101906134c0565b9050611aa9816122e7565b5050565b6000611b02826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e459092919063ffffffff16565b9050805160001480611b23575080806020019051810190611b239190613633565b610b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610457565b600086600f811115611bc357611bc361364e565b03611c42576040517fce7e4ba200000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b0385169063ce7e4ba2906024015b600060405180830381600087803b158015611c2557600080fd5b505af1158015611c39573d6000803e3d6000fd5b50505050612210565b600186600f811115611c5657611c5661364e565b03611ca2576040517f2c3fe73700000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03841690632c3fe73790602401611c0b565b600286600f811115611cb657611cb661364e565b03611d02576040517f0f80c7c200000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03841690630f80c7c290602401611c0b565b600386600f811115611d1657611d1661364e565b03611d62576040517f15935df900000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b038416906315935df990602401611c0b565b600486600f811115611d7657611d7661364e565b03611dc2576040517f8383269e00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03841690638383269e90602401611c0b565b600586600f811115611dd657611dd661364e565b03611e22576040517fed8a5e7700000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b0383169063ed8a5e7790602401611c0b565b600686600f811115611e3657611e3661364e565b03611e82576040517fdf11d42d00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b0383169063df11d42d90602401611c0b565b600786600f811115611e9657611e9661364e565b03611ee2576040517f23dd537b00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b038316906323dd537b90602401611c0b565b600886600f811115611ef657611ef661364e565b03611f42576040517fc00c1ec000000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b0382169063c00c1ec090602401611c0b565b600986600f811115611f5657611f5661364e565b03611fa2576040517f6130569400000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690636130569490602401611c0b565b600a86600f811115611fb657611fb661364e565b03612002576040517f0f9bc9fe00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690630f9bc9fe90602401611c0b565b600b86600f8111156120165761201661364e565b03612062576040517f6255af2200000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690636255af2290602401611c0b565b600c86600f8111156120765761207661364e565b036120c2576040517f01baf94e00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b038216906301baf94e90602401611c0b565b600d86600f8111156120d6576120d661364e565b03612122576040517f9783b7b500000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690639783b7b590602401611c0b565b600e86600f8111156121365761213661364e565b03612182576040517f47e4d72f00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b038216906347e4d72f90602401611c0b565b600f86600f8111156121965761219661364e565b03612210576040517f0bba265500000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690630bba265590602401600060405180830381600087803b1580156121f757600080fd5b505af115801561220b573d6000803e3d6000fd5b505050505b505050505050565b6000826001600160a01b0316826001600160a01b0316101561228d576040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015285901b166034820152604801604051602081830303815290604052805190602001209050610331565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085811b8216602084015284901b16603482015260480160405160208183030381529060405280519060200120905092915050565b60028160400151600a8111156122ff576122ff61364e565b03612610577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635fe9257482608001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633fc8cef36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ba91906133c1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381600087803b15801561241a57600080fd5b505af115801561242e573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635fe9257482608001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e891906133c1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381600087803b15801561254857600080fd5b505af115801561255c573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385876e956040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156125bb57600080fd5b505af11580156125cf573d6000803e3d6000fd5b5050505080608001516001600160a01b03167f0605196c37cbac61bc09b5f7563e3d035f75955e62ca7b10a5321f9386626f6960405160405180910390a250565b60038160400151600a8111156126285761262861364e565b0361283c578060a001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b491906133c1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015612713573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273791906133de565b10610810576127db81608001518260a001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cb91906133c1565b6001600160a01b03169190610b13565b6127e862093a8042613426565b60038190555080608001516001600160a01b03167f019ab7ffa8deca9abe2be22ff7ad0312be5fa93c3ad09489f7ad2b74669838548260a0015160405161283191815260200190565b60405180910390a250565b60048160400151600a8111156128545761285461364e565b0361294e57608081015160a08201516040517fb031537e0000000000000000000000000000000000000000000000000000000081526001600160a01b039092169163b031537e916128ab9160040190815260200190565b600060405180830381600087803b1580156128c557600080fd5b505af19250505080156128d6575060015b61290c573d808015612904576040519150601f19603f3d011682016040523d82523d6000602084013e612909565b606091505b50505b8060a0015181608001516001600160a01b03167f30d3875f3629365a603d62f6889826ab71cb3aa199856034c3cf0dd4676bc15a60405160405180910390a350565b60058160400151600a8111156129665761296661364e565b03612acb57600060028260c00151604051612981919061374d565b908152602001604051809103902060006101000a81548160ff0219169083151502179055507f53461c5d64b5022b90e4635624292d9ff4a4ed62d97d8e3e5e9256d5077982738160c0015160007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fdcb60686040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5091906133c1565b6001600160a01b031663a5e293b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ab191906133de565b604051612ac093929190613769565b60405180910390a150565b60068160400151600a811115612ae357612ae361364e565b03612c7d57600160028260c00151604051612afe919061374d565b908152602001604051809103902060006101000a81548160ff0219169083151502179055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fdcb60686040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba591906133c1565b6001600160a01b031663783af9976040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612bdf57600080fd5b505af1158015612bf3573d6000803e3d6000fd5b505050507f53461c5d64b5022b90e4635624292d9ff4a4ed62d97d8e3e5e9256d5077982738160c0015160017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fdcb60686040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a2c573d6000803e3d6000fd5b60078160400151600a811115612c9557612c9561364e565b03612d5b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d095a4d58260600151604051602001612cde919061378e565b604051602081830303815290604052600984608001518560e001516040518563ffffffff1660e01b8152600401612d1894939291906137e7565b6020604051808303816000875af1158015612d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa991906133de565b60088160400151600a811115612d7357612d7361364e565b03612df9577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d095a4d58260600151604051602001612dbc919061378e565b604051602081830303815290604052600a60008560c001518660e001516040518663ffffffff1660e01b8152600401612d1895949392919061383a565b60098160400151600a811115612e1157612e1161364e565b03612e1f5761081081612e5c565b600a8160400151600a811115612e3757612e3761364e565b036108105761081081612f34565b6060612e548484600085612f7a565b949350505050565b60808101516040517fc95808040000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201527f00000000000000000000000000000000000000000000000000000000000000009091169063c958080490602401600060405180830381600087803b158015612edf57600080fd5b505af1158015612ef3573d6000803e3d6000fd5b5050505080608001516001600160a01b03167fcd582c342d6a1928e4e023c1fac88be786cdb2001d965ff0f41bb0ba098d7ef560405160405180910390a250565b60c0810151600190612f4690826138e3565b507f3499c42b0f88098d2db4001620e9902dab4491c334ad3e417151d75ae7ce82798160c00151604051612ac0919061326c565b60608247101561300c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610457565b600080866001600160a01b03168587604051613028919061374d565b60006040518083038185875af1925050503d8060008114613065576040519150601f19603f3d011682016040523d82523d6000602084013e61306a565b606091505b509150915061307b87838387613086565b979650505050505050565b6060831561310f578251600003613108576001600160a01b0385163b613108576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610457565b5081612e54565b612e5483838151156131245781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610457919061326c565b6000806020838503121561316b57600080fd5b823567ffffffffffffffff8082111561318357600080fd5b818501915085601f83011261319757600080fd5b8135818111156131a657600080fd5b8660208285010111156131b857600080fd5b60209290920196919550909350505050565b6001600160a01b038116811461081057600080fd5b6000602082840312156131f157600080fd5b81356131fc816131ca565b9392505050565b60006020828403121561321557600080fd5b5035919050565b60005b8381101561323757818101518382015260200161321f565b50506000910152565b6000815180845261325881602086016020860161321c565b601f01601f19169290920160200192915050565b6020815260006131fc6020830184613240565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156132d2576132d261327f565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156133015761330161327f565b604052919050565b600067ffffffffffffffff8211156133235761332361327f565b50601f01601f191660200190565b60006020828403121561334357600080fd5b813567ffffffffffffffff81111561335a57600080fd5b8201601f8101841361336b57600080fd5b803561337e61337982613309565b6132d8565b81815285602083850101111561339357600080fd5b81602084016020830137600091810160200191909152949350505050565b8183823760009101908152919050565b6000602082840312156133d357600080fd5b81516131fc816131ca565b6000602082840312156133f057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610331576103316133f7565b81810381811115610331576103316133f7565b8051801515811461345c57600080fd5b919050565b8051600b811061345c57600080fd5b600082601f83011261348157600080fd5b815161348f61337982613309565b8181528460208386010111156134a457600080fd5b612e5482602083016020870161321c565b805161345c816131ca565b6000602082840312156134d257600080fd5b815167ffffffffffffffff808211156134ea57600080fd5b9083019061016082860312156134ff57600080fd5b6135076132ae565b825181526135176020840161344c565b602082015261352860408401613461565b604082015260608301518281111561353f57600080fd5b61354b87828601613470565b60608301525061355d608084016134b5565b608082015260a083015160a082015260c08301518281111561357e57600080fd5b61358a87828601613470565b60c08301525060e0830151828111156135a257600080fd5b6135ae87828601613470565b60e083015250610100838101519082015261012080840151908201526101409283015192810192909252509392505050565b600181811c908216806135f457607f821691505b60208210810361362d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561364557600080fd5b6131fc8261344c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561368f57600080fd5b8151600581106131fc57600080fd5b60208101600583106136b2576136b261364e565b91905290565b8082028115828204841417610331576103316133f7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602080825282518282018190526000919060409081850190868401855b828110156137405781518051855286015186850152928401929085019060010161371b565b5091979650505050505050565b6000825161375f81846020870161321c565b9190910192915050565b60608152600061377c6060830186613240565b93151560208301525060400152919050565b7f636f6e6669726d5f0000000000000000000000000000000000000000000000008152600082516137c681600885016020870161321c565b9190910160080192915050565b600b81106137e3576137e361364e565b9052565b60a0815260006137fa60a0830187613240565b61380760208401876137d3565b6001600160a01b0385166040840152828103806060850152600082526020810160808501525061307b6020820185613240565b60a08152600061384d60a0830188613240565b61385a60208401886137d3565b6001600160a01b0386166040840152828103606084015261387b8186613240565b9050828103608084015261388f8185613240565b98975050505050505050565b601f821115610b93576000816000526020600020601f850160051c810160208610156138c45750805b601f850160051c820191505b81811015612210578281556001016138d0565b815167ffffffffffffffff8111156138fd576138fd61327f565b6139118161390b84546135e0565b8461389b565b602080601f831160018114613964576000841561392e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612210565b600085815260208120601f198616915b8281101561399357888601518255948401946001909101908401613974565b50858210156139cf57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea26469706673582212205039d11bcdf29f39f101b17fa56dbb07403db8661c039be63b00561fc085793664736f6c634300081600330000000000000000000000003a07ffb529c1f4efe2bb3613e2419a149c3571100000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd90000000000000000000000000ac992636f863504039a028a6e9a2c192529c4870000000000000000000000001e1abc5affa2fadbdf8c10cfa4c432e6f6b674de000000000000000000000000c1c4cd45572ebc537120f25be396f2c6d2825e620000000000000000000000002a2bc9fdf452f7ba7e33b8d5db3955a6d6cdf335000000000000000000000000b97e087a9406ee5f3414a00414b95359a57bce6a
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806363eab1801161009757806396ceac341161006657806396ceac3414610264578063c5c51dca1461028b578063d3f22ec1146102b2578063fa05dd00146102e057600080fd5b806363eab18014610200578063779f6350146102155780637af0eb391461022a5780637b3ef6161461025157600080fd5b806336829dfc116100d357806336829dfc146101785780634e4cce731461019f57806352c19b5a146101b257806355ef20e6146101d957600080fd5b80630e2789bb146100fa57806313ea84a71461013e578063304591c414610161575b600080fd5b6101217f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd981565b6040516001600160a01b0390911681526020015b60405180910390f35b61015161014c366004613158565b610307565b6040519015158152602001610135565b61016a60035481565b604051908152602001610135565b6101217f0000000000000000000000001e1abc5affa2fadbdf8c10cfa4c432e6f6b674de81565b61016a6101ad3660046131df565b610337565b6101217f0000000000000000000000000ac992636f863504039a028a6e9a2c192529c48781565b6101217f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc81565b61021361020e366004613203565b61062a565b005b61021d610813565b604051610135919061326c565b6101217f000000000000000000000000b97e087a9406ee5f3414a00414b95359a57bce6a81565b61021361025f366004613203565b6108a1565b6101217f000000000000000000000000c1c4cd45572ebc537120f25be396f2c6d2825e6281565b6101217f0000000000000000000000003a07ffb529c1f4efe2bb3613e2419a149c35711081565b6101516102c0366004613331565b805160208183018101805160028252928201919093012091525460ff1681565b6101217f0000000000000000000000002a2bc9fdf452f7ba7e33b8d5db3955a6d6cdf33581565b60006002838360405161031b9291906133b1565b9081526040519081900360200190205460ff1690505b92915050565b60007f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b0316632cf4704a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103bb91906133c1565b6001600160a01b0316336001600160a01b031614610460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f44414f2e776974686472617746726f6d44414f206973206f6e6c792063616c6c60448201527f61626c652066726f6d207468652055706b65657020636f6e747261637400000060648201526084015b60405180910390fd5b6040517f2c6628570000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301527f0000000000000000000000003a07ffb529c1f4efe2bb3613e2419a149c3571101690632c66285790604401602060405180830381865afa1580156104e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050991906133de565b905061051760646001613426565b811161052557506000919050565b610530600182613439565b6040517ff3fef3a30000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390529192507f0000000000000000000000003a07ffb529c1f4efe2bb3613e2419a149c3571109091169063f3fef3a390604401600060405180830381600087803b1580156105b857600080fd5b505af11580156105cc573d6000803e3d6000fd5b506105e5925050506001600160a01b0383163383610b13565b6040518181526001600160a01b0383169033907f6337ed398c0e8467698c581374fdce4db14922df487b5a39483079f5f59b60a49060200160405180910390a3919050565b610632610b98565b6040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b031690634507488790602401600060405180830381865afa1580156106b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106db91908101906134c0565b9050806101200151421015610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5468652062616c6c6f74206973206e6f74207965742061626c6520746f20626560448201527f206d616e75616c6c792072656d6f7665640000000000000000000000000000006064820152608401610457565b6040517f568d86d7000000000000000000000000000000000000000000000000000000008152600481018390527f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b03169063568d86d790602401600060405180830381600087803b1580156107ed57600080fd5b505af1158015610801573d6000803e3d6000fd5b50505050506108106001600055565b50565b60018054610820906135e0565b80601f016020809104026020016040519081016040528092919081815260200182805461084c906135e0565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b505050505081565b6108a9610b98565b6040517f880d266c000000000000000000000000000000000000000000000000000000008152600481018290527f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b03169063880d266c90602401602060405180830381865afa158015610927573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094b9190613633565b6109d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5468652062616c6c6f74206973206e6f74207965742061626c6520746f20626560448201527f2066696e616c697a6564000000000000000000000000000000000000000000006064820152608401610457565b6040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b031690634507488790602401600060405180830381865afa158015610a58573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a8091908101906134c0565b905060008160400151600a811115610a9a57610a9a61364e565b03610aad57610aa882610c0b565b610772565b60018160400151600a811115610ac557610ac561364e565b03610ad357610aa882610f1a565b60038160400151600a811115610aeb57610aeb61364e565b03610b0057600354421015610b005750610b09565b6107728261194e565b6108106001600055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610b93908490611aad565b505050565b600260005403610c04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610457565b6002600055565b6040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b031690634507488790602401600060405180830381865afa158015610c8c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cb491908101906134c0565b6040517f0bb44e76000000000000000000000000000000000000000000000000000000008152600481018490529091506000906001600160a01b037f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc1690630bb44e7690602401602060405180830381865afa158015610d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5c919061367d565b90506000816004811115610d7257610d7261364e565b03610e2057610e1b8260a00151600f811115610d9057610d9061364e565b60017f0000000000000000000000000ac992636f863504039a028a6e9a2c192529c4877f0000000000000000000000001e1abc5affa2fadbdf8c10cfa4c432e6f6b674de7f000000000000000000000000c1c4cd45572ebc537120f25be396f2c6d2825e627f0000000000000000000000002a2bc9fdf452f7ba7e33b8d5db3955a6d6cdf335611baf565b610edd565b6001816004811115610e3457610e3461364e565b03610edd57610edd8260a00151600f811115610e5257610e5261364e565b60007f0000000000000000000000000ac992636f863504039a028a6e9a2c192529c4877f0000000000000000000000001e1abc5affa2fadbdf8c10cfa4c432e6f6b674de7f000000000000000000000000c1c4cd45572ebc537120f25be396f2c6d2825e627f0000000000000000000000002a2bc9fdf452f7ba7e33b8d5db3955a6d6cdf335611baf565b827f787fae0daaaa02dbd66a0760a849b186c8a2e5ab9b46ed6790a0558329f8a1c982604051610f0d919061369e565b60405180910390a2505050565b6040517f84526cec000000000000000000000000000000000000000000000000000000008152600481018290527f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b0316906384526cec90602401602060405180830381865afa158015610f98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbc9190613633565b15610810576040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b031690634507488790602401600060405180830381865afa158015611042573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261106a91908101906134c0565b905060007f0000000000000000000000002a2bc9fdf452f7ba7e33b8d5db3955a6d6cdf3356001600160a01b031663ada4442d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f091906133de565b905060007f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117691906133c1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f991906133de565b90506112068260026136b8565b8110156112bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f57686974656c697374696e67206973206e6f742063757272656e746c7920706f60448201527f737369626c652064756520746f20696e73756666696369656e7420626f6f747360648201527f7472617070696e67207265776172647300000000000000000000000000000000608482015260a401610457565b7f0000000000000000000000000ac992636f863504039a028a6e9a2c192529c4876001600160a01b031663bf18543e84608001517f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b0316633fc8cef36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561134d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137191906133c1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381600087803b1580156113d157600080fd5b505af11580156113e5573d6000803e3d6000fd5b505050507f0000000000000000000000000ac992636f863504039a028a6e9a2c192529c4876001600160a01b031663bf18543e84608001517f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561147b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149f91906133c1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381600087803b1580156114ff57600080fd5b505af1158015611513573d6000803e3d6000fd5b505050507f0000000000000000000000003a07ffb529c1f4efe2bb3613e2419a149c3571106001600160a01b03166385876e956040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561157257600080fd5b505af1158015611586573d6000803e3d6000fd5b50505050600061161b84608001517f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b0316633fc8cef36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161691906133c1565b612218565b9050600061168585608001517f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b6040805160028082526060820190925291925060009190816020015b60408051808201909152600080825260208201528152602001906001900390816116a1579050509050604051806040016040528084815260200186815250816000815181106116f2576116f26136cf565b602002602001018190525060405180604001604052808381526020018681525081600181518110611725576117256136cf565b60200260200101819052507f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561178e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b291906133c1565b6001600160a01b031663095ea7b37f000000000000000000000000b97e087a9406ee5f3414a00414b95359a57bce6a6117ec8860026136b8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af115801561184f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118739190613633565b506040517fd106dae10000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000b97e087a9406ee5f3414a00414b95359a57bce6a169063d106dae1906118d99084906004016136fe565b600060405180830381600087803b1580156118f357600080fd5b505af1158015611907573d6000803e3d6000fd5b5050505085608001516001600160a01b03167f135fa382eab99c8178b56314eb5b6dff1763d35fdb177c8332f18e0a4ff32e4f60405160405180910390a250505050505050565b6040517f84526cec000000000000000000000000000000000000000000000000000000008152600481018290527f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b0316906384526cec90602401602060405180830381865afa1580156119cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f09190613633565b15610810576040517f45074887000000000000000000000000000000000000000000000000000000008152600481018290526000907f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b031690634507488790602401600060405180830381865afa158015611a76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a9e91908101906134c0565b9050611aa9816122e7565b5050565b6000611b02826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e459092919063ffffffff16565b9050805160001480611b23575080806020019051810190611b239190613633565b610b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610457565b600086600f811115611bc357611bc361364e565b03611c42576040517fce7e4ba200000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b0385169063ce7e4ba2906024015b600060405180830381600087803b158015611c2557600080fd5b505af1158015611c39573d6000803e3d6000fd5b50505050612210565b600186600f811115611c5657611c5661364e565b03611ca2576040517f2c3fe73700000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03841690632c3fe73790602401611c0b565b600286600f811115611cb657611cb661364e565b03611d02576040517f0f80c7c200000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03841690630f80c7c290602401611c0b565b600386600f811115611d1657611d1661364e565b03611d62576040517f15935df900000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b038416906315935df990602401611c0b565b600486600f811115611d7657611d7661364e565b03611dc2576040517f8383269e00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03841690638383269e90602401611c0b565b600586600f811115611dd657611dd661364e565b03611e22576040517fed8a5e7700000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b0383169063ed8a5e7790602401611c0b565b600686600f811115611e3657611e3661364e565b03611e82576040517fdf11d42d00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b0383169063df11d42d90602401611c0b565b600786600f811115611e9657611e9661364e565b03611ee2576040517f23dd537b00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b038316906323dd537b90602401611c0b565b600886600f811115611ef657611ef661364e565b03611f42576040517fc00c1ec000000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b0382169063c00c1ec090602401611c0b565b600986600f811115611f5657611f5661364e565b03611fa2576040517f6130569400000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690636130569490602401611c0b565b600a86600f811115611fb657611fb661364e565b03612002576040517f0f9bc9fe00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690630f9bc9fe90602401611c0b565b600b86600f8111156120165761201661364e565b03612062576040517f6255af2200000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690636255af2290602401611c0b565b600c86600f8111156120765761207661364e565b036120c2576040517f01baf94e00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b038216906301baf94e90602401611c0b565b600d86600f8111156120d6576120d661364e565b03612122576040517f9783b7b500000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690639783b7b590602401611c0b565b600e86600f8111156121365761213661364e565b03612182576040517f47e4d72f00000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b038216906347e4d72f90602401611c0b565b600f86600f8111156121965761219661364e565b03612210576040517f0bba265500000000000000000000000000000000000000000000000000000000815285151560048201526001600160a01b03821690630bba265590602401600060405180830381600087803b1580156121f757600080fd5b505af115801561220b573d6000803e3d6000fd5b505050505b505050505050565b6000826001600160a01b0316826001600160a01b0316101561228d576040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015285901b166034820152604801604051602081830303815290604052805190602001209050610331565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085811b8216602084015284901b16603482015260480160405160208183030381529060405280519060200120905092915050565b60028160400151600a8111156122ff576122ff61364e565b03612610577f0000000000000000000000000ac992636f863504039a028a6e9a2c192529c4876001600160a01b0316635fe9257482608001517f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b0316633fc8cef36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ba91906133c1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381600087803b15801561241a57600080fd5b505af115801561242e573d6000803e3d6000fd5b505050507f0000000000000000000000000ac992636f863504039a028a6e9a2c192529c4876001600160a01b0316635fe9257482608001517f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e891906133c1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381600087803b15801561254857600080fd5b505af115801561255c573d6000803e3d6000fd5b505050507f0000000000000000000000003a07ffb529c1f4efe2bb3613e2419a149c3571106001600160a01b03166385876e956040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156125bb57600080fd5b505af11580156125cf573d6000803e3d6000fd5b5050505080608001516001600160a01b03167f0605196c37cbac61bc09b5f7563e3d035f75955e62ca7b10a5321f9386626f6960405160405180910390a250565b60038160400151600a8111156126285761262861364e565b0361283c578060a001517f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b491906133c1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015612713573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273791906133de565b10610810576127db81608001518260a001517f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663bc1b392d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cb91906133c1565b6001600160a01b03169190610b13565b6127e862093a8042613426565b60038190555080608001516001600160a01b03167f019ab7ffa8deca9abe2be22ff7ad0312be5fa93c3ad09489f7ad2b74669838548260a0015160405161283191815260200190565b60405180910390a250565b60048160400151600a8111156128545761285461364e565b0361294e57608081015160a08201516040517fb031537e0000000000000000000000000000000000000000000000000000000081526001600160a01b039092169163b031537e916128ab9160040190815260200190565b600060405180830381600087803b1580156128c557600080fd5b505af19250505080156128d6575060015b61290c573d808015612904576040519150601f19603f3d011682016040523d82523d6000602084013e612909565b606091505b50505b8060a0015181608001516001600160a01b03167f30d3875f3629365a603d62f6889826ab71cb3aa199856034c3cf0dd4676bc15a60405160405180910390a350565b60058160400151600a8111156129665761296661364e565b03612acb57600060028260c00151604051612981919061374d565b908152602001604051809103902060006101000a81548160ff0219169083151502179055507f53461c5d64b5022b90e4635624292d9ff4a4ed62d97d8e3e5e9256d5077982738160c0015160007f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663fdcb60686040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5091906133c1565b6001600160a01b031663a5e293b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ab191906133de565b604051612ac093929190613769565b60405180910390a150565b60068160400151600a811115612ae357612ae361364e565b03612c7d57600160028260c00151604051612afe919061374d565b908152602001604051809103902060006101000a81548160ff0219169083151502179055507f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663fdcb60686040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba591906133c1565b6001600160a01b031663783af9976040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612bdf57600080fd5b505af1158015612bf3573d6000803e3d6000fd5b505050507f53461c5d64b5022b90e4635624292d9ff4a4ed62d97d8e3e5e9256d5077982738160c0015160017f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd96001600160a01b031663fdcb60686040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a2c573d6000803e3d6000fd5b60078160400151600a811115612c9557612c9561364e565b03612d5b577f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b031663d095a4d58260600151604051602001612cde919061378e565b604051602081830303815290604052600984608001518560e001516040518563ffffffff1660e01b8152600401612d1894939291906137e7565b6020604051808303816000875af1158015612d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa991906133de565b60088160400151600a811115612d7357612d7361364e565b03612df9577f0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc6001600160a01b031663d095a4d58260600151604051602001612dbc919061378e565b604051602081830303815290604052600a60008560c001518660e001516040518663ffffffff1660e01b8152600401612d1895949392919061383a565b60098160400151600a811115612e1157612e1161364e565b03612e1f5761081081612e5c565b600a8160400151600a811115612e3757612e3761364e565b036108105761081081612f34565b6060612e548484600085612f7a565b949350505050565b60808101516040517fc95808040000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201527f000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd99091169063c958080490602401600060405180830381600087803b158015612edf57600080fd5b505af1158015612ef3573d6000803e3d6000fd5b5050505080608001516001600160a01b03167fcd582c342d6a1928e4e023c1fac88be786cdb2001d965ff0f41bb0ba098d7ef560405160405180910390a250565b60c0810151600190612f4690826138e3565b507f3499c42b0f88098d2db4001620e9902dab4491c334ad3e417151d75ae7ce82798160c00151604051612ac0919061326c565b60608247101561300c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610457565b600080866001600160a01b03168587604051613028919061374d565b60006040518083038185875af1925050503d8060008114613065576040519150601f19603f3d011682016040523d82523d6000602084013e61306a565b606091505b509150915061307b87838387613086565b979650505050505050565b6060831561310f578251600003613108576001600160a01b0385163b613108576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610457565b5081612e54565b612e5483838151156131245781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610457919061326c565b6000806020838503121561316b57600080fd5b823567ffffffffffffffff8082111561318357600080fd5b818501915085601f83011261319757600080fd5b8135818111156131a657600080fd5b8660208285010111156131b857600080fd5b60209290920196919550909350505050565b6001600160a01b038116811461081057600080fd5b6000602082840312156131f157600080fd5b81356131fc816131ca565b9392505050565b60006020828403121561321557600080fd5b5035919050565b60005b8381101561323757818101518382015260200161321f565b50506000910152565b6000815180845261325881602086016020860161321c565b601f01601f19169290920160200192915050565b6020815260006131fc6020830184613240565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156132d2576132d261327f565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156133015761330161327f565b604052919050565b600067ffffffffffffffff8211156133235761332361327f565b50601f01601f191660200190565b60006020828403121561334357600080fd5b813567ffffffffffffffff81111561335a57600080fd5b8201601f8101841361336b57600080fd5b803561337e61337982613309565b6132d8565b81815285602083850101111561339357600080fd5b81602084016020830137600091810160200191909152949350505050565b8183823760009101908152919050565b6000602082840312156133d357600080fd5b81516131fc816131ca565b6000602082840312156133f057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610331576103316133f7565b81810381811115610331576103316133f7565b8051801515811461345c57600080fd5b919050565b8051600b811061345c57600080fd5b600082601f83011261348157600080fd5b815161348f61337982613309565b8181528460208386010111156134a457600080fd5b612e5482602083016020870161321c565b805161345c816131ca565b6000602082840312156134d257600080fd5b815167ffffffffffffffff808211156134ea57600080fd5b9083019061016082860312156134ff57600080fd5b6135076132ae565b825181526135176020840161344c565b602082015261352860408401613461565b604082015260608301518281111561353f57600080fd5b61354b87828601613470565b60608301525061355d608084016134b5565b608082015260a083015160a082015260c08301518281111561357e57600080fd5b61358a87828601613470565b60c08301525060e0830151828111156135a257600080fd5b6135ae87828601613470565b60e083015250610100838101519082015261012080840151908201526101409283015192810192909252509392505050565b600181811c908216806135f457607f821691505b60208210810361362d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561364557600080fd5b6131fc8261344c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561368f57600080fd5b8151600581106131fc57600080fd5b60208101600583106136b2576136b261364e565b91905290565b8082028115828204841417610331576103316133f7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602080825282518282018190526000919060409081850190868401855b828110156137405781518051855286015186850152928401929085019060010161371b565b5091979650505050505050565b6000825161375f81846020870161321c565b9190910192915050565b60608152600061377c6060830186613240565b93151560208301525060400152919050565b7f636f6e6669726d5f0000000000000000000000000000000000000000000000008152600082516137c681600885016020870161321c565b9190910160080192915050565b600b81106137e3576137e361364e565b9052565b60a0815260006137fa60a0830187613240565b61380760208401876137d3565b6001600160a01b0385166040840152828103806060850152600082526020810160808501525061307b6020820185613240565b60a08152600061384d60a0830188613240565b61385a60208401886137d3565b6001600160a01b0386166040840152828103606084015261387b8186613240565b9050828103608084015261388f8185613240565b98975050505050505050565b601f821115610b93576000816000526020600020601f850160051c810160208610156138c45750805b601f850160051c820191505b81811015612210578281556001016138d0565b815167ffffffffffffffff8111156138fd576138fd61327f565b6139118161390b84546135e0565b8461389b565b602080601f831160018114613964576000841561392e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612210565b600085815260208120601f198616915b8281101561399357888601518255948401946001909101908401613974565b50858210156139cf57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea26469706673582212205039d11bcdf29f39f101b17fa56dbb07403db8661c039be63b00561fc085793664736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003a07ffb529c1f4efe2bb3613e2419a149c3571100000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd90000000000000000000000000ac992636f863504039a028a6e9a2c192529c4870000000000000000000000001e1abc5affa2fadbdf8c10cfa4c432e6f6b674de000000000000000000000000c1c4cd45572ebc537120f25be396f2c6d2825e620000000000000000000000002a2bc9fdf452f7ba7e33b8d5db3955a6d6cdf335000000000000000000000000b97e087a9406ee5f3414a00414b95359a57bce6a
-----Decoded View---------------
Arg [0] : _pools (address): 0x3A07FfB529C1f4EfE2Bb3613e2419a149c357110
Arg [1] : _proposals (address): 0x1b4ed0e03E124DF3946B7b03032a0f8AF416c6cC
Arg [2] : _exchangeConfig (address): 0xF2fEd4a7a8D1CC2dB73AE0439E07db21D0D58bD9
Arg [3] : _poolsConfig (address): 0x0aC992636f863504039A028A6E9a2c192529c487
Arg [4] : _stakingConfig (address): 0x1E1aBC5aFFA2FadBDf8c10CfA4C432E6f6B674De
Arg [5] : _rewardsConfig (address): 0xc1c4cd45572EbC537120f25be396F2c6d2825E62
Arg [6] : _daoConfig (address): 0x2A2BC9FDF452f7Ba7e33B8d5Db3955a6D6cDF335
Arg [7] : _liquidityRewardsEmitter (address): 0xb97e087A9406EE5f3414a00414B95359a57BCE6A
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000003a07ffb529c1f4efe2bb3613e2419a149c357110
Arg [1] : 0000000000000000000000001b4ed0e03e124df3946b7b03032a0f8af416c6cc
Arg [2] : 000000000000000000000000f2fed4a7a8d1cc2db73ae0439e07db21d0d58bd9
Arg [3] : 0000000000000000000000000ac992636f863504039a028a6e9a2c192529c487
Arg [4] : 0000000000000000000000001e1abc5affa2fadbdf8c10cfa4c432e6f6b674de
Arg [5] : 000000000000000000000000c1c4cd45572ebc537120f25be396f2c6d2825e62
Arg [6] : 0000000000000000000000002a2bc9fdf452f7ba7e33b8d5db3955a6d6cdf335
Arg [7] : 000000000000000000000000b97e087a9406ee5f3414a00414b95359a57bce6a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.