More Info
Private Name Tags
ContractCreator
Multichain Info
No addresses found
Latest 25 from a total of 544 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Stake_66380860 | 22133278 | 36 mins ago | IN | 0 ETH | 0.00017868 | ||||
Stake_66380860 | 22133222 | 47 mins ago | IN | 0 ETH | 0.00018583 | ||||
Claim_41202704 | 22131818 | 5 hrs ago | IN | 0 ETH | 0.00076177 | ||||
Stake_66380860 | 22131183 | 7 hrs ago | IN | 0 ETH | 0.00030848 | ||||
Claim_41202704 | 22130939 | 8 hrs ago | IN | 0 ETH | 0.00029098 | ||||
Claim_41202704 | 22126801 | 22 hrs ago | IN | 0 ETH | 0.00026953 | ||||
Request Claim_81... | 22126289 | 23 hrs ago | IN | 0 ETH | 0.00057585 | ||||
Flash Withdraw W... | 22126278 | 24 hrs ago | IN | 0 ETH | 0.00032157 | ||||
Request Claim_81... | 22126134 | 24 hrs ago | IN | 0 ETH | 0.00031324 | ||||
Flash Withdraw W... | 22124473 | 30 hrs ago | IN | 0 ETH | 0.00007211 | ||||
Flash Withdraw W... | 22124470 | 30 hrs ago | IN | 0 ETH | 0.00007211 | ||||
Stake_66380860 | 22124304 | 30 hrs ago | IN | 0 ETH | 0.00029309 | ||||
Claim_41202704 | 22121537 | 39 hrs ago | IN | 0 ETH | 0.00036062 | ||||
Claim_41202704 | 22120668 | 42 hrs ago | IN | 0 ETH | 0.00018962 | ||||
Claim_41202704 | 22118243 | 2 days ago | IN | 0 ETH | 0.00041096 | ||||
Request Claim_81... | 22115213 | 2 days ago | IN | 0 ETH | 0.00026844 | ||||
Request Claim_81... | 22113544 | 2 days ago | IN | 0 ETH | 0.00039182 | ||||
Claim_41202704 | 22109582 | 3 days ago | IN | 0 ETH | 0.00025902 | ||||
Claim_41202704 | 22107844 | 3 days ago | IN | 0 ETH | 0.00023825 | ||||
Stake_66380860 | 22104183 | 4 days ago | IN | 0 ETH | 0.00015434 | ||||
Request Claim_81... | 22101297 | 4 days ago | IN | 0 ETH | 0.00029503 | ||||
Stake_66380860 | 22101046 | 4 days ago | IN | 0 ETH | 0.00028179 | ||||
Claim_41202704 | 22100503 | 4 days ago | IN | 0 ETH | 0.0002709 | ||||
Stake_66380860 | 22100320 | 4 days ago | IN | 0 ETH | 0.00027857 | ||||
Claim_41202704 | 22099026 | 4 days ago | IN | 0 ETH | 0.00057626 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
Vault
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 20 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity =0.8.28; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import "./IzkToken.sol"; import "./IWithdrawVault.sol"; import "./IVault.sol"; import "./utils.sol"; contract Vault is Pausable, AccessControl, IVault { using SafeERC20 for IERC20; using SafeERC20 for IzkToken; mapping(address => uint256) private tvl; // Supported tokens list mapping(address => bool) public supportedTokens; //zkTokens list mapping(address => IzkToken) public supportedTokenToZkToken; mapping(address => address) public zkTokenToSupportedToken; uint256 public lastClaimQueueID = 10_000; mapping(uint256 => ClaimItem) private claimQueue; // Main information mapping(address => mapping(address => AssetsInfo)) private userAssetsInfo; // Reward rate struct RewardRateState { address token; uint256 rewardRate; uint256 updatedTime; } mapping(address => RewardRateState[]) private rewardRateState; // Role bytes32 private constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 private constant BOT_ROLE = keccak256("BOT_ROLE"); // Misc address private ceffu; uint256 private penaltyRate = 50; // 0.5% mapping(address => uint256) public minStakeAmount; mapping(address => uint256) public maxStakeAmount; uint256 public WAITING_TIME; uint256 private constant BASE = 10_000; mapping(address => uint256) public totalStakeAmountByToken; mapping(address => uint256) private _lastRewardUpdatedTime; mapping(address => uint256) public totalRewardsAmountByToken; uint256 private initialTime; IWithdrawVault private withdrawVault; address private airdropAddr; bool flashNotEnable; bool cancelNotEnable = true; constructor( address[] memory _tokens, address[] memory _zkTokens, uint256[] memory _newRewardRate, uint256[] memory _minStakeAmount, uint256[] memory _maxStakeAmount, address _admin, address _bot, address _ceffu, uint256 _waitingTime, address payable withdrawVaultAddress, address _airdropAddr ) { Utils.CheckIsZeroAddress(_ceffu); Utils.CheckIsZeroAddress(_admin); Utils.CheckIsZeroAddress(_bot); airdropAddr = _airdropAddr; uint256 len = _tokens.length; require(Utils.MustGreaterThanZero(len)); require( len == _newRewardRate.length && len == _minStakeAmount.length && len == _maxStakeAmount.length && len == _zkTokens.length ); // Grant role _grantRole(DEFAULT_ADMIN_ROLE, _admin); _grantRole(PAUSER_ROLE, _admin); _grantRole(BOT_ROLE, _bot); ceffu = _ceffu; emit UpdateCeffu(address(0), _ceffu); WAITING_TIME = _waitingTime; emit UpdateWaitingTime(0, _waitingTime); initialTime = block.timestamp; // Set the supported tokens and reward rate for (uint256 i = 0; i < len; i++) { require(_minStakeAmount[i] < _maxStakeAmount[i]); // supported tokens address token = _tokens[i]; minStakeAmount[token] = _minStakeAmount[i]; maxStakeAmount[token] = _maxStakeAmount[i]; supportedTokens[token] = true; emit AddSupportedToken(token, _minStakeAmount[i], _maxStakeAmount[i]); IzkToken tokenTemp = IzkToken(_zkTokens[i]); supportedTokenToZkToken[token] = tokenTemp; zkTokenToSupportedToken[address(tokenTemp)] = token; emit ZkTokenCreated(address(tokenTemp)); // reward rate RewardRateState memory rewardRateItem = RewardRateState({ token: token, rewardRate: _newRewardRate[i], updatedTime: block.timestamp }); rewardRateState[token].push(rewardRateItem); emit UpdateRewardRate(token, 0, _newRewardRate[i]); _lastRewardUpdatedTime[token] = block.timestamp; } withdrawVault = IWithdrawVault(withdrawVaultAddress); _pause(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// Controller /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// modifier OnlyFlashEnable{ require(!flashNotEnable, "flash withdraw not enable"); _; } modifier OnlyCancelEnable{ require(!cancelNotEnable, "cancel claim not enable"); _; } event FlashStatusChanged(bool indexed oldStatus, bool indexed newStatus); event CancelStatusChanged(bool indexed oldStatus, bool indexed newStatus); function setFlashEnable(bool _enable) external onlyRole(DEFAULT_ADMIN_ROLE){ require(_enable != flashNotEnable, "nothing changed"); bool oldStatus = flashNotEnable; flashNotEnable = _enable; emit FlashStatusChanged(oldStatus, _enable); } function setCancelEnable(bool _enable) external onlyRole(DEFAULT_ADMIN_ROLE){ require(_enable != cancelNotEnable, "nothing changed"); bool oldStatus = cancelNotEnable; cancelNotEnable = _enable; emit CancelStatusChanged(oldStatus, _enable); } modifier onlySupportedToken(address _token) { require(supportedTokens[_token], "Unsupported"); _; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// write /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// // function signature: 000000ed, the less function matching, the more gas saved function stake_66380860(address _token, uint256 _stakedAmount) external onlySupportedToken(_token) whenNotPaused { AssetsInfo storage assetsInfo = userAssetsInfo[msg.sender][_token]; uint256 currentStakedAmount = assetsInfo.stakedAmount; require(Utils.Add(currentStakedAmount, _stakedAmount) >= minStakeAmount[_token]); require(Utils.Add(currentStakedAmount, _stakedAmount) <= maxStakeAmount[_token]); IERC20(_token).safeTransferFrom(msg.sender, address(this), _stakedAmount); _updateRewardState(msg.sender, _token); uint256 exchangeRate = _getExchangeRate(_token); totalStakeAmountByToken[_token] += _stakedAmount; uint256 mintAmount = _stakedAmount * 1e18 / exchangeRate; supportedTokenToZkToken[_token].mint(msg.sender, mintAmount); // update status assetsInfo.stakeHistory.push( StakeItem({ stakeTimestamp: block.timestamp, amount: _stakedAmount, token: _token, user: msg.sender }) ); unchecked { assetsInfo.stakedAmount += _stakedAmount; tvl[_token] += _stakedAmount; } emit Stake(msg.sender, _token, _stakedAmount); } // function signature: 0000004e, the less function matching, the more gas saved function requestClaim_8135334( address _token, uint256 _amount ) external onlySupportedToken(_token) whenNotPaused returns(uint256 _returnID) { _updateRewardState(msg.sender, _token); uint256 exchangeRate = _getExchangeRate(_token); AssetsInfo storage assetsInfo = userAssetsInfo[msg.sender][_token]; uint256 currentStakedAmount = assetsInfo.stakedAmount; uint256 currentAccumulatedRewardAmount = assetsInfo.accumulatedReward; require( Utils.MustGreaterThanZero(_amount) && (_amount <= Utils.Add(currentStakedAmount, currentAccumulatedRewardAmount) || _amount == type(uint256).max), "Invalid amount" ); ClaimItem storage queueItem = claimQueue[lastClaimQueueID]; // Withdraw from reward first; if insufficient, continue withdrawing from principal uint256 totalAmount = _amount; (totalAmount, , ) = _handleWithdraw(_amount, assetsInfo, queueItem, false); require(totalAmount > 0, "No assets to withdraw"); // update status assetsInfo.pendingClaimQueueIDs.push(lastClaimQueueID); totalStakeAmountByToken[_token] -= queueItem.principalAmount; totalRewardsAmountByToken[_token] -= queueItem.rewardAmount; uint256 sharesToBurn = totalAmount * 1e18 / exchangeRate; uint256 zkBalance = supportedTokenToZkToken[_token].balanceOf(msg.sender); if(sharesToBurn > zkBalance || assetsInfo.stakedAmount == 0) sharesToBurn = zkBalance; supportedTokenToZkToken[_token].burn(msg.sender, sharesToBurn); // update queue queueItem.token = _token; queueItem.user = msg.sender; queueItem.totalAmount = totalAmount; queueItem.requestTime = block.timestamp; queueItem.claimTime = Utils.Add(block.timestamp, WAITING_TIME); unchecked { _returnID = lastClaimQueueID; ++lastClaimQueueID; } emit RequestClaim(msg.sender, _token, totalAmount, _returnID); } function cancelClaim(uint256 _queueId, address _token) external whenNotPaused OnlyCancelEnable{ ClaimItem memory claimItem = claimQueue[_queueId]; delete claimQueue[_queueId]; address token = claimItem.token; AssetsInfo storage assetsInfo = userAssetsInfo[msg.sender][token]; uint256[] memory pendingClaimQueueIDs = userAssetsInfo[msg.sender][token].pendingClaimQueueIDs; require(Utils.MustGreaterThanZero(claimItem.totalAmount)); require(claimItem.user == msg.sender); require(!claimItem.isDone, "claimed"); require(token == _token, "wrong token"); for(uint256 i = 0; i < pendingClaimQueueIDs.length; i++) { if(pendingClaimQueueIDs[i] == _queueId) { assetsInfo.pendingClaimQueueIDs[i] = pendingClaimQueueIDs[pendingClaimQueueIDs.length-1]; assetsInfo.pendingClaimQueueIDs.pop(); break; } } uint256 principal = claimItem.principalAmount; uint256 reward = claimItem.rewardAmount; assetsInfo.stakedAmount += principal; assetsInfo.accumulatedReward += reward; assetsInfo.lastRewardUpdateTime = block.timestamp; _updateRewardState(msg.sender, _token); uint256 exchangeRate = _getExchangeRate(_token); uint256 amountToMint = (principal + reward) * 1e18 / exchangeRate; totalStakeAmountByToken[_token] += principal; totalRewardsAmountByToken[_token] += reward; supportedTokenToZkToken[_token].mint(msg.sender, amountToMint); emit CancelClaim(msg.sender, _token, principal + reward, _queueId); } // function signature: 000000e5, the less function matching, the more gas saved function claim_41202704(uint256 _queueID, address _token) external whenNotPaused{ ClaimItem memory claimItem = claimQueue[_queueID]; address token = claimItem.token; AssetsInfo storage assetsInfo = userAssetsInfo[msg.sender][token]; uint256[] memory pendingClaimQueueIDs = userAssetsInfo[msg.sender][token].pendingClaimQueueIDs; require(Utils.MustGreaterThanZero(claimItem.totalAmount)); require(block.timestamp >= claimItem.claimTime); require(claimItem.user == msg.sender); require(!claimItem.isDone, "claimed"); require(token == _token, "wrong token"); // update status claimQueue[_queueID].isDone = true; for(uint256 i = 0; i < pendingClaimQueueIDs.length; i++) { if(pendingClaimQueueIDs[i] == _queueID) { assetsInfo.pendingClaimQueueIDs[i] = pendingClaimQueueIDs[pendingClaimQueueIDs.length-1]; assetsInfo.pendingClaimQueueIDs.pop(); break; } } tvl[token] -= claimItem.principalAmount; assetsInfo.claimHistory.push( ClaimItem({ isDone: true, token: token, user: msg.sender, totalAmount: claimItem.totalAmount, principalAmount: claimItem.principalAmount, rewardAmount: claimItem.rewardAmount, requestTime: claimItem.requestTime, claimTime: block.timestamp }) ); withdrawVault.transfer(token, msg.sender, claimItem.totalAmount); emit ClaimAssets(msg.sender, token, claimItem.totalAmount, _queueID); } function flashWithdrawWithPenalty( address _token, uint256 _amount ) external onlySupportedToken(_token) whenNotPaused OnlyFlashEnable{ AssetsInfo storage assetsInfo = userAssetsInfo[msg.sender][_token]; _updateRewardState(msg.sender, _token); uint256 exchangeRate = _getExchangeRate(_token); uint256 currentStakedAmount = assetsInfo.stakedAmount; uint256 currentAccumulatedRewardAmount = assetsInfo.accumulatedReward; require( Utils.MustGreaterThanZero(_amount) && (_amount <= Utils.Add(currentStakedAmount, currentAccumulatedRewardAmount) || _amount == type(uint256).max) ); uint256 totalAmount = _amount; uint256 principalAmount; uint256 rewardAmount; (totalAmount, principalAmount, rewardAmount) = _handleWithdraw(_amount, assetsInfo, claimQueue[lastClaimQueueID], true); require(totalAmount > 0, "no assets to withdraw"); totalStakeAmountByToken[_token] -= principalAmount; totalRewardsAmountByToken[_token] -= rewardAmount; uint256 sharesToBurn = (totalAmount * 1e18) / exchangeRate; uint256 zkBalance = supportedTokenToZkToken[_token].balanceOf(msg.sender); if(sharesToBurn > zkBalance || assetsInfo.stakedAmount == 0) sharesToBurn = zkBalance; supportedTokenToZkToken[_token].burn(msg.sender, sharesToBurn); uint256 amountToSent = totalAmount * (BASE - penaltyRate) / BASE; uint256 fee = totalAmount - amountToSent; require(getContractBalance(_token) >= amountToSent, "not enough balance"); IERC20(_token).safeTransfer(msg.sender, amountToSent); tvl[_token] -= principalAmount; assetsInfo.claimHistory.push( ClaimItem({ isDone: true, token: _token, user: msg.sender, totalAmount: totalAmount, principalAmount: principalAmount, rewardAmount: rewardAmount, requestTime: block.timestamp, claimTime: block.timestamp }) ); emit FlashWithdraw(msg.sender, _token, totalAmount, fee); } function _handleWithdraw( uint256 _amount, AssetsInfo storage assetsInfo, ClaimItem storage queueItem, bool isFlash ) internal returns(uint256, uint256, uint256){ uint256 totalAmount = _amount; uint256 principalAmount; uint256 rewardAmount; uint256 currentAccumulatedRewardAmount = assetsInfo.accumulatedReward; if(_amount == type(uint256).max){ totalAmount = Utils.Add(currentAccumulatedRewardAmount, assetsInfo.stakedAmount); rewardAmount = currentAccumulatedRewardAmount; assetsInfo.accumulatedReward = 0; principalAmount = assetsInfo.stakedAmount; assetsInfo.stakedAmount = 0; }else if(currentAccumulatedRewardAmount >= _amount) { assetsInfo.accumulatedReward -= _amount; rewardAmount = _amount; } else { rewardAmount = currentAccumulatedRewardAmount; assetsInfo.accumulatedReward = 0; uint256 difference = _amount - currentAccumulatedRewardAmount; assetsInfo.stakedAmount -= difference; principalAmount = difference; } if(!isFlash) { queueItem.rewardAmount = rewardAmount; queueItem.principalAmount = principalAmount; } return(totalAmount, principalAmount, rewardAmount); } function _updateRewardState(address _user, address _token) internal { AssetsInfo storage assetsInfo = userAssetsInfo[_user][_token]; uint256 newAccumulatedReward = 0; uint256 newAccumulatedRewardForAll; if(assetsInfo.lastRewardUpdateTime != 0) { // not the first time to stake newAccumulatedReward = _getClaimableRewards(_user, _token); } newAccumulatedRewardForAll = _getClaimableRewards(address(this), _token); assetsInfo.accumulatedReward = newAccumulatedReward; assetsInfo.lastRewardUpdateTime = block.timestamp; _lastRewardUpdatedTime[_token] = block.timestamp; totalRewardsAmountByToken[_token] = newAccumulatedRewardForAll; } function _getExchangeRate(address _token) internal view returns(uint256 exchangeRate){ uint256 totalSupplyZKToken = supportedTokenToZkToken[_token].totalSupply(); if (totalSupplyZKToken == 0) { exchangeRate = 1e18; } else { exchangeRate = ((totalStakeAmountByToken[_token] + totalRewardsAmountByToken[_token]) * 1e18) / totalSupplyZKToken; } } function convertToShares(uint256 tokenAmount, address _token) public view returns(uint256 shares) { uint256 totalSupplyZKToken = supportedTokenToZkToken[_token].totalSupply(); uint256 totalStaked = totalStakeAmountByToken[_token]; uint256 totalRewards = _getClaimableRewards(address(this), _token); uint256 exchangeRate = totalSupplyZKToken == 0 ? 1e18 : (totalStaked + totalRewards) * 1e18 / totalSupplyZKToken; shares = (tokenAmount * 1e18) / exchangeRate; } function convertToAssets(uint256 shares, address _token) public view returns(uint256 tokenAmount) { uint256 totalSupplyZKToken = supportedTokenToZkToken[_token].totalSupply(); uint256 totalStaked = totalStakeAmountByToken[_token]; uint256 totalRewards = _getClaimableRewards(address(this), _token); uint256 exchangeRate = totalSupplyZKToken == 0 ? 1e18 : (totalStaked + totalRewards) * 1e18 / totalSupplyZKToken; tokenAmount = (shares * exchangeRate) / 1e18; } function transferOrTransferFrom(address token, address from, address to, uint256 amount) public returns (bool) { require(from != to, "from can not be same as the to"); require(amount > 0, "amount must be greater than 0"); uint256 tokenBefore = getZKTokenAmount(from, token); require(tokenBefore >= amount, "balance"); if(msg.sender != from){ require(supportedTokenToZkToken[token].allowance(from, msg.sender) >= amount, "allowance"); supportedTokenToZkToken[token].updateAllowance(from, msg.sender, amount); supportedTokenToZkToken[token].transferFrom(from, to, amount); }else{ supportedTokenToZkToken[token].transferFrom(msg.sender, to, amount); } _assetsInfoUpdate(token, from, to, amount, tokenBefore); return true; } // airdrop function sendLpTokens(address token, address to, uint256 amount, bool flag) external { require(msg.sender == airdropAddr); supportedTokenToZkToken[token].transferFrom(airdropAddr, to, amount); AssetsInfo storage assetsInfo = userAssetsInfo[to][token]; if(flag == true){ assetsInfo.lastRewardUpdateTime = initialTime; }else{ _updateRewardState(to, token); } assetsInfo.stakedAmount += amount; totalStakeAmountByToken[token] += amount; tvl[token] += amount; } function _assetsInfoUpdate(address token, address from, address to, uint256 amount, uint256 tokenBefore) internal{ _updateRewardState(from, token); _updateRewardState(to, token); AssetsInfo storage assetsInfoFrom = userAssetsInfo[from][token]; uint256 stakedAmount = assetsInfoFrom.stakedAmount; uint256 accumulatedReward = assetsInfoFrom.accumulatedReward; AssetsInfo storage assetsInfoTo = userAssetsInfo[to][token]; uint256 percent = amount * 1e18 / tokenBefore; uint256 deltaStaked = (stakedAmount * percent / 1e18); uint256 deltaReward = (accumulatedReward * percent / 1e18); assetsInfoTo.stakedAmount += deltaStaked; assetsInfoFrom.stakedAmount -= deltaStaked; assetsInfoTo.accumulatedReward += deltaReward; assetsInfoFrom.accumulatedReward -= deltaReward; assetsInfoTo.lastRewardUpdateTime = block.timestamp ; } function transferToCeffu( address _token, uint256 _amount ) external onlySupportedToken(_token) onlyRole(BOT_ROLE) { require(Utils.MustGreaterThanZero(_amount), "must > 0"); require(_amount <= IERC20(_token).balanceOf(address(this)), "Not enough balance"); IERC20(_token).safeTransfer(ceffu, _amount); emit CeffuReceive(_token, ceffu, _amount); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// emergency /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// function emergencyWithdraw(address _token, address _receiver) external onlyRole(DEFAULT_ADMIN_ROLE) { // `_token` could be not supported, so that we could sweep the tokens which are sent to this contract accidentally Utils.CheckIsZeroAddress(_token); Utils.CheckIsZeroAddress(_receiver); IERC20(_token).safeTransfer(_receiver, IERC20(_token).balanceOf(address(this))); emit EmergencyWithdrawal(_token, _receiver); } function pause() external onlyRole(PAUSER_ROLE) { _pause(); } function unpause() external onlyRole(PAUSER_ROLE) { _unpause(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// configuration /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// function addSupportedToken( address _token, uint256 _minAmount, uint256 _maxAmount, address _zkToken ) external onlyRole(DEFAULT_ADMIN_ROLE) { Utils.CheckIsZeroAddress(_token); require(!supportedTokens[_token], "Supported"); // update the supported tokens supportedTokens[_token] = true; setStakeLimit(_token, _minAmount, _maxAmount); emit AddSupportedToken(_token, _minAmount, _maxAmount); IzkToken tokenTemp = IzkToken(_zkToken); supportedTokenToZkToken[_token] = tokenTemp; zkTokenToSupportedToken[address(tokenTemp)] = _token; emit ZkTokenCreated(address(tokenTemp)); } function setRewardRate( address _token, uint256 _newRewardRate ) external onlySupportedToken(_token) onlyRole(DEFAULT_ADMIN_ROLE) { require(_newRewardRate < BASE, "Invalid rate"); RewardRateState[] memory rewardRateArray = rewardRateState[_token]; uint256 currentRewardRate = rewardRateArray[rewardRateArray.length - 1].rewardRate; require(currentRewardRate != _newRewardRate && Utils.MustGreaterThanZero(_newRewardRate), "Invalid new rate"); // add the new reward rate to the array RewardRateState memory rewardRateItem = RewardRateState({ updatedTime: block.timestamp, token: _token, rewardRate: _newRewardRate }); rewardRateState[_token].push(rewardRateItem); emit UpdateRewardRate(_token, currentRewardRate, _newRewardRate); } function setAirdropAddr(address newAirdropAddr) external onlyRole(DEFAULT_ADMIN_ROLE) { //allow equal address(0), when we want to disable airdrop airdropAddr = newAirdropAddr; } function setPenaltyRate(uint256 newRate) external onlyRole(DEFAULT_ADMIN_ROLE) { require(newRate <= BASE && newRate != penaltyRate, "Invalid"); emit UpdatePenaltyRate(penaltyRate, newRate); penaltyRate = newRate; } function setCeffu(address _newCeffu) external onlyRole(DEFAULT_ADMIN_ROLE) { Utils.CheckIsZeroAddress(_newCeffu); require(_newCeffu != ceffu); emit UpdateCeffu(ceffu, _newCeffu); ceffu = _newCeffu; } function setStakeLimit( address _token, uint256 _minAmount, uint256 _maxAmount ) public onlyRole(DEFAULT_ADMIN_ROLE) onlySupportedToken(_token) { require(Utils.MustGreaterThanZero(_minAmount) && _minAmount < _maxAmount); emit UpdateStakeLimit(_token, minStakeAmount[_token], maxStakeAmount[_token], _minAmount, _maxAmount); minStakeAmount[_token] = _minAmount; maxStakeAmount[_token] = _maxAmount; } function setWaitingTime(uint256 _newWaitingTime) external onlyRole(DEFAULT_ADMIN_ROLE){ require(_newWaitingTime != WAITING_TIME, "Invalid"); emit UpdateWaitingTime(WAITING_TIME, _newWaitingTime); WAITING_TIME = _newWaitingTime; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// view / pure /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// function calculateReward( uint256 _stakedAmount, uint256 _rewardRate, uint256 _elapsedTime ) internal pure returns (uint256 result) { // (stakedAmount * rewardRate * elapsedTime) / (ONE_YEAR * 10000) // Parameter descriptions: // - stakedAmount: The amount staked by the user // - rewardRate: The annual reward rate (e.g., 700 means 7%) // - elapsedTime: The time interval over which the reward is calculated, in seconds // - ONE_YEAR: The total number of seconds in one year (365.25 days) assembly { // uint256 ONE_YEAR = uint256(365.25 * 24 * 60 * 60); // 365.25 days per year: 31557600 let ONE_YEAR := 31557600 // Calculate numerator = stakedAmount * rewardRate * elapsedTime let numerator := mul(_stakedAmount, _rewardRate) numerator := mul(numerator, _elapsedTime) // Calculate denominator = ONE_YEAR * 10000 let denominator := mul(ONE_YEAR, BASE) // Perform the division result = numerator / denominator result := div(numerator, denominator) } } function _getClaimableRewards(address _user, address _token) internal view returns (uint256) { uint256 currentStakedAmount; uint256 lastRewardUpdate; uint256 currentRewardAmount; if(_user != address(this)){ AssetsInfo memory assetsInfo = userAssetsInfo[_user][_token]; currentStakedAmount = assetsInfo.stakedAmount; lastRewardUpdate = assetsInfo.lastRewardUpdateTime; currentRewardAmount = assetsInfo.accumulatedReward; } else { currentStakedAmount = totalStakeAmountByToken[_token]; lastRewardUpdate = _lastRewardUpdatedTime[_token]; currentRewardAmount = totalRewardsAmountByToken[_token]; } RewardRateState[] memory rewardRateArray = rewardRateState[_token]; uint256 rewardRateLength = rewardRateArray.length; RewardRateState memory currentRewardRateState = rewardRateArray[rewardRateLength - 1]; if(lastRewardUpdate == 0) return 0; // 1. Retrieve the last deposit time `begin` // 2. Retrieve the current deposit time `end` // 3. Check whether the reward rate changed between time `begin` and time `end` // 4. Determine if the reward rate has changed since the last deposit: // - If no changes occurred, directly calculate and add the reward. // - If changes occurred, divide the deposit time into segments based on different rates // and accumulate the rewards accordingly. if(currentRewardRateState.updatedTime <= lastRewardUpdate){ /* begin end |~~~~~~ position ~~~~~~~| |--------- reward rate 1 --------------|--------- upcoming reward rate 2 --------------| */ uint256 elapsedTime = block.timestamp - lastRewardUpdate; uint256 reward = calculateReward( currentStakedAmount, currentRewardRateState.rewardRate, elapsedTime ); return currentRewardAmount + reward; } else { /* begin end |~~~~~~~~~~~~~~~~~~~~~~ position ~~~~~~~~~~~~~~~~~~~~~~~~~~~| |--------- reward rate 1 --------------|-- reward rate 2 --|-------- reward rate 3 --------| */ // a. based on the reward rate at the time of the last stake, find the corresponding index in the rate array uint256 beginIndex = 0; for (uint256 i = 0; i < rewardRateLength; i++) { if (lastRewardUpdate < rewardRateArray[i].updatedTime) { beginIndex = i; break; } } // b. iterate to the latest-1 reward rate uint256 tempLastRewardUpdateTime = lastRewardUpdate; for (uint256 i = beginIndex; i < rewardRateLength; i++) { if(i == 0) continue; uint256 tempElapsedTime = rewardRateArray[i].updatedTime - tempLastRewardUpdateTime; uint256 tempReward = calculateReward( currentStakedAmount, rewardRateArray[i - 1].rewardRate, tempElapsedTime ); tempLastRewardUpdateTime = rewardRateArray[i].updatedTime; unchecked{ currentRewardAmount += tempReward; } } // c. the reward generated by the latest reward rate uint256 elapsedTime = block.timestamp - currentRewardRateState.updatedTime; uint256 reward = calculateReward( currentStakedAmount, currentRewardRateState.rewardRate, elapsedTime ); return currentRewardAmount + reward; } } // principal + rewards function getClaimableAssets(address _user, address _token) external view returns (uint256) { AssetsInfo memory assetsInfo = userAssetsInfo[_user][_token]; return Utils.Add(assetsInfo.stakedAmount, _getClaimableRewards(_user, _token)); } // current rewards function getClaimableRewards(address _user, address _token) external view returns (uint256) { return _getClaimableRewards(_user, _token); } // history rewards + current rewards function getTotalRewards(address _user, address _token) external view returns (uint256) { uint256 historyRewards = 0; uint256 currentRewards = _getClaimableRewards(_user, _token); AssetsInfo memory stakeInfo = userAssetsInfo[_user][_token]; for(uint256 i = 0; i < stakeInfo.claimHistory.length; i++) { historyRewards += stakeInfo.claimHistory[i].rewardAmount; } return Utils.Add(historyRewards, currentRewards); } // Calculate the total withdrawable amount for a user at a future time, // based on the user's current staked amount and the current reward rate. function getClaimableRewardsWithTargetTime( address _user, address _token, uint256 _targetTime ) external view returns (uint256) { require(_targetTime > block.timestamp, "Invalid time"); AssetsInfo memory assetsInfo = userAssetsInfo[_user][_token]; RewardRateState[] memory rewardRateArray = rewardRateState[_token]; RewardRateState memory currentRewardRateState = rewardRateArray[rewardRateArray.length - 1]; uint256 newAccumulatedReward = 0; if(assetsInfo.lastRewardUpdateTime != 0) { // not the first time to stake newAccumulatedReward = _getClaimableRewards(_user, _token); } uint256 elapsedTime = _targetTime - block.timestamp; uint256 reward = calculateReward( assetsInfo.stakedAmount, currentRewardRateState.rewardRate, elapsedTime ); return Utils.Add(newAccumulatedReward, reward); } function getStakedAmount(address _user, address _token) public view onlySupportedToken(_token) returns (uint256) { AssetsInfo memory stakeInfo = userAssetsInfo[_user][_token]; return stakeInfo.stakedAmount; } function getZKTokenAmount(address _user, address _token) public view onlySupportedToken(_token) returns (uint256) { return supportedTokenToZkToken[_token].balanceOf(_user); } function getContractBalance(address _token) public view returns (uint256) { Utils.CheckIsZeroAddress(_token); return IERC20(_token).balanceOf(address(this)); } function getStakeHistory( address _user, address _token, uint256 _index ) external view onlySupportedToken(_token) returns (StakeItem memory) { AssetsInfo memory stakeInfo = userAssetsInfo[_user][_token]; require(_index < stakeInfo.stakeHistory.length, "index"); return stakeInfo.stakeHistory[_index]; } function getClaimHistory( address _user, address _token, uint256 _index ) external view onlySupportedToken(_token) returns (ClaimItem memory) { AssetsInfo memory stakeInfo = userAssetsInfo[_user][_token]; require(_index < stakeInfo.claimHistory.length, "index"); return stakeInfo.claimHistory[_index]; } function getStakeHistoryLength(address _user, address _token) external view returns(uint256) { AssetsInfo memory stakeInfo = userAssetsInfo[_user][_token]; return stakeInfo.stakeHistory.length; } function getClaimHistoryLength(address _user, address _token) public view returns(uint256) { AssetsInfo memory stakeInfo = userAssetsInfo[_user][_token]; return stakeInfo.claimHistory.length; } // Check the current withdrawal request in progress for a specific user function getClaimQueueIDs(address _user, address _token) external view returns (uint256[] memory) { AssetsInfo memory assetsInfo = userAssetsInfo[_user][_token]; return assetsInfo.pendingClaimQueueIDs; } // Measure the reward rate as a percentage, and return the numerator and denominator function getCurrentRewardRate(address _token) external view returns (uint256, uint256) { RewardRateState[] memory rewardRateStateArray = rewardRateState[_token]; RewardRateState memory currentRewardRateState = rewardRateStateArray[rewardRateStateArray.length - 1]; return (currentRewardRateState.rewardRate, BASE); } function getClaimQueueInfo(uint256 _index) external view returns(ClaimItem memory) { return claimQueue[_index]; } function getTVL(address _token) external view returns(uint256){ return tvl[_token]; } receive() external payable { revert(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 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 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @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.encodeCall(token.transfer, (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.encodeCall(token.transferFrom, (from, to, 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. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @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. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @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 silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { bool private _paused; /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.28; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IzkToken is IERC20 { function mint(address to, uint256 amount) external; function burn(address from, uint256 amount) external; function setMinter(address minter, address vault) external; function updateAllowance(address from, address to, uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.28; interface IWithdrawVault { function transfer(address, address, uint256) external; function addSupportedToken(address) external; function setVault(address) external; function getSupportedTokens() external view returns (address[] memory); function getBalance(address) external view returns (uint256); function emergencyWithdraw(address, address, uint) external; function transferToCeffu(address token, uint amount)external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.28; // Main information: stake and claim struct AssetsInfo { uint256 stakedAmount; uint256 accumulatedReward; uint256 lastRewardUpdateTime; uint256[] pendingClaimQueueIDs; StakeItem[] stakeHistory; ClaimItem[] claimHistory; } struct StakeItem { address token; address user; uint256 amount; uint256 stakeTimestamp; } struct ClaimItem { bool isDone; address token; address user; uint256 totalAmount; uint256 principalAmount; uint256 rewardAmount; uint256 requestTime; uint256 claimTime; } interface IVault { ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// events /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// event Stake(address indexed _user, address indexed _token, uint256 indexed _amount); event RequestClaim(address _user, address indexed _token, uint256 indexed _amount, uint256 indexed _id); event ClaimAssets(address indexed _user, address indexed _token, uint256 indexed _amount, uint256 _id); event UpdateRewardRate(address _token, uint256 _oldRewardRate, uint256 _newRewardRate); event UpdateCeffu(address _oldCeffu, address _newCeffu); event UpdateStakeLimit(address indexed _token, uint256 _oldMinAmount, uint256 _oldMaxAmount, uint256 _newMinAmount, uint256 _newMaxAmount); event CeffuReceive(address indexed _token, address _ceffu, uint256 indexed _amount); event AddSupportedToken(address indexed _token, uint256 _minAmount, uint256 _maxAmount); event EmergencyWithdrawal(address indexed _token, address indexed _receiver); event UpdateWaitingTime(uint256 _oldWaitingTime, uint256 _newWaitingTIme); event ZkTokenCreated(address indexed _token); event FlashWithdraw(address indexed _user, address indexed _token, uint256 indexed _amount, uint _fee); event UpdatePenaltyRate(uint indexed oldRate, uint indexed newRate); event CancelClaim(address indexed user, address indexed _token, uint256 indexed _amount, uint256 _id); ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// write /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// function stake_66380860(address _token, uint256 _stakedAmount) external; function requestClaim_8135334(address _token, uint256 _amount) external returns(uint256); function cancelClaim(uint _queueId, address _token) external; function claim_41202704(uint256 _queueID, address token) external; function flashWithdrawWithPenalty(address _token, uint256 _amount) external; function sendLpTokens(address token, address to, uint amount, bool flag) external; function transferToCeffu(address _token, uint256 _amount) external; function emergencyWithdraw(address _token, address _receiver) external; ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// configuration /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// function addSupportedToken(address _token, uint256 _minAmount, uint256 _maxAmount, address _zkToken) external; function setRewardRate(address _token, uint256 _newRewardRate) external; function setPenaltyRate(uint256 _newRate) external; function setAirdropAddr(address newAirdropAddr) external; function setStakeLimit(address _token, uint256 _minAmount, uint256 _maxAmount) external; function setCeffu(address _newCeffu) external; function setWaitingTime(uint256 _newWaitingTIme) external; function pause() external; function unpause() external; ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// view / pure /// ///////////////////////////////////////////////////////////////////////////////////////////////////////// function convertToShares(uint tokenAmount, address _token) external view returns (uint256); function convertToAssets(uint shares, address _token) external view returns (uint256); function getClaimableRewardsWithTargetTime(address _user, address _token, uint256 _targetTime) external view returns (uint256); function getClaimableAssets(address _user, address _token) external view returns (uint256); function getClaimableRewards(address _user, address _token) external view returns (uint256); function getTotalRewards(address _user, address _token) external view returns (uint256); function getStakedAmount(address _user, address _token) external view returns (uint256); function getContractBalance(address _token) external view returns (uint256); function getStakeHistory(address _user, address _token, uint256 _index) external view returns (StakeItem memory); function getClaimHistory(address _user, address _token, uint256 _index) external view returns (ClaimItem memory); function getStakeHistoryLength(address _user, address _token) external view returns(uint256); function getClaimHistoryLength(address _user, address _token) external view returns(uint256); function getCurrentRewardRate(address _token) external view returns(uint256, uint256); function getClaimQueueInfo(uint256 _index) external view returns(ClaimItem memory); function getClaimQueueIDs(address _user, address _token) external view returns(uint256[] memory); function getTVL(address _token) external view returns(uint256); function getZKTokenAmount(address _user, address _token) external view returns(uint256); function lastClaimQueueID() external view returns(uint256); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.28; library Utils { // Use this when we are certain that an overflow will not occur function Add(uint _a, uint _b) public pure returns (uint256) { assembly { mstore(0x0, add(_a, _b)) return(0x0, 32) } } function CheckIsZeroAddress(address _address) public pure returns (bool) { assembly { if iszero(_address) { mstore(0x00, 0x20) mstore(0x20, 0x0c) mstore(0x40, 0x5a65726f20416464726573730000000000000000000000000000000000000000) // load hex of "Zero Address" to memory revert(0x00, 0x60) } } return true; } function MustGreaterThanZero(uint256 _value) internal pure returns (bool result) { assembly { // The 'iszero' opcode returns 1 if the input is zero, and 0 otherwise. // So, 'iszero(iszero(_value))' returns 1 if value > 0, and 0 if value == 0. result := iszero(iszero(_value)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) 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 assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "@openzeppelin/=lib/openzeppelin-contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 20 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": { "src/utils.sol": { "Utils": "0x8724d1B62DDf87D830811C9DCB2E1a6494C9c117" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address[]","name":"_zkTokens","type":"address[]"},{"internalType":"uint256[]","name":"_newRewardRate","type":"uint256[]"},{"internalType":"uint256[]","name":"_minStakeAmount","type":"uint256[]"},{"internalType":"uint256[]","name":"_maxStakeAmount","type":"uint256[]"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_bot","type":"address"},{"internalType":"address","name":"_ceffu","type":"address"},{"internalType":"uint256","name":"_waitingTime","type":"uint256"},{"internalType":"address payable","name":"withdrawVaultAddress","type":"address"},{"internalType":"address","name":"_airdropAddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_minAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_maxAmount","type":"uint256"}],"name":"AddSupportedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_id","type":"uint256"}],"name":"CancelClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"oldStatus","type":"bool"},{"indexed":true,"internalType":"bool","name":"newStatus","type":"bool"}],"name":"CancelStatusChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"address","name":"_ceffu","type":"address"},{"indexed":true,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"CeffuReceive","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_id","type":"uint256"}],"name":"ClaimAssets","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"address","name":"_receiver","type":"address"}],"name":"EmergencyWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"oldStatus","type":"bool"},{"indexed":true,"internalType":"bool","name":"newStatus","type":"bool"}],"name":"FlashStatusChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"FlashWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_id","type":"uint256"}],"name":"RequestClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldCeffu","type":"address"},{"indexed":false,"internalType":"address","name":"_newCeffu","type":"address"}],"name":"UpdateCeffu","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldRate","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"UpdatePenaltyRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_oldRewardRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newRewardRate","type":"uint256"}],"name":"UpdateRewardRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_oldMinAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_oldMaxAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMinAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMaxAmount","type":"uint256"}],"name":"UpdateStakeLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldWaitingTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newWaitingTIme","type":"uint256"}],"name":"UpdateWaitingTime","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"}],"name":"ZkTokenCreated","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WAITING_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_minAmount","type":"uint256"},{"internalType":"uint256","name":"_maxAmount","type":"uint256"},{"internalType":"address","name":"_zkToken","type":"address"}],"name":"addSupportedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_queueId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"cancelClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_queueID","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"claim_41202704","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"flashWithdrawWithPenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getClaimHistory","outputs":[{"components":[{"internalType":"bool","name":"isDone","type":"bool"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"principalAmount","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"uint256","name":"requestTime","type":"uint256"},{"internalType":"uint256","name":"claimTime","type":"uint256"}],"internalType":"struct ClaimItem","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getClaimHistoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getClaimQueueIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getClaimQueueInfo","outputs":[{"components":[{"internalType":"bool","name":"isDone","type":"bool"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"principalAmount","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"uint256","name":"requestTime","type":"uint256"},{"internalType":"uint256","name":"claimTime","type":"uint256"}],"internalType":"struct ClaimItem","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getClaimableAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getClaimableRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_targetTime","type":"uint256"}],"name":"getClaimableRewardsWithTargetTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getContractBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getCurrentRewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getStakeHistory","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakeTimestamp","type":"uint256"}],"internalType":"struct StakeItem","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getStakeHistoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getStakedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getTVL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getTotalRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getZKTokenAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastClaimQueueID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxStakeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minStakeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"requestClaim_8135334","outputs":[{"internalType":"uint256","name":"_returnID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"flag","type":"bool"}],"name":"sendLpTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAirdropAddr","type":"address"}],"name":"setAirdropAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enable","type":"bool"}],"name":"setCancelEnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newCeffu","type":"address"}],"name":"setCeffu","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enable","type":"bool"}],"name":"setFlashEnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"setPenaltyRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_newRewardRate","type":"uint256"}],"name":"setRewardRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_minAmount","type":"uint256"},{"internalType":"uint256","name":"_maxAmount","type":"uint256"}],"name":"setStakeLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newWaitingTime","type":"uint256"}],"name":"setWaitingTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_stakedAmount","type":"uint256"}],"name":"stake_66380860","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedTokenToZkToken","outputs":[{"internalType":"contract IzkToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalRewardsAmountByToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalStakeAmountByToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferOrTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferToCeffu","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"zkTokenToSupportedToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608080604052346105c457615900803803809161001c8285610658565b83398101610160828203126105c45781516001600160401b0381116105c457816100479184016106a6565b60208301519091906001600160401b0381116105c457816100699185016106a6565b60408401519092906001600160401b0381116105c4578261008b91860161070b565b60608501519093906001600160401b0381116105c457836100ad91870161070b565b608086015190936001600160401b0382116105c4576100cd91870161070b565b926100da60a08701610692565b936100e760c08801610692565b6100f360e08901610692565b6101008901516101208a01516001600160a01b0381169a908b90036105c45761014061011f9101610692565b6000805460ff191690556127106006556032600b556014805460ff60a81b1916600160a81b17905560405163092d4e2760e21b81526001600160a01b039093166004840181905292738724d1b62ddf87d830811c9dcb2e1a6494c9c11790602081602481855af480156106145761063b575b5060405163092d4e2760e21b81526001600160a01b038b16600482015290602082602481845af490811561061457602492602092610620575b5060405163092d4e2760e21b81526001600160a01b038816600482015292839182905af48015610614576105e7575b50601480546001600160a01b0319166001600160a01b039290921691909117905586519788156105c45789518914806105dd575b806105d3575b806105c9575b156105c457604080936102a17fe4200d45d2a3d89971b73afef9feb38c84ba9c3a34c7a5d971392dbd399692299661029b856102957f2181541ed844bb663fa1c189300cc64ee66517f8346ea79c074cf61c782f0ed397610794565b50610810565b506108a8565b50600a80546001600160a01b031916821790558151600081526020810191909152a180600e55815190600082526020820152a14260125560005b85811061035457601380546001600160a01b0319168917905560005460ff81166103435760019060ff1916176000557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1604051614f3f90816109418239f35b63d93c066560e01b60005260046000fd5b61035e8184610780565b516103698284610780565b5111156105c4576001600160a01b036103828287610780565b51169061038f8185610780565b5182600052600c6020526040600020556103a98184610780565b5182600052600d6020526040600020558160005260036020526040600020600160ff19825416179055817fd9fe4a232fa59fb866233bcdccaf84797cdd30506e8fc261699d4daaff18e4cd60406104008488610780565b5161040b8588610780565b5182519182526020820152a26001600160a01b036104298287610780565b5116826000526004602052604060002060018060a01b03821660018060a01b0319825416179055806000526005602052604060002060018060a01b03841660018060a01b03198254161790557fb2d8bbd38e8da68edecef6590f2c4977823a30e753091a7822bf5229ebd71977600080a26104a48189610780565b51604051909290606081016001600160401b038111828210176105ae576040528181526020810193845260408101428152826000526009602052604060002090815495680100000000000000008710156105ae5760018701808455871015610598576001966002936000526003602060002091020193878060a01b0390888060a01b0390511616878060a01b03198554161784555186840155519101557f37709c0c7a143f7f128833da302459d5478d74b7775d223b5f77553310a221de606061056e848c610780565b5160405190848252600060208301526040820152a1600052601060205242604060002055016102db565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600080fd5b5086518914610239565b5084518914610233565b508551891461022d565b6106089060203d60201161060d575b6106008183610658565b810190610768565b6101f9565b503d6105f6565b6040513d6000823e3d90fd5b61063690833d851161060d576106008183610658565b6101ca565b6106539060203d60201161060d576106008183610658565b610191565b601f909101601f19168101906001600160401b038211908210176105ae57604052565b6001600160401b0381116105ae5760051b60200190565b51906001600160a01b03821682036105c457565b9080601f830112156105c45781516106bd8161067b565b926106cb6040519485610658565b81845260208085019260051b8201019283116105c457602001905b8282106106f35750505090565b6020809161070084610692565b8152019101906106e6565b9080601f830112156105c45781516107228161067b565b926107306040519485610658565b81845260208085019260051b8201019283116105c457602001905b8282106107585750505090565b815181526020918201910161074b565b908160209103126105c4575180151581036105c45790565b80518210156105985760209160051b010190565b6001600160a01b03811660009081526000805160206158a0833981519152602052604090205460ff1661080a576001600160a01b031660008181526000805160206158a083398151915260205260408120805460ff191660011790553391906000805160206158808339815191528180a4600190565b50600090565b6001600160a01b03811660009081526000805160206158e0833981519152602052604090205460ff1661080a576001600160a01b031660008181526000805160206158e083398151915260205260408120805460ff191660011790553391907f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a906000805160206158808339815191529080a4600190565b6001600160a01b03811660009081526000805160206158c0833981519152602052604090205460ff1661080a576001600160a01b031660008181526000805160206158c083398151915260205260408120805460ff191660011790553391907f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b906000805160206158808339815191529080a460019056fe60806040526004361015610013575b600080fd5b6000803560e01c80604e14613af4578060ed1461379b57806301ffc9a71461374457806304d3a96d146132245780630db14e95146130925780630e155c9514612faf5780630f40517a14612f765780631a9be40a14612d81578063209302ca14612d545780632169678314612a7a578063248a9ca314612a5b578063251d6ec314612a225780632d4abd2d146128b35780632f2ff15d1461288157806332cf58c41461267f578063361032911461255857806336568abe1461251357806339de62a6146124975780633a33a4f8146122ec5780633f4ba83a14612286578063429f30501461202357806343ab265f14611fff57806346891db714611e1757806348d832cb14611d3c5780634d2b144414611d1e5780634f8fe1f114611ca25780635c975abb14611c805780636382d9ad14611b0557806366fd9d651461170757806368c4ac26146116c85780636c0a188e146116aa5780637c395b131461150e578063812a71d5146112a15780638456cb59146112485780638d34a9ed146110fb57806391d14854146110af578063920c28f31461106e57806394af69aa14610e1757806395d322b014610dde5780639ed9e48314610c6f578063a1bab44714610c03578063a217fddf14610be7578063abd4292214610ba3578063b883d89c14610b5e578063cb0b8fe514610b25578063cfb66ab114610ae4578063d295fa9a146109a0578063d547741f14610965578063da57c7d71461077e578063e30227ea1461069e578063e315d80414610665578063ebc73e6514610604578063f56f4f0f146105cf5763f7192ba81461026a57600080fd5b346105cc5760403660031901126105cc5760043561028661402a565b9061028f61476d565b60ff60145460a81c1661058d5780835260076020526102b0604084206143ae565b818452600760205283600660408220828155826001820155826002820155826003820155826004820155826005820155015560018060a01b03602082015116903385526008602052604080862060009060018060a01b03851682526020522033865260086020526040862060018060a01b03841660005260205261033a600360406000200161434a565b94606083015115610589576040830151336001600160a01b03909116036105895761036683511561455f565b6001600160a01b0381169361037c908514614595565b865b865181101561057a5785610392828961444b565b51146103a05760010161037e565b909192939495805190600019820191821161056657916103f26103ca6103f793610435969561444b565b516103d96003880193846141cc565b90919082549060031b91821b91600019901b1916179055565b6145cf565b60a060808501519401519261040d858254614290565b81556001810161041e858254614290565b9055600242910155610430813361478a565b614811565b61043f8284614290565b670de0b6b3a7640000810290808204670de0b6b3a7640000149015171561055257869161046b91614230565b848252600f60205260408220610482858254614290565b905584825260116020526040822061049b848254614290565b9055848252600460205260408220546001600160a01b0316803b1561054e576040516340c10f1960e01b815291839183918290849082906104e0903360048401614250565b03925af180156105435761052a575b50506104fa91614290565b916040519081527f16a8ebcbce0c773c9fc99b0335c37c4f8128bb11da6e765f86f0aa66c6735b1860203392a480f35b81610534916141ab565b61053f5784386104ef565b8480fd5b6040513d84823e3d90fd5b8280fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b506104359192939495506103f7565b8680fd5b60405162461bcd60e51b815260206004820152601760248201527663616e63656c20636c61696d206e6f7420656e61626c6560481b6044820152606490fd5b80fd5b50346105cc5760403660031901126105cc5760206105fc6105ee614014565b6105f661402a565b90614a2f565b604051908152f35b50346105cc5760203660031901126105cc5760043561062161492d565b7fe4200d45d2a3d89971b73afef9feb38c84ba9c3a34c7a5d971392dbd399692296040600e5461065381851415614737565b8151908152836020820152a1600e5580f35b50346105cc5760203660031901126105cc576020906040906001600160a01b0361068d614014565b168152601183522054604051908152f35b50346105cc5760203660031901126105cc576001600160a01b036106c0614014565b16815260096020526040812080546106d781614397565b916106e560405193846141ab565b81835283526020808420849184015b838310610740578585805191600019830192831161072c576040602061071a858561444b565b51015181519081526127106020820152f35b634e487b7160e01b81526011600452602490fd5b6003602060019260405161075381614190565b848060a01b0386541681528486015483820152600286015460408201528152019201920191906106f4565b50346105cc57604061078f36614040565b9291846060845161079f81614128565b8281528260208201528286820152015260018060a01b038216855260036020526107ce60ff84872054166140ee565b6001600160a01b03908116855260086020908152838620929091166000908152919052206040516107fe81614175565b8154815260018201546020820152600282015460408201526108226003830161434a565b60608201526004820191825461083781614397565b9361084560405195866141ab565b81855286526020808720879186015b8383106109105750505050600590608083019384520190815461087681614397565b9261088460405194856141ab565b81845286526020808720969084015b8282106108f25760806108ba88888860a08901526108b48151518310614703565b5161444b565b5160606040519160018060a01b03815116835260018060a01b0360208201511660208401526040810151604084015201516060820152f35b600760206001926109028b6143ae565b815201980191019096610893565b6004602060019260409b989b5161092681614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190979497610854565b50346105cc5760403660031901126105cc5761099c60043561098561402a565b906109976109928261450d565b6149f2565b614e28565b5080f35b50346105cc5760403660031901126105cc5760043560046109bf61402a565b6001600160a01b03818116808652602084815260408088205490516318160ddd60e01b81529592939192869290918391165afa928315610ad9578593610aa5575b508452600f602052610a1760408520549130614a2f565b82610a5757505050670de0b6b3a7640000915b670de0b6b3a7640000820291808304670de0b6b3a7640000149015171561072c5760206105fc8484614230565b610a6091614290565b670de0b6b3a7640000810290808204670de0b6b3a76400001490151715610a915790610a8b91614230565b91610a2a565b634e487b7160e01b84526011600452602484fd5b9092506020813d602011610ad1575b81610ac1602093836141ab565b8101031261000e57519138610a00565b3d9150610ab4565b6040513d87823e3d90fd5b50346105cc5760203660031901126105cc576020906001600160a01b03610b09614014565b16815260048252604060018060a01b0391205416604051908152f35b50346105cc5760203660031901126105cc576020906040906001600160a01b03610b4d614014565b168152600f83522054604051908152f35b50346105cc5760203660031901126105cc57610b78614014565b610b8061492d565b601480546001600160a01b0319166001600160a01b039290921691909117905580f35b50346105cc5760203660031901126105cc57610bd76040610be392610bc66146c6565b5060043581526007602052206143ae565b60405191829182614089565b0390f35b50346105cc57806003193601126105cc57602090604051908152f35b50346105cc5760203660031901126105cc57600435610c2061492d565b61271081111580610c63575b610c3590614737565b80600b547f2841fef93624d9d474e38055eb5f9d3a6a8c9fdf078b6790af293d5d31225e108480a3600b5580f35b50600b54811415610c2c565b50346105cc5760403660031901126105cc576040610c8b614014565b610c9361402a565b6001600160a01b0391821684526008602090815283852091909216600090815291522060405191610cc383614175565b815483526001820154602084015260028201546040840152610ce76003830161434a565b606084015260048201918254610cfc81614397565b93610d0a60405195866141ab565b81855283526020808420849186015b838310610d8f575050505060808401928352600501805490610d3a82614397565b92610d4860405194856141ab565b82845290815260208082209084015b838310610d71576020868660a08a01525151604051908152f35b60076020600192610d81856143ae565b815201920192019190610d57565b60046020600192604051610da281614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190610d19565b50346105cc5760203660031901126105cc576020906040906001600160a01b03610e06614014565b168152600c83522054604051908152f35b50346105cc5760803660031901126105cc57610e31614014565b6064356001600160a01b0381169190604435906024359084900361053f57610e5761492d565b60405163092d4e2760e21b81526001600160a01b039093166004840181905292602081602481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af4801561106357611036575b50828552600360205260ff60408620541661100557828552600360205260408520805460ff19166001179055610ed361492d565b8285526003602052610eeb60ff6040872054166140ee565b80151580610ffc575b1561053f5760407fd9fe4a232fa59fb866233bcdccaf84797cdd30506e8fc261699d4daaff18e4cd918493848852600c602052847fe4b65af790442ef39b02e91f9b1e0caf05cb7e3607b3525b51b8d26dc27383826080858b2054838c52600d602052868c2054875191825260208201528587820152846060820152a2848852600c6020528183892055848852600d602052808389205582519182526020820152a280835260046020908152604080852080546001600160a01b03199081166001600160a01b0387161790915584865260059092528420805490911690911790557fb2d8bbd38e8da68edecef6590f2c4977823a30e753091a7822bf5229ebd719778280a280f35b50818110610ef4565b60405162461bcd60e51b815260206004820152600960248201526814dd5c1c1bdc9d195960ba1b6044820152606490fd5b6110579060203d60201161105c575b61104f81836141ab565b810190614419565b610e9f565b503d611045565b6040513d88823e3d90fd5b50346105cc5760203660031901126105cc576020906001600160a01b03611093614014565b16815260058252604060018060a01b0391205416604051908152f35b50346105cc5760403660031901126105cc5760406110cb61402a565b9160043581526001602052209060018060a01b0316600052602052602060ff604060002054166040519015158152f35b50346105cc5760803660031901126105cc57611115614014565b61111d61402a565b90604435916064359081151580920361053f576014546001600160a01b031692338490036112445761118960208660018060a01b03841696878a5260048352858a60018060a01b0360408220541692604051968795869485936323b872dd60e01b85526004850161460e565b03925af180156112395761121c575b506001600160a01b03821686526008602090815260408088206000878152925290209260010361120e57505060125460028201555b6111d8838254614290565b9055808352600f602052604083206111f1838254614290565b90558252600260205261120960408320918254614290565b905580f35b6112179161478a565b6111cd565b6112349060203d60201161105c5761104f81836141ab565b611198565b6040513d89823e3d90fd5b8580fd5b50346105cc57806003193601126105cc57611261614980565b61126961476d565b600160ff198254161781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b50346105cc5760403660031901126105cc576112bb614014565b6001600160a01b031680825260036020526040822054602435906112e19060ff166140ee565b6112e961492d565b6127108110156114da57818352600960205260408320805461130a81614397565b9161131860405193846141ab565b81835285526020808620869184015b83831061149c575050505080519060001982019182116114885760209161134d9161444b565b510151818114158061147f575b156114475760405161136b81614190565b838152602081018381526040820190428252858752600960205260408720805490600160401b821015611433576001820180825582101561141f57885260208089209451600390920290940180546001600160a01b0319166001600160a01b03929092169190911781559051600182015590516002919091015560408051948552908401919091528201527f37709c0c7a143f7f128833da302459d5478d74b7775d223b5f77553310a221de90606090a180f35b634e487b7160e01b89526032600452602489fd5b634e487b7160e01b89526041600452602489fd5b60405162461bcd60e51b815260206004820152601060248201526f496e76616c6964206e6577207261746560801b6044820152606490fd5b5081151561135a565b634e487b7160e01b85526011600452602485fd5b600360206001926040516114af81614190565b848060a01b038654168152848601548382015260028601546040820152815201920192019190611327565b60405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964207261746560a01b6044820152606490fd5b50346105cc5760409061152036614040565b939161152a6146c6565b506001600160a01b038216845260036020528284205461154c9060ff166140ee565b6001600160a01b03908116845260086020908152838520929091166000908152919052206040519061157d82614175565b8054825260018101546020830152600281015460408301526115a16003820161434a565b60608301526004810180546115b581614397565b916115c360405193846141ab565b81835285526020808620869184015b83831061165b575050505060808301526005018054906115f182614397565b936115ff60405195866141ab565b82855290815260208082209085015b83831061163d57610be361163088886108b460a08a0191808352518310614703565b5160405191829182614089565b6007602060019261164d856143ae565b81520192019201919061160e565b6004602060019260405161166e81614128565b848060a01b038654168152848060a01b0385870154168382015260028601546040820152600386015460608201528152019201920191906115d2565b50346105cc57806003193601126105cc576020600654604051908152f35b50346105cc5760203660031901126105cc5760209060ff906040906001600160a01b036116f3614014565b168152600384522054166040519015158152f35b50346105cc5760803660031901126105cc57611721614014565b61172961402a565b6044356001600160a01b038116919082810361053f57606435906001600160a01b03831690848214611ac0578215611a7b57611765868561445f565b93838510611a4c57338314611a0b5760018060a01b038716808952600460205260018060a01b0360408a20541660206040518092636eb1769f60e11b825281806117b3338960048401614431565b03915afa8015611a005786918b916119cb575b501061199a578089526004602052604089205489906001600160a01b0316803b1561199657816040518092630f75ba2160e41b825281838161180d8d338c6004850161460e565b03925af180156105435761197d575b5052600460205260018060a01b0360408920541691602060405180946323b872dd60e01b8252818c816118548b888a6004850161460e565b03925af1928315611972578880936118759261187a96611953575b5061478a565b61478a565b85526008602052604080862060009060018060a01b03871682526020522091825491604060018501968754968952600860205281892060009160018060a01b031682526020522096670de0b6b3a76400008202918204670de0b6b3a76400000361072c5750611910611940959493670de0b6b3a7640000611909611902611926968396614230565b809361421d565b049561421d565b049261191d818854614290565b875582546141fa565b905560018401611937828254614290565b905582546141fa565b9055600242910155602060405160018152f35b61196b9060203d60201161105c5761104f81836141ab565b503861186f565b6040513d8b823e3d90fd5b81611987916141ab565b61199257883861181c565b8880fd5b5080fd5b60405162461bcd60e51b8152602060048201526009602482015268616c6c6f77616e636560b81b6044820152606490fd5b9150506020813d6020116119f8575b816119e7602093836141ab565b8101031261000e57859051386117c6565b3d91506119da565b6040513d8c823e3d90fd5b60018060a01b0387168852600460205260018060a01b0360408920541691602060405180946323b872dd60e01b8252818c816118548b88336004850161460e565b60405162461bcd60e51b815260206004820152600760248201526662616c616e636560c81b6044820152606490fd5b60405162461bcd60e51b815260206004820152601d60248201527f616d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606490fd5b60405162461bcd60e51b815260206004820152601e60248201527f66726f6d2063616e206e6f742062652073616d652061732074686520746f00006044820152606490fd5b50346105cc5760403660031901126105cc57611b1f614014565b611b2761402a565b90611b3061492d565b60405163092d4e2760e21b81526001600160a01b0390911660048201819052738724d1b62ddf87d830811c9dcb2e1a6494c9c117929091602081602481875af48015610ad957611c63575b5060405163092d4e2760e21b81526001600160a01b0382166004820181905293602090829060249082905af48015610ad957611c46575b506040516370a0823160e01b815230600482015290602082602481865afa908115610ad9578591611c10575b611be99250836148f3565b7ff5b6d8b404f034718f55a370884db03c4e27e9652e2636d4adcd0540d7c4203f8380a380f35b90506020823d602011611c3e575b81611c2b602093836141ab565b8101031261000e57611be9915190611bde565b3d9150611c1e565b611c5e9060203d60201161105c5761104f81836141ab565b611bb2565b611c7b9060203d60201161105c5761104f81836141ab565b611b7b565b50346105cc57806003193601126105cc5760ff60209154166040519015158152f35b50346105cc5760203660031901126105cc57611cbc61407a565b611cc461492d565b6014549060ff8260a81c16151590151591611ce182841415614521565b60ff60a81b191660a883901b60ff60a81b16176014557f84e3667aff0d15c7464eb61e79d9db356389b19a3a5024099a09272a7bf11ce98380a380f35b50346105cc57806003193601126105cc576020600e54604051908152f35b50346105cc5760603660031901126105cc57611d56614014565b60243560443591611d6561492d565b6001600160a01b031680845260036020526040842054909190611d8a9060ff166140ee565b80151580611e0e575b15611e0a57818452600c602052817fe4b65af790442ef39b02e91f9b1e0caf05cb7e3607b3525b51b8d26dc273838260806040872054838852600d60205260408820546040519182526020820152846040820152866060820152a2818452600c60205260408420558252600d602052604082205580f35b8380fd5b50828110611d93565b50346105cc5760403660031901126105cc57611e31614014565b6001600160a01b0316808252600360205260408220546024359190611e589060ff166140ee565b7f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b8352600160209081526040808520336000908152925290205460ff1615611fc8578115611f98576040516370a0823160e01b8152306004820152602081602481855afa908115611f8d578491611f5b575b508211611f2157600a54611ee99083906001600160a01b0316836148f3565b7f4df7f50f630ac07eef038205b5b9c0c910ce8498aa925abbfcb0e1e674058aa9602060018060a01b03600a5416604051908152a380f35b60405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606490fd5b90506020813d602011611f85575b81611f76602093836141ab565b8101031261000e575138611eca565b3d9150611f69565b6040513d86823e3d90fd5b60405162461bcd60e51b815260206004820152600860248201526706d757374203e20360c41b6044820152606490fd5b63e2517d3f60e01b8352336004527f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b602452604483fd5b50346105cc5760203660031901126105cc5760206105fc61201e614014565b614630565b50346105cc5760403660031901126105cc5760043561204061402a565b9061204961476d565b808352600760205261205d604084206143ae565b60208181015133808752600880845260408089206001600160a01b039094166000818152948652818520938a529185528089208285529094529290912090949192906120ab9060030161434a565b9460608201928351156122825760e08301514210612282576040830151336001600160a01b0390911603612282576120f8906120e884511561455f565b6001600160a01b03168514614595565b848752600760205260408720805460ff19166001179055865b86518110156122715785612125828961444b565b511461213357600101612111565b9091929394958051906000198201918211610566576005926103f26121606121dc97969461216f9461444b565b516103d96003860193846141cc565b60808301928351878a52600260205261218d60408b209182546141fa565b9055855193519060c060a082015191015191604051956121ac87614159565b600187528960208801523360408801526060870152608086015260a085015260c08401524260e08401520161429d565b601354815185916001600160a01b0316803b1561054e576040516317d5759960e31b8152918391839182908490829061221a90338c6004850161460e565b03925af180156105435761225c575b505051916040519081527fdddf48d4d866b99b4e98ab4756d69715555f0445680fe5941715d094c362c0fd60203392a480f35b81612266916141ab565b611e0a578338612229565b506121dc929394955060059061216f565b8780fd5b50346105cc57806003193601126105cc5761229f614980565b805460ff8116156122dd5760ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a180f35b638dfc202b60e01b8252600482fd5b50346105cc5760403660031901126105cc576040612308614014565b61231061402a565b6001600160a01b0391821684526008602090815283852091909216600090815291522060405161233f81614175565b8154815260018201546020820152600282015460408201526123636003830161434a565b916060820192835260048101805461237a81614397565b9161238860405193846141ab565b81835286526020808720879184015b8383106124485750505050906005916080840152019081546123b881614397565b926123c660405194856141ab565b81845285526020808620869185015b83831061242a575050505060a001525190604051918291602083016020845282518091526020604085019301915b818110612411575050500390f35b8251845285945060209384019390920191600101612403565b6007602060019261243a856143ae565b8152019201920191906123d5565b6004602060019260405161245b81614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190612397565b50346105cc5760203660031901126105cc576124b161407a565b6124b961492d565b6014549060ff8260a01c161515901515916124d682841415614521565b60ff60a01b191660a083901b60ff60a01b16176014557f99859612a8514731da8547a1b97ab4654097e36c13fe2c98960ecd00f770747b8380a380f35b50346105cc5760403660031901126105cc5761252d61402a565b336001600160a01b038216036125495761099c90600435614e28565b63334bd91960e11b8252600482fd5b50346105cc5760403660031901126105cc5760049061257561402a565b6001600160a01b03818116808452602085815260408086205490516318160ddd60e01b81529692939192879290918391165afa938415612674578394612640575b508252600f6020526125cd60408320549130614a2f565b836125f757505050506020670de0b6b3a76400006125ee815b60043561421d565b04604051908152f35b61260091614290565b90670de0b6b3a7640000820291808304670de0b6b3a7640000149015171561072c57506125ee61263b602093670de0b6b3a764000093614230565b6125e6565b9093506020813d60201161266c575b8161265c602093836141ab565b8101031261000e575192386125b6565b3d915061264f565b6040513d85823e3d90fd5b50346105cc5760403660031901126105cc57612699614014565b6126a161402a565b9160018060a01b03821681526008602052604080822060009060018060a01b03861682526020522092604051936126d785614175565b8054855260018101546020860152600281015460408601526126fb6003820161434a565b606086015260048101805461270f81614397565b9161271d60405193846141ab565b81835285526020808620869184015b83831061283257505050509060059160808701520193845461274d81614397565b9061275b60405192836141ab565b80825260208201968552602085209685905b8282106128145750505060a082015251926127889190614a2f565b60405192637afbe4f160e01b845260048401526024830152602082604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af490811561280857906127d5575b602090604051908152f35b506020813d602011612800575b816127ef602093836141ab565b8101031261000e57602090516127ca565b3d91506127e2565b604051903d90823e3d90fd5b600760206001926128248c6143ae565b81520199019101909761276d565b6004602060019260405161284581614128565b848060a01b038654168152848060a01b03858701541683820152600286015460408201526003860154606082015281520192019201919061272c565b50346105cc5760403660031901126105cc5761099c6004356128a161402a565b906128ae6109928261450d565b614d99565b50346105cc5760403660031901126105cc5760406128cf614014565b6128d761402a565b6001600160a01b03918216845260086020908152838520919092166000908152915220604051909161290882614175565b82548252600183015460208301526002830154604083015261292c6003840161434a565b60608301526004830192835461294181614397565b9061294f60405192836141ab565b80825260208201958452602084209584905b8282106129d357505050608084015260050180549061297f82614397565b9261298d60405194856141ab565b82845290815260208082209084015b8383106129b5576020858060a089015251604051908152f35b600760206001926129c5856143ae565b81520192019201919061299c565b600460206001926040516129e681614128565b848060a01b038c54168152848060a01b03858d0154168382015260028c0154604082015260038c01546060820152815201980191019096612961565b50346105cc5760203660031901126105cc576020906040906001600160a01b03612a4a614014565b168152600d83522054604051908152f35b50346105cc5760203660031901126105cc5760206105fc60043561450d565b50346105cc57612a8936614040565b929042841115612d205760018060a01b03831682526008602052604080832060009060018060a01b0384168252602052209260405191612ac883614175565b845483526001850154602084015260028501549460408401958652612aef6003820161434a565b6060850152600481018054612b0381614397565b91612b1160405193846141ab565b81835287526020808820889184015b838310612cd1575050505060808501526005018054612b3e81614397565b91612b4c60405193846141ab565b81835286526020808720879184015b838310612cb3575050505060a08401526001600160a01b03811684526009602052604084208054612b8b81614397565b91612b9960405193846141ab565b81835286526020808720879184015b838310612c7557505050508051906000198201918211612c615790612bcc9161444b565b5191849551612c41575b50506020612bed644979cb9e0094959642906141fa565b925191015102020460405192637afbe4f160e01b845260048401526024830152602082604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af490811561280857906127d557602090604051908152f35b644979cb9e00949550612c59602092612bed92614a2f565b959450612bd6565b634e487b7160e01b86526011600452602486fd5b60036020600192604051612c8881614190565b848060a01b038654168152848601548382015260028601546040820152815201920192019190612ba8565b60076020600192612cc3856143ae565b815201920192019190612b5b565b60046020600192604051612ce481614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190612b20565b60405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b6044820152606490fd5b50346105cc5760403660031901126105cc5760206105fc612d73614014565b612d7b61402a565b9061445f565b50346105cc5760403660031901126105cc57612d9b614014565b90612da461402a565b9160408293612db38184614a2f565b6001600160a01b0393841685526008602090815283862092909416600090815291909352206040519290612de684614175565b805484526001810154602085015260028101546040850152612e0a6003820161434a565b6060850152600481018054612e1e81614397565b91612e2c60405193846141ab565b81835284526020808520859184015b838310612f27575050505090600591608086015201928354612e5c81614397565b94612e6a60405196876141ab565b81865283526020808420849187015b838310612f09575050505060a00192835280935b83518051861015612ebb5760019160a0612eaa88612eb39461444b565b51015190614290565b940193612e8d565b509160405192637afbe4f160e01b845260048401526024830152602082604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af490811561280857906127d557602090604051908152f35b60076020600192612f19856143ae565b815201920192019190612e79565b60046020600192604051612f3a81614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190612e3b565b50346105cc5760203660031901126105cc576020906040906001600160a01b03612f9e614014565b168152600283522054604051908152f35b50346105cc5760203660031901126105cc57612fc9614014565b612fd161492d565b60405163092d4e2760e21b81526001600160a01b038216600482018190529190602081602481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af48015611f8d57613075575b50600a54906001600160a01b0382169083821461053f577f2181541ed844bb663fa1c189300cc64ee66517f8346ea79c074cf61c782f0ed39161306160405192839283614431565b0390a16001600160a01b03191617600a5580f35b61308d9060203d60201161105c5761104f81836141ab565b613019565b50346105cc5760403660031901126105cc5760406130ae614014565b6130b661402a565b6001600160a01b03811684526003602052828420549091906130da9060ff166140ee565b60018060a01b03168352600860205281832060009160018060a01b03168252602052209060405161310a81614175565b82548152600183015460208201526002830154604082015261312e6003840161434a565b60608201526004830192835461314381614397565b9061315160405192836141ab565b80825260208201958552602085209585905b8282106131d557505050608083015260050180549061318182614397565b9361318f60405195866141ab565b82855290815260208082209085015b8383106131b7576020858760a082015251604051908152f35b600760206001926131c7856143ae565b81520192019201919061319e565b600460206001926040516131e881614128565b848060a01b038c54168152848060a01b03858d0154168382015260028c0154604082015260038c01546060820152815201980191019096613163565b50346105cc5760403660031901126105cc5761323e614014565b6001600160a01b0381168083526003602052604083205460243592906132669060ff166140ee565b61326e61476d565b60ff60145460a01c1661370357338452600860205260408085206000908482526020522061329c823361478a565b6132a582614811565b81549160018101928354908715159182613662575b50501561058957600654875260076020528254958781600019810361361d5750505086815460405190637afbe4f160e01b82528860048301526024820152602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af49081156105435782916135e8575b509693558054918782555b86156135ab57858852600f6020526040882061334b8482546141fa565b90558588526011602052604088206133648582546141fa565b9055670de0b6b3a76400008702878104670de0b6b3a76400000361056657889161338d91614230565b86825260046020526024602060018060a01b03604085205416604051928380926370a0823160e01b82523360048301525afa908115612674578391613576575b50808211801561356d575b613565575b50868252600460205260408220546001600160a01b0316803b1561054e57604051632770a7eb60e21b81529183918391829084908290613421903360048401614250565b03925af1801561054357613550575b5050600b5461271003612710811161353c5761344f612710918861421d565b04908161346561345f828a6141fa565b96614630565b10613502576134d39361347b60059333896148f3565b8689526002602052604089206134928582546141fa565b9055604051936134a185614159565b60018552876020860152336040860152886060860152608085015260a08401524260c08401524260e08401520161429d565b6040519081527febb065a01aeb84b2b8d3adb2f31a9b004b8ddaba2a4f702240f6f569e49855be60203392a480f35b60405162461bcd60e51b81526020600482015260126024820152716e6f7420656e6f7567682062616c616e636560701b6044820152606490fd5b634e487b7160e01b88526011600452602488fd5b8161355a916141ab565b610589578638613430565b9050386133dd565b508354156133d8565b9250506020823d6020116135a3575b81613592602093836141ab565b8101031261000e57889151386133cd565b3d9150613585565b60405162461bcd60e51b81526020600482015260156024820152746e6f2061737365747320746f20776974686472617760581b6044820152606490fd5b9150506020813d602011613615575b81613604602093836141ab565b8101031261000e5787905138613323565b3d91506135f7565b91979394909382811061363e57506136368282546141fa565b90559261332e565b9094935061364f91898296556141fa565b61365a8183546141fa565b82559161332e565b604051637afbe4f160e01b8152600481019290925260248201529050602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af49081156136f85788916136c6575b5086118015906136bb575b38806132ba565b5060001986146136b4565b90506020813d6020116136f0575b816136e1602093836141ab565b8101031261000e5751386136a9565b3d91506136d4565b6040513d8a823e3d90fd5b60405162461bcd60e51b8152602060048201526019602482015278666c617368207769746864726177206e6f7420656e61626c6560381b6044820152606490fd5b50346105cc5760203660031901126105cc5760043563ffffffff60e01b811680910361199657602090637965db0b60e01b811490811561378a575b506040519015158152f35b6301ffc9a760e01b1490508261377f565b50346105cc5760403660031901126105cc576137b5614014565b6001600160a01b0381168083526003602052604083205460243592906137dd9060ff166140ee565b6137e561476d565b3384526008602052604080852060009084825260205220908154738724d1b62ddf87d830811c9dcb2e1a6494c9c11790604051637afbe4f160e01b8152816004820152866024820152602081604481865af49081156136f8578891613ac2575b50858852600c60205260408820541161058957602090604460405180948193637afbe4f160e01b835260048301528960248301525af4908115611063578691613a90575b50838652600d60205260408620541061053f576138e4906138da6040516323b872dd60e01b60208201526138d4816138c68930336024850161460e565b03601f1981018352826141ab565b85614eae565b610430813361478a565b828552600f602052604085206138fb858254614290565b9055670de0b6b3a76400008402848104670de0b6b3a76400001485151715612c6157859161392891614230565b838252600460205260408220546001600160a01b0316803b1561054e576040516340c10f1960e01b8152918391839182908490829061396b903360048401614250565b03925af1801561054357613a7b575b50506040516004820161398c82614128565b8382526020820133815260408301908682526060840192428452805490600160401b821015613a675760018201808255821015613a535789526020808a209551600292831b90960180546001600160a01b039788166001600160a01b03199182161782559351600182018054919098169416939093179095559151818301559151600390920191909155825485019092558285525260408320805483019055337f99039fcf0a98f484616c5196ee8b2ecfa971babf0b519848289ea4db381f85f78480a480f35b634e487b7160e01b8a52603260045260248afd5b634e487b7160e01b8a52604160045260248afd5b81613a85916141ab565b611e0a57833861397a565b90506020813d602011613aba575b81613aab602093836141ab565b8101031261000e575138613889565b3d9150613a9e565b90506020813d602011613aec575b81613add602093836141ab565b8101031261000e575138613845565b3d9150613ad0565b50346105cc5760403660031901126105cc57613b0e614014565b6001600160a01b038116808352600360205260408320546024359290613b369060ff166140ee565b613b3e61476d565b613b48813361478a565b613b5181614811565b903385526008602052604085208386526020526040852080549260018201938454908715159182613f7e575b505015613f485760065487526007602052604087209386888254986000198114600014613f065750505087835460405190637afbe4f160e01b82528960048301526024820152602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af4908115610543578291613ed4575b5097915582548884555b60048601918255600386019081558715613e975760065460038501805490600160401b821015613e8357816103d9916001613c3695940181556141cc565b54868952600f602052613c4e60408a209182546141fa565b9055548588526011602052613c68604089209182546141fa565b9055670de0b6b3a76400008602868104670de0b6b3a76400000361353c57613c94889392602492614230565b918684526004602052602060018060a01b03604086205416604051938480926370a0823160e01b82523360048301525afa918215611f8d578492613e4f575b50818311908115613e45575b50613e3d575b50848252600460205260408220546001600160a01b031690813b1561054e578291613d2791604051948580948193632770a7eb60e21b83523360048401614250565b03925af1801561106357613e27575b50613d41908261426b565b6001810180546001600160a01b03191633179055600281018390554260058201819055600e54604051637afbe4f160e01b815260048101929092526024820152602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af49485156128085794613df2575b509260066020940155600654918291600183016006557f558f1f0a2c456722ef2cc50e288df74e32ca2e201a9218272de7eb91065150a985604051338152a4604051908152f35b93506020843d602011613e1f575b81613e0d602093836141ab565b8101031261000e579251926006613dab565b3d9150613e00565b94613e3681613d4193976141ab565b9490613d36565b905038613ce5565b9050541538613cdf565b9091506020813d602011613e7b575b81613e6b602093836141ab565b81010312611e0a57519038613cd3565b3d9150613e5e565b634e487b7160e01b8c52604160045260248cfd5b60405162461bcd60e51b81526020600482015260156024820152744e6f2061737365747320746f20776974686472617760581b6044820152606490fd5b90506020813d602011613efe575b81613eef602093836141ab565b81010312611996575138613bee565b3d9150613ee2565b9198909290828110613f265750613f1e8282546141fa565b905590613bf8565b909250613f36918a8294556141fa565b613f418185546141fa565b8455613bf8565b60405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606490fd5b604051637afbe4f160e01b8152600481019290925260248201529050602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af49081156136f8578891613fe2575b508611801590613fd7575b3880613b7d565b506000198614613fd0565b90506020813d60201161400c575b81613ffd602093836141ab565b81010312612282575138613fc5565b3d9150613ff0565b600435906001600160a01b038216820361000e57565b602435906001600160a01b038216820361000e57565b606090600319011261000e576004356001600160a01b038116810361000e57906024356001600160a01b038116810361000e579060443590565b60043590811515820361000e57565b91909160e08061010083019480511515845260018060a01b03602082015116602085015260018060a01b036040820151166040850152606081015160608501526080810151608085015260a081015160a085015260c081015160c08501520151910152565b156140f557565b60405162461bcd60e51b815260206004820152600b60248201526a155b9cdd5c1c1bdc9d195960aa1b6044820152606490fd5b608081019081106001600160401b0382111761414357604052565b634e487b7160e01b600052604160045260246000fd5b61010081019081106001600160401b0382111761414357604052565b60c081019081106001600160401b0382111761414357604052565b606081019081106001600160401b0382111761414357604052565b90601f801991011681019081106001600160401b0382111761414357604052565b80548210156141e45760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b9190820391821161420757565b634e487b7160e01b600052601160045260246000fd5b8181029291811591840414171561420757565b811561423a570490565b634e487b7160e01b600052601260045260246000fd5b6001600160a01b039091168152602081019190915260400190565b8054610100600160a81b03191660089290921b610100600160a81b0316919091179055565b9190820180921161420757565b805490600160401b82101561414357600182018082558210156141e45760069160e09160005260076020600020910201928051151560ff801986541691161784556142f460018060a01b036020830151168561426b565b60408101516001850180546001600160a01b0319166001600160a01b0392909216919091179055606081015160028501556080810151600385015560a0810151600485015560c081015160058501550151910155565b906040519182815491828252602082019060005260206000209260005b81811061437e57505061437c925003836141ab565b565b8454835260019485019487945060209093019201614367565b6001600160401b0381116141435760051b60200190565b906040516143bb81614159565b825460ff81161515825260081c6001600160a01b03908116602083015260018401541660408201526002830154606082015260038301546080820152600483015460a0820152600583015460c08201526006929092015460e0830152565b9081602091031261000e5751801515810361000e5790565b6001600160a01b0391821681529116602082015260400190565b80518210156141e45760209160051b010190565b6001600160a01b039091166000818152600360205260409020546144859060ff166140ee565b6000526004602052602060018060a01b0360406000205416916024604051809481936370a0823160e01b835260018060a01b031660048301525afa908115614501576000916144d2575090565b90506020813d6020116144f9575b816144ed602093836141ab565b8101031261000e575190565b3d91506144e0565b6040513d6000823e3d90fd5b600052600160205260016040600020015490565b1561452857565b60405162461bcd60e51b815260206004820152600f60248201526e1b9bdd1a1a5b99c818da185b99d959608a1b6044820152606490fd5b1561456657565b60405162461bcd60e51b815260206004820152600760248201526618db185a5b595960ca1b6044820152606490fd5b1561459c57565b60405162461bcd60e51b815260206004820152600b60248201526a3bb937b733903a37b5b2b760a91b6044820152606490fd5b805480156145f85760001901906145e682826141cc565b8154906000199060031b1b1916905555565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b03918216815291166020820152604081019190915260600190565b60405163092d4e2760e21b81526001600160a01b0390911660048201819052602082602481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af4908115614501576024926020926146ab575b506040516370a0823160e01b815230600482015292839182905afa908115614501576000916144d2575090565b6146c190833d851161105c5761104f81836141ab565b61467e565b604051906146d382614159565b600060e0838281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b1561470a57565b60405162461bcd60e51b81526020600482015260056024820152640d2dcc8caf60db1b6044820152606490fd5b1561473e57565b60405162461bcd60e51b8152602060048201526007602482015266125b9d985b1a5960ca1b6044820152606490fd5b60ff6000541661477957565b63d93c066560e01b60005260046000fd5b9060018060a01b0382166000526008602052604060002060018060a01b03821660005260205260406000209160008260028501928354614800575b506147d260019130614a2f565b94015542905560018060a01b0316806000526010602052426040600020556000526011602052604060002055565b61480a9250614a2f565b82386147c5565b6001600160a01b039081166000818152600460208181526040928390205492516318160ddd60e01b81529490928592918391165afa918215614501576000926148bf575b5081614869575050670de0b6b3a764000090565b8061489191600052600f60205260406000205490600052601160205260406000205490614290565b90670de0b6b3a7640000820291808304670de0b6b3a76400001490151715614207576148bc91614230565b90565b90916020823d6020116148eb575b816148da602093836141ab565b810103126105cc5750519038614855565b3d91506148cd565b61492861437c939261491a60405194859263a9059cbb60e01b602085015260248401614250565b03601f1981018452836141ab565b614eae565b3360009081527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602052604090205460ff161561496657565b63e2517d3f60e01b60005233600452600060245260446000fd5b3360009081527fb9cbbae02fe941283ec0eefd7b121e3bc7f89fae077b27bdd75a7fd4cf1543a8602052604090205460ff16156149b957565b63e2517d3f60e01b600052336004527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a60245260446000fd5b600081815260016020908152604080832033845290915290205460ff1615614a175750565b63e2517d3f60e01b6000523360045260245260446000fd5b9091906001600160a01b03166000308214614d5b5750600052600860205260408060002060009060018060a01b03851682526020522091604051614a7281614175565b835481526001840154906020810191825260028501549460408201958652614a9c6003820161434a565b6060830152600481018054614ab081614397565b91614abe60405193846141ab565b818352602083019060005260206000206000915b838310614d0c575050505060808301526005018054614af081614397565b91614afe60405193846141ab565b818352602083019060005260206000206000915b838310614cee575050505060a08201525193519051915b60018060a01b031660005260096020526040600020908154614b4a81614397565b92614b5860405194856141ab565b818452602084019060005260206000206000915b838310614cb05750505050815191600019830183811161420757614b90908261444b565b51928215614ca55760408401918383511115600014614bd057505050906148bc93946020614bc4644979cb9e0094426141fa565b92015102020490614290565b60009392939260005b838110614c77575b505b828410614c075750505050906148bc93946020614bc4644979cb9e009451426141fa565b839691929315614c6d57614c29906040614c21898661444b565b5101516141fa565b6000198701878111614207576001916020614c4a644979cb9e00938761444b565b5101518b0202046040614c5d898661444b565b5101519201965b01929190614be3565b9095600190614c64565b6040614c86828596979561444b565b5101518210614c9b5760010193929193614bd9565b9392915038614be1565b506000955050505050565b60036020600192604051614cc381614190565b848060a01b038654168152848601548382015260028601546040820152815201920192019190614b6c565b60076020600192614cfe856143ae565b815201920192019190614b12565b60046020600192604051614d1f81614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190614ad2565b929050604060018060a01b03821693848152600f60205220549280600052601060205260406000205490600052601160205260406000205491614b29565b60008181526001602090815260408083206001600160a01b038616845290915290205460ff16614e215760008181526001602081815260408084206001600160a01b0396909616808552959091528220805460ff19169091179055339291907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b5050600090565b60008181526001602090815260408083206001600160a01b038616845290915290205460ff1615614e215760008181526001602090815260408083206001600160a01b0395909516808452949091528120805460ff19169055339291907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b906000602091828151910182855af115614501576000513d614f0057506001600160a01b0381163b155b614edf5750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b60011415614ed856fea26469706673582212207e4762669c715cdbd5a4a68f8422d6b23a0e6fabf252bf8692575e8a66c8482f64736f6c634300081c00332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0da6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4923b5fec2089556a6c5b151e34068bfe081a4d2aa094faa466b56d44dbb75c738b9cbbae02fe941283ec0eefd7b121e3bc7f89fae077b27bdd75a7fd4cf1543a8000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000006740a2b31bc55782e46c2a9d7a32a38905e118c5000000000000000000000000934c775d3004689ea5738fe80f34378f589f190d000000000000000000000000d038213a84a86348d000929c115528ae9ddc11580000000000000000000000000000000000000000000000000000000000127500000000000000000000000000c4a718735f0783e81fdcaa999773199c2d1498d4000000000000000000000000cb60b1d1f6399e2177ef60df7ae9312940a5e5430000000000000000000000000000000000000000000000000000000000000002000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000020000000000000000000000007336c89ff7af86131d336d504e677db0eb338a160000000000000000000000001ee6e93134aee641bdbe470df2417af476bb917f000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bc0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Deployed Bytecode
0x60806040526004361015610013575b600080fd5b6000803560e01c80604e14613af4578060ed1461379b57806301ffc9a71461374457806304d3a96d146132245780630db14e95146130925780630e155c9514612faf5780630f40517a14612f765780631a9be40a14612d81578063209302ca14612d545780632169678314612a7a578063248a9ca314612a5b578063251d6ec314612a225780632d4abd2d146128b35780632f2ff15d1461288157806332cf58c41461267f578063361032911461255857806336568abe1461251357806339de62a6146124975780633a33a4f8146122ec5780633f4ba83a14612286578063429f30501461202357806343ab265f14611fff57806346891db714611e1757806348d832cb14611d3c5780634d2b144414611d1e5780634f8fe1f114611ca25780635c975abb14611c805780636382d9ad14611b0557806366fd9d651461170757806368c4ac26146116c85780636c0a188e146116aa5780637c395b131461150e578063812a71d5146112a15780638456cb59146112485780638d34a9ed146110fb57806391d14854146110af578063920c28f31461106e57806394af69aa14610e1757806395d322b014610dde5780639ed9e48314610c6f578063a1bab44714610c03578063a217fddf14610be7578063abd4292214610ba3578063b883d89c14610b5e578063cb0b8fe514610b25578063cfb66ab114610ae4578063d295fa9a146109a0578063d547741f14610965578063da57c7d71461077e578063e30227ea1461069e578063e315d80414610665578063ebc73e6514610604578063f56f4f0f146105cf5763f7192ba81461026a57600080fd5b346105cc5760403660031901126105cc5760043561028661402a565b9061028f61476d565b60ff60145460a81c1661058d5780835260076020526102b0604084206143ae565b818452600760205283600660408220828155826001820155826002820155826003820155826004820155826005820155015560018060a01b03602082015116903385526008602052604080862060009060018060a01b03851682526020522033865260086020526040862060018060a01b03841660005260205261033a600360406000200161434a565b94606083015115610589576040830151336001600160a01b03909116036105895761036683511561455f565b6001600160a01b0381169361037c908514614595565b865b865181101561057a5785610392828961444b565b51146103a05760010161037e565b909192939495805190600019820191821161056657916103f26103ca6103f793610435969561444b565b516103d96003880193846141cc565b90919082549060031b91821b91600019901b1916179055565b6145cf565b60a060808501519401519261040d858254614290565b81556001810161041e858254614290565b9055600242910155610430813361478a565b614811565b61043f8284614290565b670de0b6b3a7640000810290808204670de0b6b3a7640000149015171561055257869161046b91614230565b848252600f60205260408220610482858254614290565b905584825260116020526040822061049b848254614290565b9055848252600460205260408220546001600160a01b0316803b1561054e576040516340c10f1960e01b815291839183918290849082906104e0903360048401614250565b03925af180156105435761052a575b50506104fa91614290565b916040519081527f16a8ebcbce0c773c9fc99b0335c37c4f8128bb11da6e765f86f0aa66c6735b1860203392a480f35b81610534916141ab565b61053f5784386104ef565b8480fd5b6040513d84823e3d90fd5b8280fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b506104359192939495506103f7565b8680fd5b60405162461bcd60e51b815260206004820152601760248201527663616e63656c20636c61696d206e6f7420656e61626c6560481b6044820152606490fd5b80fd5b50346105cc5760403660031901126105cc5760206105fc6105ee614014565b6105f661402a565b90614a2f565b604051908152f35b50346105cc5760203660031901126105cc5760043561062161492d565b7fe4200d45d2a3d89971b73afef9feb38c84ba9c3a34c7a5d971392dbd399692296040600e5461065381851415614737565b8151908152836020820152a1600e5580f35b50346105cc5760203660031901126105cc576020906040906001600160a01b0361068d614014565b168152601183522054604051908152f35b50346105cc5760203660031901126105cc576001600160a01b036106c0614014565b16815260096020526040812080546106d781614397565b916106e560405193846141ab565b81835283526020808420849184015b838310610740578585805191600019830192831161072c576040602061071a858561444b565b51015181519081526127106020820152f35b634e487b7160e01b81526011600452602490fd5b6003602060019260405161075381614190565b848060a01b0386541681528486015483820152600286015460408201528152019201920191906106f4565b50346105cc57604061078f36614040565b9291846060845161079f81614128565b8281528260208201528286820152015260018060a01b038216855260036020526107ce60ff84872054166140ee565b6001600160a01b03908116855260086020908152838620929091166000908152919052206040516107fe81614175565b8154815260018201546020820152600282015460408201526108226003830161434a565b60608201526004820191825461083781614397565b9361084560405195866141ab565b81855286526020808720879186015b8383106109105750505050600590608083019384520190815461087681614397565b9261088460405194856141ab565b81845286526020808720969084015b8282106108f25760806108ba88888860a08901526108b48151518310614703565b5161444b565b5160606040519160018060a01b03815116835260018060a01b0360208201511660208401526040810151604084015201516060820152f35b600760206001926109028b6143ae565b815201980191019096610893565b6004602060019260409b989b5161092681614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190979497610854565b50346105cc5760403660031901126105cc5761099c60043561098561402a565b906109976109928261450d565b6149f2565b614e28565b5080f35b50346105cc5760403660031901126105cc5760043560046109bf61402a565b6001600160a01b03818116808652602084815260408088205490516318160ddd60e01b81529592939192869290918391165afa928315610ad9578593610aa5575b508452600f602052610a1760408520549130614a2f565b82610a5757505050670de0b6b3a7640000915b670de0b6b3a7640000820291808304670de0b6b3a7640000149015171561072c5760206105fc8484614230565b610a6091614290565b670de0b6b3a7640000810290808204670de0b6b3a76400001490151715610a915790610a8b91614230565b91610a2a565b634e487b7160e01b84526011600452602484fd5b9092506020813d602011610ad1575b81610ac1602093836141ab565b8101031261000e57519138610a00565b3d9150610ab4565b6040513d87823e3d90fd5b50346105cc5760203660031901126105cc576020906001600160a01b03610b09614014565b16815260048252604060018060a01b0391205416604051908152f35b50346105cc5760203660031901126105cc576020906040906001600160a01b03610b4d614014565b168152600f83522054604051908152f35b50346105cc5760203660031901126105cc57610b78614014565b610b8061492d565b601480546001600160a01b0319166001600160a01b039290921691909117905580f35b50346105cc5760203660031901126105cc57610bd76040610be392610bc66146c6565b5060043581526007602052206143ae565b60405191829182614089565b0390f35b50346105cc57806003193601126105cc57602090604051908152f35b50346105cc5760203660031901126105cc57600435610c2061492d565b61271081111580610c63575b610c3590614737565b80600b547f2841fef93624d9d474e38055eb5f9d3a6a8c9fdf078b6790af293d5d31225e108480a3600b5580f35b50600b54811415610c2c565b50346105cc5760403660031901126105cc576040610c8b614014565b610c9361402a565b6001600160a01b0391821684526008602090815283852091909216600090815291522060405191610cc383614175565b815483526001820154602084015260028201546040840152610ce76003830161434a565b606084015260048201918254610cfc81614397565b93610d0a60405195866141ab565b81855283526020808420849186015b838310610d8f575050505060808401928352600501805490610d3a82614397565b92610d4860405194856141ab565b82845290815260208082209084015b838310610d71576020868660a08a01525151604051908152f35b60076020600192610d81856143ae565b815201920192019190610d57565b60046020600192604051610da281614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190610d19565b50346105cc5760203660031901126105cc576020906040906001600160a01b03610e06614014565b168152600c83522054604051908152f35b50346105cc5760803660031901126105cc57610e31614014565b6064356001600160a01b0381169190604435906024359084900361053f57610e5761492d565b60405163092d4e2760e21b81526001600160a01b039093166004840181905292602081602481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af4801561106357611036575b50828552600360205260ff60408620541661100557828552600360205260408520805460ff19166001179055610ed361492d565b8285526003602052610eeb60ff6040872054166140ee565b80151580610ffc575b1561053f5760407fd9fe4a232fa59fb866233bcdccaf84797cdd30506e8fc261699d4daaff18e4cd918493848852600c602052847fe4b65af790442ef39b02e91f9b1e0caf05cb7e3607b3525b51b8d26dc27383826080858b2054838c52600d602052868c2054875191825260208201528587820152846060820152a2848852600c6020528183892055848852600d602052808389205582519182526020820152a280835260046020908152604080852080546001600160a01b03199081166001600160a01b0387161790915584865260059092528420805490911690911790557fb2d8bbd38e8da68edecef6590f2c4977823a30e753091a7822bf5229ebd719778280a280f35b50818110610ef4565b60405162461bcd60e51b815260206004820152600960248201526814dd5c1c1bdc9d195960ba1b6044820152606490fd5b6110579060203d60201161105c575b61104f81836141ab565b810190614419565b610e9f565b503d611045565b6040513d88823e3d90fd5b50346105cc5760203660031901126105cc576020906001600160a01b03611093614014565b16815260058252604060018060a01b0391205416604051908152f35b50346105cc5760403660031901126105cc5760406110cb61402a565b9160043581526001602052209060018060a01b0316600052602052602060ff604060002054166040519015158152f35b50346105cc5760803660031901126105cc57611115614014565b61111d61402a565b90604435916064359081151580920361053f576014546001600160a01b031692338490036112445761118960208660018060a01b03841696878a5260048352858a60018060a01b0360408220541692604051968795869485936323b872dd60e01b85526004850161460e565b03925af180156112395761121c575b506001600160a01b03821686526008602090815260408088206000878152925290209260010361120e57505060125460028201555b6111d8838254614290565b9055808352600f602052604083206111f1838254614290565b90558252600260205261120960408320918254614290565b905580f35b6112179161478a565b6111cd565b6112349060203d60201161105c5761104f81836141ab565b611198565b6040513d89823e3d90fd5b8580fd5b50346105cc57806003193601126105cc57611261614980565b61126961476d565b600160ff198254161781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b50346105cc5760403660031901126105cc576112bb614014565b6001600160a01b031680825260036020526040822054602435906112e19060ff166140ee565b6112e961492d565b6127108110156114da57818352600960205260408320805461130a81614397565b9161131860405193846141ab565b81835285526020808620869184015b83831061149c575050505080519060001982019182116114885760209161134d9161444b565b510151818114158061147f575b156114475760405161136b81614190565b838152602081018381526040820190428252858752600960205260408720805490600160401b821015611433576001820180825582101561141f57885260208089209451600390920290940180546001600160a01b0319166001600160a01b03929092169190911781559051600182015590516002919091015560408051948552908401919091528201527f37709c0c7a143f7f128833da302459d5478d74b7775d223b5f77553310a221de90606090a180f35b634e487b7160e01b89526032600452602489fd5b634e487b7160e01b89526041600452602489fd5b60405162461bcd60e51b815260206004820152601060248201526f496e76616c6964206e6577207261746560801b6044820152606490fd5b5081151561135a565b634e487b7160e01b85526011600452602485fd5b600360206001926040516114af81614190565b848060a01b038654168152848601548382015260028601546040820152815201920192019190611327565b60405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964207261746560a01b6044820152606490fd5b50346105cc5760409061152036614040565b939161152a6146c6565b506001600160a01b038216845260036020528284205461154c9060ff166140ee565b6001600160a01b03908116845260086020908152838520929091166000908152919052206040519061157d82614175565b8054825260018101546020830152600281015460408301526115a16003820161434a565b60608301526004810180546115b581614397565b916115c360405193846141ab565b81835285526020808620869184015b83831061165b575050505060808301526005018054906115f182614397565b936115ff60405195866141ab565b82855290815260208082209085015b83831061163d57610be361163088886108b460a08a0191808352518310614703565b5160405191829182614089565b6007602060019261164d856143ae565b81520192019201919061160e565b6004602060019260405161166e81614128565b848060a01b038654168152848060a01b0385870154168382015260028601546040820152600386015460608201528152019201920191906115d2565b50346105cc57806003193601126105cc576020600654604051908152f35b50346105cc5760203660031901126105cc5760209060ff906040906001600160a01b036116f3614014565b168152600384522054166040519015158152f35b50346105cc5760803660031901126105cc57611721614014565b61172961402a565b6044356001600160a01b038116919082810361053f57606435906001600160a01b03831690848214611ac0578215611a7b57611765868561445f565b93838510611a4c57338314611a0b5760018060a01b038716808952600460205260018060a01b0360408a20541660206040518092636eb1769f60e11b825281806117b3338960048401614431565b03915afa8015611a005786918b916119cb575b501061199a578089526004602052604089205489906001600160a01b0316803b1561199657816040518092630f75ba2160e41b825281838161180d8d338c6004850161460e565b03925af180156105435761197d575b5052600460205260018060a01b0360408920541691602060405180946323b872dd60e01b8252818c816118548b888a6004850161460e565b03925af1928315611972578880936118759261187a96611953575b5061478a565b61478a565b85526008602052604080862060009060018060a01b03871682526020522091825491604060018501968754968952600860205281892060009160018060a01b031682526020522096670de0b6b3a76400008202918204670de0b6b3a76400000361072c5750611910611940959493670de0b6b3a7640000611909611902611926968396614230565b809361421d565b049561421d565b049261191d818854614290565b875582546141fa565b905560018401611937828254614290565b905582546141fa565b9055600242910155602060405160018152f35b61196b9060203d60201161105c5761104f81836141ab565b503861186f565b6040513d8b823e3d90fd5b81611987916141ab565b61199257883861181c565b8880fd5b5080fd5b60405162461bcd60e51b8152602060048201526009602482015268616c6c6f77616e636560b81b6044820152606490fd5b9150506020813d6020116119f8575b816119e7602093836141ab565b8101031261000e57859051386117c6565b3d91506119da565b6040513d8c823e3d90fd5b60018060a01b0387168852600460205260018060a01b0360408920541691602060405180946323b872dd60e01b8252818c816118548b88336004850161460e565b60405162461bcd60e51b815260206004820152600760248201526662616c616e636560c81b6044820152606490fd5b60405162461bcd60e51b815260206004820152601d60248201527f616d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606490fd5b60405162461bcd60e51b815260206004820152601e60248201527f66726f6d2063616e206e6f742062652073616d652061732074686520746f00006044820152606490fd5b50346105cc5760403660031901126105cc57611b1f614014565b611b2761402a565b90611b3061492d565b60405163092d4e2760e21b81526001600160a01b0390911660048201819052738724d1b62ddf87d830811c9dcb2e1a6494c9c117929091602081602481875af48015610ad957611c63575b5060405163092d4e2760e21b81526001600160a01b0382166004820181905293602090829060249082905af48015610ad957611c46575b506040516370a0823160e01b815230600482015290602082602481865afa908115610ad9578591611c10575b611be99250836148f3565b7ff5b6d8b404f034718f55a370884db03c4e27e9652e2636d4adcd0540d7c4203f8380a380f35b90506020823d602011611c3e575b81611c2b602093836141ab565b8101031261000e57611be9915190611bde565b3d9150611c1e565b611c5e9060203d60201161105c5761104f81836141ab565b611bb2565b611c7b9060203d60201161105c5761104f81836141ab565b611b7b565b50346105cc57806003193601126105cc5760ff60209154166040519015158152f35b50346105cc5760203660031901126105cc57611cbc61407a565b611cc461492d565b6014549060ff8260a81c16151590151591611ce182841415614521565b60ff60a81b191660a883901b60ff60a81b16176014557f84e3667aff0d15c7464eb61e79d9db356389b19a3a5024099a09272a7bf11ce98380a380f35b50346105cc57806003193601126105cc576020600e54604051908152f35b50346105cc5760603660031901126105cc57611d56614014565b60243560443591611d6561492d565b6001600160a01b031680845260036020526040842054909190611d8a9060ff166140ee565b80151580611e0e575b15611e0a57818452600c602052817fe4b65af790442ef39b02e91f9b1e0caf05cb7e3607b3525b51b8d26dc273838260806040872054838852600d60205260408820546040519182526020820152846040820152866060820152a2818452600c60205260408420558252600d602052604082205580f35b8380fd5b50828110611d93565b50346105cc5760403660031901126105cc57611e31614014565b6001600160a01b0316808252600360205260408220546024359190611e589060ff166140ee565b7f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b8352600160209081526040808520336000908152925290205460ff1615611fc8578115611f98576040516370a0823160e01b8152306004820152602081602481855afa908115611f8d578491611f5b575b508211611f2157600a54611ee99083906001600160a01b0316836148f3565b7f4df7f50f630ac07eef038205b5b9c0c910ce8498aa925abbfcb0e1e674058aa9602060018060a01b03600a5416604051908152a380f35b60405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606490fd5b90506020813d602011611f85575b81611f76602093836141ab565b8101031261000e575138611eca565b3d9150611f69565b6040513d86823e3d90fd5b60405162461bcd60e51b815260206004820152600860248201526706d757374203e20360c41b6044820152606490fd5b63e2517d3f60e01b8352336004527f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b602452604483fd5b50346105cc5760203660031901126105cc5760206105fc61201e614014565b614630565b50346105cc5760403660031901126105cc5760043561204061402a565b9061204961476d565b808352600760205261205d604084206143ae565b60208181015133808752600880845260408089206001600160a01b039094166000818152948652818520938a529185528089208285529094529290912090949192906120ab9060030161434a565b9460608201928351156122825760e08301514210612282576040830151336001600160a01b0390911603612282576120f8906120e884511561455f565b6001600160a01b03168514614595565b848752600760205260408720805460ff19166001179055865b86518110156122715785612125828961444b565b511461213357600101612111565b9091929394958051906000198201918211610566576005926103f26121606121dc97969461216f9461444b565b516103d96003860193846141cc565b60808301928351878a52600260205261218d60408b209182546141fa565b9055855193519060c060a082015191015191604051956121ac87614159565b600187528960208801523360408801526060870152608086015260a085015260c08401524260e08401520161429d565b601354815185916001600160a01b0316803b1561054e576040516317d5759960e31b8152918391839182908490829061221a90338c6004850161460e565b03925af180156105435761225c575b505051916040519081527fdddf48d4d866b99b4e98ab4756d69715555f0445680fe5941715d094c362c0fd60203392a480f35b81612266916141ab565b611e0a578338612229565b506121dc929394955060059061216f565b8780fd5b50346105cc57806003193601126105cc5761229f614980565b805460ff8116156122dd5760ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a180f35b638dfc202b60e01b8252600482fd5b50346105cc5760403660031901126105cc576040612308614014565b61231061402a565b6001600160a01b0391821684526008602090815283852091909216600090815291522060405161233f81614175565b8154815260018201546020820152600282015460408201526123636003830161434a565b916060820192835260048101805461237a81614397565b9161238860405193846141ab565b81835286526020808720879184015b8383106124485750505050906005916080840152019081546123b881614397565b926123c660405194856141ab565b81845285526020808620869185015b83831061242a575050505060a001525190604051918291602083016020845282518091526020604085019301915b818110612411575050500390f35b8251845285945060209384019390920191600101612403565b6007602060019261243a856143ae565b8152019201920191906123d5565b6004602060019260405161245b81614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190612397565b50346105cc5760203660031901126105cc576124b161407a565b6124b961492d565b6014549060ff8260a01c161515901515916124d682841415614521565b60ff60a01b191660a083901b60ff60a01b16176014557f99859612a8514731da8547a1b97ab4654097e36c13fe2c98960ecd00f770747b8380a380f35b50346105cc5760403660031901126105cc5761252d61402a565b336001600160a01b038216036125495761099c90600435614e28565b63334bd91960e11b8252600482fd5b50346105cc5760403660031901126105cc5760049061257561402a565b6001600160a01b03818116808452602085815260408086205490516318160ddd60e01b81529692939192879290918391165afa938415612674578394612640575b508252600f6020526125cd60408320549130614a2f565b836125f757505050506020670de0b6b3a76400006125ee815b60043561421d565b04604051908152f35b61260091614290565b90670de0b6b3a7640000820291808304670de0b6b3a7640000149015171561072c57506125ee61263b602093670de0b6b3a764000093614230565b6125e6565b9093506020813d60201161266c575b8161265c602093836141ab565b8101031261000e575192386125b6565b3d915061264f565b6040513d85823e3d90fd5b50346105cc5760403660031901126105cc57612699614014565b6126a161402a565b9160018060a01b03821681526008602052604080822060009060018060a01b03861682526020522092604051936126d785614175565b8054855260018101546020860152600281015460408601526126fb6003820161434a565b606086015260048101805461270f81614397565b9161271d60405193846141ab565b81835285526020808620869184015b83831061283257505050509060059160808701520193845461274d81614397565b9061275b60405192836141ab565b80825260208201968552602085209685905b8282106128145750505060a082015251926127889190614a2f565b60405192637afbe4f160e01b845260048401526024830152602082604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af490811561280857906127d5575b602090604051908152f35b506020813d602011612800575b816127ef602093836141ab565b8101031261000e57602090516127ca565b3d91506127e2565b604051903d90823e3d90fd5b600760206001926128248c6143ae565b81520199019101909761276d565b6004602060019260405161284581614128565b848060a01b038654168152848060a01b03858701541683820152600286015460408201526003860154606082015281520192019201919061272c565b50346105cc5760403660031901126105cc5761099c6004356128a161402a565b906128ae6109928261450d565b614d99565b50346105cc5760403660031901126105cc5760406128cf614014565b6128d761402a565b6001600160a01b03918216845260086020908152838520919092166000908152915220604051909161290882614175565b82548252600183015460208301526002830154604083015261292c6003840161434a565b60608301526004830192835461294181614397565b9061294f60405192836141ab565b80825260208201958452602084209584905b8282106129d357505050608084015260050180549061297f82614397565b9261298d60405194856141ab565b82845290815260208082209084015b8383106129b5576020858060a089015251604051908152f35b600760206001926129c5856143ae565b81520192019201919061299c565b600460206001926040516129e681614128565b848060a01b038c54168152848060a01b03858d0154168382015260028c0154604082015260038c01546060820152815201980191019096612961565b50346105cc5760203660031901126105cc576020906040906001600160a01b03612a4a614014565b168152600d83522054604051908152f35b50346105cc5760203660031901126105cc5760206105fc60043561450d565b50346105cc57612a8936614040565b929042841115612d205760018060a01b03831682526008602052604080832060009060018060a01b0384168252602052209260405191612ac883614175565b845483526001850154602084015260028501549460408401958652612aef6003820161434a565b6060850152600481018054612b0381614397565b91612b1160405193846141ab565b81835287526020808820889184015b838310612cd1575050505060808501526005018054612b3e81614397565b91612b4c60405193846141ab565b81835286526020808720879184015b838310612cb3575050505060a08401526001600160a01b03811684526009602052604084208054612b8b81614397565b91612b9960405193846141ab565b81835286526020808720879184015b838310612c7557505050508051906000198201918211612c615790612bcc9161444b565b5191849551612c41575b50506020612bed644979cb9e0094959642906141fa565b925191015102020460405192637afbe4f160e01b845260048401526024830152602082604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af490811561280857906127d557602090604051908152f35b644979cb9e00949550612c59602092612bed92614a2f565b959450612bd6565b634e487b7160e01b86526011600452602486fd5b60036020600192604051612c8881614190565b848060a01b038654168152848601548382015260028601546040820152815201920192019190612ba8565b60076020600192612cc3856143ae565b815201920192019190612b5b565b60046020600192604051612ce481614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190612b20565b60405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b6044820152606490fd5b50346105cc5760403660031901126105cc5760206105fc612d73614014565b612d7b61402a565b9061445f565b50346105cc5760403660031901126105cc57612d9b614014565b90612da461402a565b9160408293612db38184614a2f565b6001600160a01b0393841685526008602090815283862092909416600090815291909352206040519290612de684614175565b805484526001810154602085015260028101546040850152612e0a6003820161434a565b6060850152600481018054612e1e81614397565b91612e2c60405193846141ab565b81835284526020808520859184015b838310612f27575050505090600591608086015201928354612e5c81614397565b94612e6a60405196876141ab565b81865283526020808420849187015b838310612f09575050505060a00192835280935b83518051861015612ebb5760019160a0612eaa88612eb39461444b565b51015190614290565b940193612e8d565b509160405192637afbe4f160e01b845260048401526024830152602082604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af490811561280857906127d557602090604051908152f35b60076020600192612f19856143ae565b815201920192019190612e79565b60046020600192604051612f3a81614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190612e3b565b50346105cc5760203660031901126105cc576020906040906001600160a01b03612f9e614014565b168152600283522054604051908152f35b50346105cc5760203660031901126105cc57612fc9614014565b612fd161492d565b60405163092d4e2760e21b81526001600160a01b038216600482018190529190602081602481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af48015611f8d57613075575b50600a54906001600160a01b0382169083821461053f577f2181541ed844bb663fa1c189300cc64ee66517f8346ea79c074cf61c782f0ed39161306160405192839283614431565b0390a16001600160a01b03191617600a5580f35b61308d9060203d60201161105c5761104f81836141ab565b613019565b50346105cc5760403660031901126105cc5760406130ae614014565b6130b661402a565b6001600160a01b03811684526003602052828420549091906130da9060ff166140ee565b60018060a01b03168352600860205281832060009160018060a01b03168252602052209060405161310a81614175565b82548152600183015460208201526002830154604082015261312e6003840161434a565b60608201526004830192835461314381614397565b9061315160405192836141ab565b80825260208201958552602085209585905b8282106131d557505050608083015260050180549061318182614397565b9361318f60405195866141ab565b82855290815260208082209085015b8383106131b7576020858760a082015251604051908152f35b600760206001926131c7856143ae565b81520192019201919061319e565b600460206001926040516131e881614128565b848060a01b038c54168152848060a01b03858d0154168382015260028c0154604082015260038c01546060820152815201980191019096613163565b50346105cc5760403660031901126105cc5761323e614014565b6001600160a01b0381168083526003602052604083205460243592906132669060ff166140ee565b61326e61476d565b60ff60145460a01c1661370357338452600860205260408085206000908482526020522061329c823361478a565b6132a582614811565b81549160018101928354908715159182613662575b50501561058957600654875260076020528254958781600019810361361d5750505086815460405190637afbe4f160e01b82528860048301526024820152602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af49081156105435782916135e8575b509693558054918782555b86156135ab57858852600f6020526040882061334b8482546141fa565b90558588526011602052604088206133648582546141fa565b9055670de0b6b3a76400008702878104670de0b6b3a76400000361056657889161338d91614230565b86825260046020526024602060018060a01b03604085205416604051928380926370a0823160e01b82523360048301525afa908115612674578391613576575b50808211801561356d575b613565575b50868252600460205260408220546001600160a01b0316803b1561054e57604051632770a7eb60e21b81529183918391829084908290613421903360048401614250565b03925af1801561054357613550575b5050600b5461271003612710811161353c5761344f612710918861421d565b04908161346561345f828a6141fa565b96614630565b10613502576134d39361347b60059333896148f3565b8689526002602052604089206134928582546141fa565b9055604051936134a185614159565b60018552876020860152336040860152886060860152608085015260a08401524260c08401524260e08401520161429d565b6040519081527febb065a01aeb84b2b8d3adb2f31a9b004b8ddaba2a4f702240f6f569e49855be60203392a480f35b60405162461bcd60e51b81526020600482015260126024820152716e6f7420656e6f7567682062616c616e636560701b6044820152606490fd5b634e487b7160e01b88526011600452602488fd5b8161355a916141ab565b610589578638613430565b9050386133dd565b508354156133d8565b9250506020823d6020116135a3575b81613592602093836141ab565b8101031261000e57889151386133cd565b3d9150613585565b60405162461bcd60e51b81526020600482015260156024820152746e6f2061737365747320746f20776974686472617760581b6044820152606490fd5b9150506020813d602011613615575b81613604602093836141ab565b8101031261000e5787905138613323565b3d91506135f7565b91979394909382811061363e57506136368282546141fa565b90559261332e565b9094935061364f91898296556141fa565b61365a8183546141fa565b82559161332e565b604051637afbe4f160e01b8152600481019290925260248201529050602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af49081156136f85788916136c6575b5086118015906136bb575b38806132ba565b5060001986146136b4565b90506020813d6020116136f0575b816136e1602093836141ab565b8101031261000e5751386136a9565b3d91506136d4565b6040513d8a823e3d90fd5b60405162461bcd60e51b8152602060048201526019602482015278666c617368207769746864726177206e6f7420656e61626c6560381b6044820152606490fd5b50346105cc5760203660031901126105cc5760043563ffffffff60e01b811680910361199657602090637965db0b60e01b811490811561378a575b506040519015158152f35b6301ffc9a760e01b1490508261377f565b50346105cc5760403660031901126105cc576137b5614014565b6001600160a01b0381168083526003602052604083205460243592906137dd9060ff166140ee565b6137e561476d565b3384526008602052604080852060009084825260205220908154738724d1b62ddf87d830811c9dcb2e1a6494c9c11790604051637afbe4f160e01b8152816004820152866024820152602081604481865af49081156136f8578891613ac2575b50858852600c60205260408820541161058957602090604460405180948193637afbe4f160e01b835260048301528960248301525af4908115611063578691613a90575b50838652600d60205260408620541061053f576138e4906138da6040516323b872dd60e01b60208201526138d4816138c68930336024850161460e565b03601f1981018352826141ab565b85614eae565b610430813361478a565b828552600f602052604085206138fb858254614290565b9055670de0b6b3a76400008402848104670de0b6b3a76400001485151715612c6157859161392891614230565b838252600460205260408220546001600160a01b0316803b1561054e576040516340c10f1960e01b8152918391839182908490829061396b903360048401614250565b03925af1801561054357613a7b575b50506040516004820161398c82614128565b8382526020820133815260408301908682526060840192428452805490600160401b821015613a675760018201808255821015613a535789526020808a209551600292831b90960180546001600160a01b039788166001600160a01b03199182161782559351600182018054919098169416939093179095559151818301559151600390920191909155825485019092558285525260408320805483019055337f99039fcf0a98f484616c5196ee8b2ecfa971babf0b519848289ea4db381f85f78480a480f35b634e487b7160e01b8a52603260045260248afd5b634e487b7160e01b8a52604160045260248afd5b81613a85916141ab565b611e0a57833861397a565b90506020813d602011613aba575b81613aab602093836141ab565b8101031261000e575138613889565b3d9150613a9e565b90506020813d602011613aec575b81613add602093836141ab565b8101031261000e575138613845565b3d9150613ad0565b50346105cc5760403660031901126105cc57613b0e614014565b6001600160a01b038116808352600360205260408320546024359290613b369060ff166140ee565b613b3e61476d565b613b48813361478a565b613b5181614811565b903385526008602052604085208386526020526040852080549260018201938454908715159182613f7e575b505015613f485760065487526007602052604087209386888254986000198114600014613f065750505087835460405190637afbe4f160e01b82528960048301526024820152602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af4908115610543578291613ed4575b5097915582548884555b60048601918255600386019081558715613e975760065460038501805490600160401b821015613e8357816103d9916001613c3695940181556141cc565b54868952600f602052613c4e60408a209182546141fa565b9055548588526011602052613c68604089209182546141fa565b9055670de0b6b3a76400008602868104670de0b6b3a76400000361353c57613c94889392602492614230565b918684526004602052602060018060a01b03604086205416604051938480926370a0823160e01b82523360048301525afa918215611f8d578492613e4f575b50818311908115613e45575b50613e3d575b50848252600460205260408220546001600160a01b031690813b1561054e578291613d2791604051948580948193632770a7eb60e21b83523360048401614250565b03925af1801561106357613e27575b50613d41908261426b565b6001810180546001600160a01b03191633179055600281018390554260058201819055600e54604051637afbe4f160e01b815260048101929092526024820152602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af49485156128085794613df2575b509260066020940155600654918291600183016006557f558f1f0a2c456722ef2cc50e288df74e32ca2e201a9218272de7eb91065150a985604051338152a4604051908152f35b93506020843d602011613e1f575b81613e0d602093836141ab565b8101031261000e579251926006613dab565b3d9150613e00565b94613e3681613d4193976141ab565b9490613d36565b905038613ce5565b9050541538613cdf565b9091506020813d602011613e7b575b81613e6b602093836141ab565b81010312611e0a57519038613cd3565b3d9150613e5e565b634e487b7160e01b8c52604160045260248cfd5b60405162461bcd60e51b81526020600482015260156024820152744e6f2061737365747320746f20776974686472617760581b6044820152606490fd5b90506020813d602011613efe575b81613eef602093836141ab565b81010312611996575138613bee565b3d9150613ee2565b9198909290828110613f265750613f1e8282546141fa565b905590613bf8565b909250613f36918a8294556141fa565b613f418185546141fa565b8455613bf8565b60405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606490fd5b604051637afbe4f160e01b8152600481019290925260248201529050602081604481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af49081156136f8578891613fe2575b508611801590613fd7575b3880613b7d565b506000198614613fd0565b90506020813d60201161400c575b81613ffd602093836141ab565b81010312612282575138613fc5565b3d9150613ff0565b600435906001600160a01b038216820361000e57565b602435906001600160a01b038216820361000e57565b606090600319011261000e576004356001600160a01b038116810361000e57906024356001600160a01b038116810361000e579060443590565b60043590811515820361000e57565b91909160e08061010083019480511515845260018060a01b03602082015116602085015260018060a01b036040820151166040850152606081015160608501526080810151608085015260a081015160a085015260c081015160c08501520151910152565b156140f557565b60405162461bcd60e51b815260206004820152600b60248201526a155b9cdd5c1c1bdc9d195960aa1b6044820152606490fd5b608081019081106001600160401b0382111761414357604052565b634e487b7160e01b600052604160045260246000fd5b61010081019081106001600160401b0382111761414357604052565b60c081019081106001600160401b0382111761414357604052565b606081019081106001600160401b0382111761414357604052565b90601f801991011681019081106001600160401b0382111761414357604052565b80548210156141e45760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b9190820391821161420757565b634e487b7160e01b600052601160045260246000fd5b8181029291811591840414171561420757565b811561423a570490565b634e487b7160e01b600052601260045260246000fd5b6001600160a01b039091168152602081019190915260400190565b8054610100600160a81b03191660089290921b610100600160a81b0316919091179055565b9190820180921161420757565b805490600160401b82101561414357600182018082558210156141e45760069160e09160005260076020600020910201928051151560ff801986541691161784556142f460018060a01b036020830151168561426b565b60408101516001850180546001600160a01b0319166001600160a01b0392909216919091179055606081015160028501556080810151600385015560a0810151600485015560c081015160058501550151910155565b906040519182815491828252602082019060005260206000209260005b81811061437e57505061437c925003836141ab565b565b8454835260019485019487945060209093019201614367565b6001600160401b0381116141435760051b60200190565b906040516143bb81614159565b825460ff81161515825260081c6001600160a01b03908116602083015260018401541660408201526002830154606082015260038301546080820152600483015460a0820152600583015460c08201526006929092015460e0830152565b9081602091031261000e5751801515810361000e5790565b6001600160a01b0391821681529116602082015260400190565b80518210156141e45760209160051b010190565b6001600160a01b039091166000818152600360205260409020546144859060ff166140ee565b6000526004602052602060018060a01b0360406000205416916024604051809481936370a0823160e01b835260018060a01b031660048301525afa908115614501576000916144d2575090565b90506020813d6020116144f9575b816144ed602093836141ab565b8101031261000e575190565b3d91506144e0565b6040513d6000823e3d90fd5b600052600160205260016040600020015490565b1561452857565b60405162461bcd60e51b815260206004820152600f60248201526e1b9bdd1a1a5b99c818da185b99d959608a1b6044820152606490fd5b1561456657565b60405162461bcd60e51b815260206004820152600760248201526618db185a5b595960ca1b6044820152606490fd5b1561459c57565b60405162461bcd60e51b815260206004820152600b60248201526a3bb937b733903a37b5b2b760a91b6044820152606490fd5b805480156145f85760001901906145e682826141cc565b8154906000199060031b1b1916905555565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b03918216815291166020820152604081019190915260600190565b60405163092d4e2760e21b81526001600160a01b0390911660048201819052602082602481738724d1b62ddf87d830811c9dcb2e1a6494c9c1175af4908115614501576024926020926146ab575b506040516370a0823160e01b815230600482015292839182905afa908115614501576000916144d2575090565b6146c190833d851161105c5761104f81836141ab565b61467e565b604051906146d382614159565b600060e0838281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b1561470a57565b60405162461bcd60e51b81526020600482015260056024820152640d2dcc8caf60db1b6044820152606490fd5b1561473e57565b60405162461bcd60e51b8152602060048201526007602482015266125b9d985b1a5960ca1b6044820152606490fd5b60ff6000541661477957565b63d93c066560e01b60005260046000fd5b9060018060a01b0382166000526008602052604060002060018060a01b03821660005260205260406000209160008260028501928354614800575b506147d260019130614a2f565b94015542905560018060a01b0316806000526010602052426040600020556000526011602052604060002055565b61480a9250614a2f565b82386147c5565b6001600160a01b039081166000818152600460208181526040928390205492516318160ddd60e01b81529490928592918391165afa918215614501576000926148bf575b5081614869575050670de0b6b3a764000090565b8061489191600052600f60205260406000205490600052601160205260406000205490614290565b90670de0b6b3a7640000820291808304670de0b6b3a76400001490151715614207576148bc91614230565b90565b90916020823d6020116148eb575b816148da602093836141ab565b810103126105cc5750519038614855565b3d91506148cd565b61492861437c939261491a60405194859263a9059cbb60e01b602085015260248401614250565b03601f1981018452836141ab565b614eae565b3360009081527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602052604090205460ff161561496657565b63e2517d3f60e01b60005233600452600060245260446000fd5b3360009081527fb9cbbae02fe941283ec0eefd7b121e3bc7f89fae077b27bdd75a7fd4cf1543a8602052604090205460ff16156149b957565b63e2517d3f60e01b600052336004527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a60245260446000fd5b600081815260016020908152604080832033845290915290205460ff1615614a175750565b63e2517d3f60e01b6000523360045260245260446000fd5b9091906001600160a01b03166000308214614d5b5750600052600860205260408060002060009060018060a01b03851682526020522091604051614a7281614175565b835481526001840154906020810191825260028501549460408201958652614a9c6003820161434a565b6060830152600481018054614ab081614397565b91614abe60405193846141ab565b818352602083019060005260206000206000915b838310614d0c575050505060808301526005018054614af081614397565b91614afe60405193846141ab565b818352602083019060005260206000206000915b838310614cee575050505060a08201525193519051915b60018060a01b031660005260096020526040600020908154614b4a81614397565b92614b5860405194856141ab565b818452602084019060005260206000206000915b838310614cb05750505050815191600019830183811161420757614b90908261444b565b51928215614ca55760408401918383511115600014614bd057505050906148bc93946020614bc4644979cb9e0094426141fa565b92015102020490614290565b60009392939260005b838110614c77575b505b828410614c075750505050906148bc93946020614bc4644979cb9e009451426141fa565b839691929315614c6d57614c29906040614c21898661444b565b5101516141fa565b6000198701878111614207576001916020614c4a644979cb9e00938761444b565b5101518b0202046040614c5d898661444b565b5101519201965b01929190614be3565b9095600190614c64565b6040614c86828596979561444b565b5101518210614c9b5760010193929193614bd9565b9392915038614be1565b506000955050505050565b60036020600192604051614cc381614190565b848060a01b038654168152848601548382015260028601546040820152815201920192019190614b6c565b60076020600192614cfe856143ae565b815201920192019190614b12565b60046020600192604051614d1f81614128565b848060a01b038654168152848060a01b038587015416838201526002860154604082015260038601546060820152815201920192019190614ad2565b929050604060018060a01b03821693848152600f60205220549280600052601060205260406000205490600052601160205260406000205491614b29565b60008181526001602090815260408083206001600160a01b038616845290915290205460ff16614e215760008181526001602081815260408084206001600160a01b0396909616808552959091528220805460ff19169091179055339291907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b5050600090565b60008181526001602090815260408083206001600160a01b038616845290915290205460ff1615614e215760008181526001602090815260408083206001600160a01b0395909516808452949091528120805460ff19169055339291907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b906000602091828151910182855af115614501576000513d614f0057506001600160a01b0381163b155b614edf5750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b60011415614ed856fea26469706673582212207e4762669c715cdbd5a4a68f8422d6b23a0e6fabf252bf8692575e8a66c8482f64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000006740a2b31bc55782e46c2a9d7a32a38905e118c5000000000000000000000000934c775d3004689ea5738fe80f34378f589f190d000000000000000000000000d038213a84a86348d000929c115528ae9ddc11580000000000000000000000000000000000000000000000000000000000127500000000000000000000000000c4a718735f0783e81fdcaa999773199c2d1498d4000000000000000000000000cb60b1d1f6399e2177ef60df7ae9312940a5e5430000000000000000000000000000000000000000000000000000000000000002000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000020000000000000000000000007336c89ff7af86131d336d504e677db0eb338a160000000000000000000000001ee6e93134aee641bdbe470df2417af476bb917f000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bc0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-----Decoded View---------------
Arg [0] : _tokens (address[]): 0xdAC17F958D2ee523a2206206994597C13D831ec7,0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [1] : _zkTokens (address[]): 0x7336C89fF7AF86131D336d504E677Db0eb338a16,0x1EE6e93134aee641BDBe470Df2417aF476bb917f
Arg [2] : _newRewardRate (uint256[]): 700,700
Arg [3] : _minStakeAmount (uint256[]): 10000000,10000000
Arg [4] : _maxStakeAmount (uint256[]): 115792089237316195423570985008687907853269984665640564039457584007913129639935,115792089237316195423570985008687907853269984665640564039457584007913129639935
Arg [5] : _admin (address): 0x6740a2b31BC55782e46C2a9D7A32A38905E118C5
Arg [6] : _bot (address): 0x934C775d3004689EA5738FE80F34378f589F190D
Arg [7] : _ceffu (address): 0xD038213A84a86348d000929C115528AE9DdC1158
Arg [8] : _waitingTime (uint256): 1209600
Arg [9] : withdrawVaultAddress (address): 0xc4A718735F0783E81FdcAA999773199C2D1498d4
Arg [10] : _airdropAddr (address): 0xcB60b1d1F6399e2177eF60df7aE9312940a5E543
-----Encoded View---------------
26 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [1] : 00000000000000000000000000000000000000000000000000000000000001c0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000220
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000280
Arg [4] : 00000000000000000000000000000000000000000000000000000000000002e0
Arg [5] : 0000000000000000000000006740a2b31bc55782e46c2a9d7a32a38905e118c5
Arg [6] : 000000000000000000000000934c775d3004689ea5738fe80f34378f589f190d
Arg [7] : 000000000000000000000000d038213a84a86348d000929c115528ae9ddc1158
Arg [8] : 0000000000000000000000000000000000000000000000000000000000127500
Arg [9] : 000000000000000000000000c4a718735f0783e81fdcaa999773199c2d1498d4
Arg [10] : 000000000000000000000000cb60b1d1f6399e2177ef60df7ae9312940a5e543
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [12] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [13] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [15] : 0000000000000000000000007336c89ff7af86131d336d504e677db0eb338a16
Arg [16] : 0000000000000000000000001ee6e93134aee641bdbe470df2417af476bb917f
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [18] : 00000000000000000000000000000000000000000000000000000000000002bc
Arg [19] : 00000000000000000000000000000000000000000000000000000000000002bc
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [21] : 0000000000000000000000000000000000000000000000000000000000989680
Arg [22] : 0000000000000000000000000000000000000000000000000000000000989680
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [24] : ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Arg [25] : ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.