More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,122 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Representa... | 21635954 | 10 days ago | IN | 0 ETH | 0.00023457 | ||||
Claim Representa... | 21196473 | 71 days ago | IN | 0 ETH | 0.00072982 | ||||
Claim Representa... | 20626349 | 151 days ago | IN | 0 ETH | 0.00031211 | ||||
Claim Representa... | 20608761 | 153 days ago | IN | 0 ETH | 0.00005241 | ||||
Claim Representa... | 20592550 | 156 days ago | IN | 0 ETH | 0.00009275 | ||||
Claim Representa... | 20554503 | 161 days ago | IN | 0 ETH | 0.0000758 | ||||
Claim Representa... | 20554416 | 161 days ago | IN | 0 ETH | 0.00017881 | ||||
Claim Representa... | 20553789 | 161 days ago | IN | 0 ETH | 0.00005312 | ||||
Claim Representa... | 20534763 | 164 days ago | IN | 0 ETH | 0.00026337 | ||||
Claim Representa... | 20522591 | 165 days ago | IN | 0 ETH | 0.00017266 | ||||
Claim Representa... | 20514656 | 167 days ago | IN | 0 ETH | 0.00021158 | ||||
Claim Representa... | 20419389 | 180 days ago | IN | 0 ETH | 0.00044402 | ||||
Claim Representa... | 20413938 | 181 days ago | IN | 0 ETH | 0.00039172 | ||||
Claim Representa... | 20364912 | 187 days ago | IN | 0 ETH | 0.00058192 | ||||
Claim Representa... | 20364797 | 187 days ago | IN | 0 ETH | 0.00094664 | ||||
Claim Representa... | 20348405 | 190 days ago | IN | 0 ETH | 0.00023787 | ||||
Claim Representa... | 20342723 | 191 days ago | IN | 0 ETH | 0.00035156 | ||||
Claim Representa... | 20297761 | 197 days ago | IN | 0 ETH | 0.00010633 | ||||
Claim Representa... | 20290666 | 198 days ago | IN | 0 ETH | 0.00018655 | ||||
Claim Representa... | 20288437 | 198 days ago | IN | 0 ETH | 0.00009213 | ||||
Claim Representa... | 20282440 | 199 days ago | IN | 0 ETH | 0.00047368 | ||||
Claim Representa... | 20278611 | 200 days ago | IN | 0 ETH | 0.0001939 | ||||
Claim Representa... | 20275524 | 200 days ago | IN | 0 ETH | 0.00029969 | ||||
Claim Representa... | 20273199 | 200 days ago | IN | 0 ETH | 0.00011492 | ||||
Claim Representa... | 20266583 | 201 days ago | IN | 0 ETH | 0.00015284 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21635954 | 10 days ago | 0.009152 ETH | ||||
21196473 | 71 days ago | 0.007216 ETH | ||||
20608761 | 153 days ago | 0.063648 ETH | ||||
20592550 | 156 days ago | 0.00888 ETH | ||||
20554503 | 161 days ago | 0.0408 ETH | ||||
20554416 | 161 days ago | 0.191612 ETH | ||||
20553789 | 161 days ago | 0.008 ETH | ||||
20534763 | 164 days ago | 0.0102 ETH | ||||
20419389 | 180 days ago | 0.00672 ETH | ||||
20364912 | 187 days ago | 0.326368 ETH | ||||
20364797 | 187 days ago | 0.778464 ETH | ||||
20348405 | 190 days ago | 0.006576 ETH | ||||
20342723 | 191 days ago | 0.0064 ETH | ||||
20297761 | 197 days ago | 0.01072 ETH | ||||
20290666 | 198 days ago | 0.0064 ETH | ||||
20288437 | 198 days ago | 0.014048 ETH | ||||
20282440 | 199 days ago | 0.006416 ETH | ||||
20278611 | 200 days ago | 0.00832 ETH | ||||
20273199 | 200 days ago | 0.012 ETH | ||||
20266583 | 201 days ago | 0.484688 ETH | ||||
20255116 | 203 days ago | 0.014416 ETH | ||||
20250227 | 203 days ago | 0.0448 ETH | ||||
20248302 | 204 days ago | 0.0729 ETH | ||||
20246583 | 204 days ago | 2.5 ETH | ||||
20245712 | 204 days ago | 0.23 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TokenStore
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 750 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: NONE pragma solidity ^0.8.21; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "./interfaces/ITokenStore.sol"; import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; import "@pythnetwork/pyth-sdk-solidity/IPyth.sol"; contract TokenStore is ITokenStore, ReentrancyGuard, AccessControl, Pausable { using SafeERC20 for IERC20; address internal constant tokenAddress = 0x8888888888888888888888888888888888888888; address internal constant ethAddress = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; uint256 public constant MULTIPLIER = 1000000000000000000; uint256 public constant precision = 18; uint256 public constant defaultPythThreshold = 28800; // 8h uint256 private _totalDepositAmount; IPyth private _pyth; uint256 private _pythNativeThreshold; bytes32 private _pythNativePriceFeedId; uint256 private _limit; uint256 private _totalSoldTokens; uint256 private _cRepRate = 50; uint256 private _tRepRate = 50; address private _treasury; Status private _saleStatus; Milestone[] private _milestone; uint256 private _currentMilestone; uint256 private _maxDepositAmount; uint256 private _minDepositAmount; bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); bytes32 public constant VERIFIED_ROLE = keccak256("VERIFIED_ROLE"); mapping(address => Stable) private _stables; mapping(address => uint256) private _userTotalBalances; mapping(address => mapping(uint256 => uint256)) private _milestoneBalances; mapping(address => bool) private _verified; mapping(address => Representative) private _reps; mapping(address => address) private _repsUsers; mapping(address => mapping(address => uint256)) private _repBalances; mapping(address => TokenConfig) private _tokenConfig; event DepositedToken( address indexed receiver, address indexed asset, address indexed representative, uint256 size, ITokenStore.Option option, uint256 tokensReleased, uint256 saleMilestone ); event DepositedNative( address indexed receiver, address indexed representative, uint256 size, ITokenStore.Option indexed option, uint256 tokensReleased, uint256 saleMilestone ); event Claimed(address indexed Representative, address indexed asset, uint256 amount); constructor(address treasury_, address[] memory stables_, address pyth_, bytes32 pythNativePriceFeedId_, address[] memory tokens, bytes32[] memory pythIds) { require(treasury_ != address(0), "TokenStore: zero bank address"); require( pyth_ != address(0), "TokenStore: cant set zero addresses" ); require(tokens.length == pythIds.length, "TokenStore: arrays lengths not equals"); _treasury = treasury_; for (uint256 index = 0; index < stables_.length; index++) { require(stables_[index] != address(0), "TokenStore: cant set zero asset address"); _stables[stables_[index]] = Stable({defined: true, total: 0}); } for(uint256 i; i < tokens.length; i++) { _tokenConfig[tokens[i]] = TokenConfig({ defined: true, pythId: pythIds[i], total:0, threshold: defaultPythThreshold }); } _pyth = IPyth(pyth_); _pythNativeThreshold = defaultPythThreshold; _pythNativePriceFeedId = pythNativePriceFeedId_; _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); _grantRole(MANAGER_ROLE, _msgSender()); } function getTreasury() external view returns (address) { return _treasury; } function getMaxDepositAmount() external view returns (uint256) { return _maxDepositAmount; } function getMinimalDepositAmount() external view returns (uint256) { return _minDepositAmount; } function getMilestoneAmount() external view returns (uint256) { return _milestone.length; } function getCurrentMilestoneIndex() external view returns (uint256) { return _currentMilestone; } function getMilestoneInfo(uint256 index_) external view returns (Milestone memory) { return _milestone[index_]; } function getTotalSoldTokens() external view returns (uint256) { return _totalSoldTokens; } function balanceOf(uint256 milestone_, address user_) external view returns (uint256) { return _milestoneBalances[user_][milestone_]; } function representativeBalanceOf(address asset_, address user_) external view returns (uint256) { return _repBalances[user_][asset_]; } function regularDepositLimit(address user_) public view returns (uint256) { uint256 amount = _userTotalBalances[user_]; uint256 limit = _limit; if (isVerified(user_)) { limit = _maxDepositAmount; } return amount < limit ? limit - amount : 0; } function maxDepositLimit(address user_) public view returns (uint256) { uint256 amount = _userTotalBalances[user_]; return amount < _maxDepositAmount ? _maxDepositAmount - amount : 0; } function getLimit() external view returns (uint256) { return _limit; } function getRepresentativeRates() external view returns (uint256, uint256) { return (_cRepRate, _tRepRate); } function getRepresentative(address user_, address rep_) public view returns (address) { Representative memory rep = _reps[_repsUsers[user_]]; if (rep.defined && rep.enabled) { return _repsUsers[user_]; } rep = _reps[rep_]; if (!rep.defined || rep.enabled) { return rep_; } return address(0); } function getRepresentativeRate(address rep_) public view returns (uint256, uint256) { Representative memory rep = _reps[rep_]; if (rep.defined) { return (Math.max(rep.firstRepRate, _cRepRate), Math.max(rep.secondRepRate, _tRepRate)); } return (_cRepRate, _tRepRate); } function isSaleActive() public view returns (bool) { return _saleStatus == Status.Opened; } function isSaleInactive() public view returns (bool) { return _saleStatus == Status.Closed; } function getCurrentMilestonePrice(Option option_) public view returns (uint256) { if (_milestone[_currentMilestone].state == Status.Opened) { return option_ == Option.Short ? _milestone[_currentMilestone].sPrice : _milestone[_currentMilestone].lPrice; } return 0; } function isVerified(address user_) public view returns (bool) { return _verified[user_]; } function open() external onlyRole(DEFAULT_ADMIN_ROLE) { require(_saleStatus == Status.None, "TokenStore: sale already started"); _saleStatus = Status.Opened; } function close() external onlyRole(DEFAULT_ADMIN_ROLE) { require(isSaleActive(), "TokenStore: sale not started"); _saleStatus = Status.Closed; } function toggleAllowedTokens( address[] calldata tokens_, bytes32[] calldata pythIds_, uint256[] calldata thresholds_, bool[] calldata statuses_ ) external onlyRole(DEFAULT_ADMIN_ROLE) { require(tokens_.length == pythIds_.length && tokens_.length == statuses_.length && tokens_.length == thresholds_.length, "TokenStore: arrays lengths not equals"); for(uint256 i; i < tokens_.length; i++) { uint256 oldTotal = _tokenConfig[tokens_[i]].total; _tokenConfig[tokens_[i]] = TokenConfig({ defined: statuses_[i], pythId: pythIds_[i], total: oldTotal, threshold: thresholds_[i] }); } } function setNativePythThreshold(uint256 pythNativeThreshold_) external onlyRole(DEFAULT_ADMIN_ROLE) { _pythNativeThreshold = pythNativeThreshold_; } function getAllowedToken(address token_) external view returns(TokenConfig memory) { return _tokenConfig[token_]; } function setMilestone( uint256 sPrice_, uint256 lPrice_, uint256 supply_ ) external onlyRole(DEFAULT_ADMIN_ROLE) { require(!isSaleInactive(), "TokenStore: sale closed"); _milestone.push( Milestone({ defined: true, state: Status.None, sPrice: sPrice_, lPrice: lPrice_, sold: 0, supply: supply_ }) ); } function setRepresentativeRate( uint256 firstRepRate_, uint256 secondRepRate_ ) external onlyRole(DEFAULT_ADMIN_ROLE) { require(!isSaleInactive(), "TokenStore: sale closed"); require(firstRepRate_ <= 1000, "TokenStore: cant set first rate more then 100%"); require(secondRepRate_ <= 1000, "TokenStore: cant set second rate more then 100%"); _cRepRate = firstRepRate_; _tRepRate = secondRepRate_; } function setupRepresentatives( address[] calldata reps_, uint256[] calldata firstRepRates_, uint256[] calldata secondRepRates_ ) external onlyRole(MANAGER_ROLE) { require(!isSaleInactive(), "TokenStore: sale closed"); require( reps_.length == firstRepRates_.length && reps_.length == secondRepRates_.length, "TokenStore: invalid arrays length setup" ); for (uint256 index = 0; index < reps_.length; index++) { _reps[reps_[index]] = Representative({ defined: true, enabled: true, firstRepRate: firstRepRates_[index], secondRepRate: secondRepRates_[index] }); } } function updateMilestonePrice( uint256 index_, uint256 sPrice_, uint256 lPrice_ ) external onlyRole(DEFAULT_ADMIN_ROLE) { require(!isSaleInactive(), "TokenStore: sale closed"); require(_milestone[index_].defined, "TokenStore: Milestone should be defined"); require(_milestone[index_].state == Status.None, "TokenStore: Milestone should not be started"); _milestone[index_].sPrice = sPrice_; _milestone[index_].lPrice = lPrice_; } function updateMilestoneSupply( uint256 index_, uint256 supply_ ) external onlyRole(DEFAULT_ADMIN_ROLE) { require(!isSaleInactive(), "TokenStore: sale closed"); require(_milestone[index_].defined, "TokenStore: Milestone should be defined"); require(_milestone[index_].state != Status.Closed, "TokenStore: Milestone should not be closed"); require( _milestone[index_].sold < supply_, "TokenStore: new supply must be bigger then sold tokens" ); _milestone[index_].supply = supply_; } function start(uint256 index_) external onlyRole(MANAGER_ROLE) { require(isSaleActive(), "TokenStore: sale not active"); require(_milestone[index_].defined, "TokenStore: Milestone should be defined"); require(_milestone[index_].state == Status.None, "TokenStore: Milestone should not be used"); if (_milestone[_currentMilestone].state == Status.Opened) { _milestone[_currentMilestone].state = Status.Closed; } _milestone[index_].state = Status.Opened; _currentMilestone = index_; } function finishMilestone(uint256 index_) external onlyRole(MANAGER_ROLE) { require(_milestone[index_].defined, "TokenStore: Milestone should be defined"); require(_milestone[index_].state == Status.Opened, "TokenStore: Milestone should be active"); _milestone[index_].state = Status.Closed; } function setVerified(address user_, bool value_) external onlyRole(MANAGER_ROLE) { _verified[user_] = value_; } function setVerifiedBatch( address[] calldata users_, bool[] calldata values_ ) external onlyRole(MANAGER_ROLE) { require(users_.length == values_.length, "TokenStore: invalid arrays length setup"); for (uint256 index = 0; index < users_.length; index++) { _verified[users_[index]] = values_[index]; } } function setMaxDepositAmount(uint256 amount_) external onlyRole(DEFAULT_ADMIN_ROLE) { require(amount_ <= 10000000000000000000000000, "TokenStore: value is too big"); require(amount_ >= _minDepositAmount, "TokenStore: value is too small"); _maxDepositAmount = amount_; } function setMinDepositAmount(uint256 amount_) external onlyRole(DEFAULT_ADMIN_ROLE) { require(amount_ >= 100000000000000000, "TokenStore: value is too small"); require(amount_ <= _maxDepositAmount, "TokenStore: value is too big"); _minDepositAmount = amount_; } function setLimit(uint256 amount_) external onlyRole(DEFAULT_ADMIN_ROLE) { require(amount_ >= _minDepositAmount && amount_ <= _maxDepositAmount, "TokenStore: invalid value"); _limit = amount_; } function setTreasury(address treasury_) external onlyRole(DEFAULT_ADMIN_ROLE) { require(treasury_ != address(0), "TokenStore: zero bank address"); _treasury = treasury_; } function _processPayment( address user_, address asset_, uint256 amount_, uint256 sold_, address rep_, uint256 fReward_, uint256 sReward_ ) private { _userTotalBalances[user_] = _userTotalBalances[user_] + amount_; _totalSoldTokens = _totalSoldTokens + sold_; _milestone[_currentMilestone].sold = _milestone[_currentMilestone].sold + sold_; _milestoneBalances[user_][_currentMilestone] = _milestoneBalances[user_][_currentMilestone] + sold_; if (rep_ != address(0)) { if (!_reps[rep_].defined) { _reps[rep_].defined = true; _reps[rep_].enabled = true; } _repBalances[rep_][asset_] += fReward_; _repBalances[rep_][tokenAddress] += sReward_; _repsUsers[user_] = rep_; } } function enableRepresentative(address rep_) external onlyRole(DEFAULT_ADMIN_ROLE) { require(_reps[rep_].defined, "TokenStore: Representative not defined"); require(!_reps[rep_].enabled, "TokenStore: Representative already enabled"); _reps[rep_].enabled = true; } function disableRepresentative(address rep_) external onlyRole(DEFAULT_ADMIN_ROLE) { require(_reps[rep_].defined, "TokenStore: Representative not defined"); require(_reps[rep_].enabled, "TokenStore: Representative already disabled"); _reps[rep_].enabled = false; } function claimRepresentativeRewards(address[] calldata assets_) external nonReentrant { address rep = _msgSender(); require(assets_.length > 0, "TokenStore: no stables to process"); require(_reps[rep].defined, "TokenStore: Representative not defined"); require(_reps[rep].enabled, "TokenStore: Representative not enabled"); for (uint256 i = 0; i < assets_.length; i++) { address token = assets_[i]; uint256 balance = _repBalances[rep][token]; if (balance == 0) { continue; } _repBalances[rep][token] = 0; if (token == ethAddress) { (bool success, ) = rep.call{value: balance}(""); require(success, "TokenStore: native claim error"); } else { IERC20(token).safeTransfer(rep, balance); } emit Claimed(rep, token, balance); } } function recoverNative() external onlyRole(DEFAULT_ADMIN_ROLE) { uint256 balance = address(this).balance; _msgSender().call{value: balance}(""); } function recoverErc20(address asset_, uint256 amount_) external onlyRole(DEFAULT_ADMIN_ROLE) { IERC20(asset_).safeTransfer(_msgSender(), amount_); } receive() external payable {} // coin seller function pause() external onlyRole(DEFAULT_ADMIN_ROLE) { _pause(); } function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } function depositCollateral( address asset_, uint256 amount_, ITokenStore.Option option_, address representative_ ) external nonReentrant { _deposit(asset_, amount_, option_, _msgSender(), representative_, false); } function depositCollateralFor( address asset_, uint256 amount_, ITokenStore.Option option_, address receiver_, address representative_ ) external nonReentrant onlyRole(VERIFIED_ROLE) { _deposit(asset_, amount_, option_, receiver_, representative_, true); } function depositToken( address asset_, uint256 amount_, ITokenStore.Option option_, address representative_ ) external nonReentrant { _depositToken(asset_, amount_, option_, _msgSender(), representative_, false); } function depositTokenFor( address asset_, uint256 amount_, ITokenStore.Option option_, address receiver_, address representative_ ) external nonReentrant onlyRole(VERIFIED_ROLE) { _depositToken(asset_, amount_, option_, receiver_, representative_, true); } function isStableSupported(address asset_) external view returns (bool) { return _stables[asset_].defined; } function getDepositedByToken(address asset_) external view returns (uint256) { return _stables[asset_].total; } function _deposit( address asset_, uint256 amount_, ITokenStore.Option option_, address receiver_, address representative_, bool isVerified_ ) internal whenNotPaused { require(receiver_ != address(0), "TokenStore: receiver is zero"); require(receiver_ != representative_, "TokenStore: self-referring is disabled"); require(amount_ > 0, "TokenStore: amount is zero"); require(_stables[asset_].defined, "TokenStore: asset is not allowed"); require(isSaleActive(), "TokenStore: sale is already closed"); ITokenStore.Milestone memory milestone = _milestone[_currentMilestone]; require( milestone.state == ITokenStore.Status.Opened, "TokenStore: milestone is not active" ); require( milestone.supply >= milestone.sold + _getSold(asset_, amount_, option_), "TokenStore: milestone allocation exceed" ); uint256 decimals = IERC20Metadata(asset_).decimals(); uint256 funds = (amount_ * MULTIPLIER) / (10 ** decimals); uint256 limit = isVerified_ ? maxDepositLimit(receiver_) : regularDepositLimit(receiver_); require( funds >= _minDepositAmount, "TokenStore: deposit amount is too small" ); require(funds <= limit, "TokenStore: deposit amount is too big"); (address rep, uint256 fTokenFunds, uint256 sTokenFunds) = _getRepresentative( receiver_, asset_, representative_, option_, amount_ ); _process(_msgSender(), asset_, amount_, fTokenFunds); _stables[asset_].total = _stables[asset_].total + amount_; uint256 sold = _getSold(asset_, amount_, option_); uint256 investment = (amount_ * MULTIPLIER) / (10 ** decimals); _processPayment( receiver_, asset_, investment, sold, representative_, fTokenFunds, sTokenFunds ); emit DepositedToken( receiver_, asset_, rep, amount_, option_, sold, _currentMilestone ); } function _depositToken( address asset_, uint256 amount_, ITokenStore.Option option_, address receiver_, address representative_, bool isVerified_ ) internal whenNotPaused { require(receiver_ != address(0), "TokenStore: receiver is zero"); require(receiver_ != representative_, "TokenStore: self-referring is disabled"); require(amount_ > 0, "TokenStore: amount is zero"); require(_tokenConfig[asset_].defined, "TokenStore: token is not configured"); require(isSaleActive(), "TokenStore: sale is already closed"); ITokenStore.Milestone memory milestone = _milestone[_currentMilestone]; require( milestone.state == ITokenStore.Status.Opened, "TokenStore: milestone is not active" ); require( milestone.supply >= milestone.sold + _getSoldTokens(asset_, amount_, option_), "TokenStore: milestone allocation exceed" ); PythStructs.Price memory priceInfo = _pyth.getPriceUnsafe(_tokenConfig[asset_].pythId); require(priceInfo.publishTime > block.timestamp - _tokenConfig[asset_].threshold, "TokenStore: Pyth Oracle price outdated"); uint256 price = uint256(uint64(priceInfo.price)); uint256 tokenDecimals = IERC20Metadata(asset_).decimals(); uint8 priceDecimals = uint8(uint32(-1 * priceInfo.expo)); uint256 funds = (amount_ * price * MULTIPLIER) / (10 ** (priceDecimals + tokenDecimals)); uint256 limit = isVerified_ ? maxDepositLimit(receiver_) : regularDepositLimit(receiver_); require( funds >= _minDepositAmount, "TokenStore: deposit amount is too small" ); require(funds <= limit, "TokenStore: deposit amount is too big"); (address rep, uint256 fTokenFunds, uint256 sTokenFunds) = _getRepresentativeToken( receiver_, asset_, representative_, option_, amount_ ); _process(_msgSender(), asset_, amount_, fTokenFunds); _tokenConfig[asset_].total += amount_; uint256 sold = _getSoldTokens(asset_, amount_, option_); _processPayment( receiver_, asset_, funds, sold, representative_, fTokenFunds, sTokenFunds ); emit DepositedToken( receiver_, asset_, rep, amount_, option_, sold, _currentMilestone ); } function _process(address receiver_, address asset_, uint256 amount_, uint256 reward_) internal { address treasury = _treasury; IERC20(asset_).safeTransferFrom(receiver_, treasury, amount_ - reward_); if (reward_ > 0) { IERC20(asset_).safeTransferFrom(receiver_, address(this), reward_); } } function _getRepresentative( address receiver_, address asset_, address representative_, ITokenStore.Option option_, uint256 amount_ ) internal view returns (address, uint256, uint256) { address representative = getRepresentative(receiver_, representative_); if (representative == address(0)) { return (representative, 0, 0); } (uint256 fReward_, uint256 secondaryReward_) = getRepresentativeRate(representative); uint256 fTokenFunds = (amount_ * fReward_) / 1000; uint256 sTokenFunds = (amount_ * secondaryReward_) / 1000; uint256 sTokenSold = _getSold(asset_, sTokenFunds, option_); return (representative, fTokenFunds, sTokenSold); } function _getRepresentativeToken( address receiver_, address asset_, address representative_, ITokenStore.Option option_, uint256 amount_ ) internal view returns (address, uint256, uint256) { address representative = getRepresentative(receiver_, representative_); if (representative == address(0)) { return (representative, 0, 0); } (uint256 fReward_, uint256 secondaryReward_) = getRepresentativeRate(representative); uint256 fTokenFunds = (amount_ * fReward_) / 1000; uint256 sTokenFunds = (amount_ * secondaryReward_) / 1000; uint256 sTokenSold = _getSoldTokens(asset_, sTokenFunds, option_); return (representative, fTokenFunds, sTokenSold); } function _getSold( address asset_, uint256 amount_, ITokenStore.Option option_ ) internal view returns (uint256) { uint8 decimals = IERC20Metadata(asset_).decimals(); return ((amount_ * 10 ** precision * MULTIPLIER) / 10 ** decimals) / getCurrentMilestonePrice(option_); } function _getSoldTokens( address asset_, uint256 amount_, ITokenStore.Option option_ ) internal view returns (uint256) { PythStructs.Price memory priceInfo = _pyth.getPriceUnsafe(_tokenConfig[asset_].pythId); require(priceInfo.publishTime > block.timestamp - _tokenConfig[asset_].threshold, "TokenStore: Pyth Oracle price outdated"); uint256 price = uint256(uint64(priceInfo.price)); uint8 priceDecimals = uint8(uint32(-1 * priceInfo.expo)); uint8 decimals = IERC20Metadata(asset_).decimals(); return (amount_ * price * MULTIPLIER * MULTIPLIER) / getCurrentMilestonePrice(option_) / (10 ** (priceDecimals + decimals)); } function depositNative( ITokenStore.Option option_, address representative_ ) external payable nonReentrant { _deposit(option_, _msgSender(), representative_, false); } function depositNativeFor( ITokenStore.Option option_, address receiver_, address representative_ ) external payable onlyRole(VERIFIED_ROLE) nonReentrant { _deposit(option_, receiver_, representative_, true); } function getTotalDepositAmount() external view returns (uint256) { return _totalDepositAmount; } function _deposit( ITokenStore.Option option_, address receiver_, address representative_, bool isVerified_ ) internal whenNotPaused { uint256 amount = msg.value; require(receiver_ != address(0), "TokenStore: receiver is zero"); require(receiver_ != representative_, "TokenStore: self-referring is disabled"); require(amount > 0, "TokenStore: amount is zero"); require(isSaleActive(), "TokenStore: sale is already closed"); ITokenStore.Milestone memory milestone = _milestone[_currentMilestone]; require( milestone.state == ITokenStore.Status.Opened, "TokenStore: milestone is not active" ); require( milestone.supply >= milestone.sold + _getSold(amount, option_), "TokenStore: milestone allocation exceed" ); PythStructs.Price memory priceInfo = _pyth.getPriceUnsafe(_pythNativePriceFeedId); require(priceInfo.publishTime > block.timestamp - _pythNativeThreshold, "TokenStore: Pyth Oracle price outdated"); uint8 decimals = uint8(uint32(-1 * priceInfo.expo)); uint256 price = uint256(uint64(priceInfo.price)); uint256 funds = (amount * price * MULTIPLIER) / (10 ** (precision + decimals)); uint256 limit = isVerified_ ? maxDepositLimit(receiver_) : regularDepositLimit(receiver_); require( funds >= _minDepositAmount, "TokenStore: deposit amount is too small" ); require(funds <= limit, "TokenStore: deposit amount is too big"); (address representative, uint256 coinFunds, uint256 tokenFunds) = _getRepresentative( receiver_, representative_, option_, amount ); _process(amount, coinFunds); _totalDepositAmount = _totalDepositAmount + amount; uint256 sold = _getSold(amount, option_); uint256 investment = (amount * price * MULTIPLIER) / (10 ** (precision + decimals)); _processPayment( receiver_, ethAddress, investment, sold, representative, coinFunds, tokenFunds ); emit DepositedNative( receiver_, representative, amount, option_, sold, _currentMilestone ); } function _process(uint256 amount_, uint256 reward_) internal { address treasury = _treasury; (bool success, ) = treasury.call{value: amount_ - reward_}(""); require(success, "TokenStore: transfer is not processed"); } function _getRepresentative( address receiver_, address representative_, ITokenStore.Option option_, uint256 amount_ ) internal view returns (address, uint256, uint256) { address representative = getRepresentative(receiver_, representative_); if (representative == address(0)) { return (representative, 0, 0); } (uint256 fRate, uint256 sRate) = getRepresentativeRate(representative); uint256 coinFunds = (amount_ * fRate) / 1000; uint256 tokenFunds = (amount_ * sRate) / 1000; uint256 tokenSold = _getSold(tokenFunds, option_); return (representative, coinFunds, tokenSold); } function _getSold( uint256 amount_, ITokenStore.Option option_ ) internal view returns (uint256) { PythStructs.Price memory priceInfo = _pyth.getPriceUnsafe(_pythNativePriceFeedId); require(priceInfo.publishTime > block.timestamp - _pythNativeThreshold, "TokenStore: Pyth Oracle price outdated"); uint8 decimals = uint8(uint32(-1 * priceInfo.expo)); uint256 price = uint256(uint64(priceInfo.price)); return (amount_ * price * MULTIPLIER) / getCurrentMilestonePrice(option_) / (10 ** decimals); } }
// 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 // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 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, an admin role * bearer except when using {AccessControl-_setupRole}. */ 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.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the 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.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 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. */ 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. */ 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. */ 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 Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { 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 silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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 AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 * {FailedInnerCall} 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 AddressInsufficientBalance(address(this)); } (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 {FailedInnerCall}) 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 {FailedInnerCall} 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 {FailedInnerCall}. */ 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// 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.0.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 ERC165 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) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 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) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "./PythStructs.sol"; import "./IPythEvents.sol"; /// @title Consume prices from the Pyth Network (https://pyth.network/). /// @dev Please refer to the guidance at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how to consume prices safely. /// @author Pyth Data Association interface IPyth is IPythEvents { /// @notice Returns the period (in seconds) that a price feed is considered valid since its publish time function getValidTimePeriod() external view returns (uint validTimePeriod); /// @notice Returns the price and confidence interval. /// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds. /// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPrice( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price and confidence interval. /// @dev Reverts if the EMA price is not available. /// @param id The Pyth Price Feed ID of which to fetch the EMA price and confidence interval. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPrice( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the price of a price feed without any sanity checks. /// @dev This function returns the most recent price update in this contract without any recency checks. /// This function is unsafe as the returned price update may be arbitrarily far in the past. /// /// Users of this function should check the `publishTime` in the price to ensure that the returned price is /// sufficiently recent for their application. If you are considering using this function, it may be /// safer / easier to use either `getPrice` or `getPriceNoOlderThan`. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPriceUnsafe( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the price that is no older than `age` seconds of the current time. /// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently /// recently. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPriceNoOlderThan( bytes32 id, uint age ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks. /// @dev This function returns the same price as `getEmaPrice` in the case where the price is available. /// However, if the price is not recent this function returns the latest available price. /// /// The returned price can be from arbitrarily far in the past; this function makes no guarantees that /// the returned price is recent or useful for any particular application. /// /// Users of this function should check the `publishTime` in the price to ensure that the returned price is /// sufficiently recent for their application. If you are considering using this function, it may be /// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPriceUnsafe( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds /// of the current time. /// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently /// recently. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPriceNoOlderThan( bytes32 id, uint age ) external view returns (PythStructs.Price memory price); /// @notice Update price feeds with given update messages. /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// Prices will be updated if they are more recent than the current stored prices. /// The call will succeed even if the update is not the most recent. /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid. /// @param updateData Array of price update data. function updatePriceFeeds(bytes[] calldata updateData) external payable; /// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is /// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the /// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`. /// /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// /// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime /// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have /// a newer or equal publish time than the given publish time, it will reject the transaction to save gas. /// Otherwise, it calls updatePriceFeeds method to update the prices. /// /// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid. /// @param updateData Array of price update data. /// @param priceIds Array of price ids. /// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]` function updatePriceFeedsIfNecessary( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes ) external payable; /// @notice Returns the required fee to update an array of price updates. /// @param updateData Array of price update data. /// @return feeAmount The required fee in Wei. function getUpdateFee( bytes[] calldata updateData ) external view returns (uint feeAmount); /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published /// within `minPublishTime` and `maxPublishTime`. /// /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price; /// otherwise, please consider using `updatePriceFeeds`. This method may store the price updates on-chain, if they /// are more recent than the current stored prices. /// /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// /// /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is /// no update for any of the given `priceIds` within the given time range. /// @param updateData Array of price update data. /// @param priceIds Array of price ids. /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`. /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`. /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order). function parsePriceFeedUpdates( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64 minPublishTime, uint64 maxPublishTime ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds); /// @notice Similar to `parsePriceFeedUpdates` but ensures the updates returned are /// the first updates published in minPublishTime. That is, if there are multiple updates for a given timestamp, /// this method will return the first update. This method may store the price updates on-chain, if they /// are more recent than the current stored prices. /// /// /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is /// no update for any of the given `priceIds` within the given time range and uniqueness condition. /// @param updateData Array of price update data. /// @param priceIds Array of price ids. /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`. /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`. /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order). function parsePriceFeedUpdatesUnique( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64 minPublishTime, uint64 maxPublishTime ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @title IPythEvents contains the events that Pyth contract emits. /// @dev This interface can be used for listening to the updates for off-chain and testing purposes. interface IPythEvents { /// @dev Emitted when the price feed with `id` has received a fresh update. /// @param id The Pyth Price Feed ID. /// @param publishTime Publish time of the given price update. /// @param price Price of the given price update. /// @param conf Confidence interval of the given price update. event PriceFeedUpdate( bytes32 indexed id, uint64 publishTime, int64 price, uint64 conf ); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; contract PythStructs { // A price with a degree of uncertainty, represented as a price +- a confidence interval. // // The confidence interval roughly corresponds to the standard error of a normal distribution. // Both the price and confidence are stored in a fixed-point numeric representation, // `x * (10^expo)`, where `expo` is the exponent. // // Please refer to the documentation at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how // to how this price safely. struct Price { // Price int64 price; // Confidence interval around the price uint64 conf; // Price exponent int32 expo; // Unix timestamp describing when the price was published uint publishTime; } // PriceFeed represents a current aggregate price from pyth publisher feeds. struct PriceFeed { // The price ID. bytes32 id; // Latest available price Price price; // Latest available exponentially-weighted moving average price Price emaPrice; } }
// SPDX-License-Identifier: NONE pragma solidity ^0.8.21; interface ITokenStore { enum Option { Short, Long } enum Status { None, Opened, Closed } struct TokenConfig { bool defined; bytes32 pythId; uint256 total; uint256 threshold; } struct Stable { bool defined; uint256 total; } struct Milestone { bool defined; Status state; uint256 sPrice; uint256 lPrice; uint256 sold; uint256 supply; } struct Representative { bool defined; bool enabled; uint256 firstRepRate; uint256 secondRepRate; } function isSaleActive() external view returns (bool); function getMilestoneInfo(uint256 index_) external view returns (Milestone memory); function getCurrentMilestoneIndex() external view returns (uint256); function regularDepositLimit(address receiver_) external view returns (uint256); function maxDepositLimit(address receiver_) external view returns (uint256); function getMinimalDepositAmount() external view returns (uint256); function getRepresentative(address receiver_, address ambasador_) external view returns (address); function getRepresentativeRate(address ambasador_) external view returns (uint256, uint256); function getCurrentMilestonePrice(Option option_) external view returns (uint256); function getTreasury() external view returns (address); function balanceOf(uint256 round_, address user_) external view returns (uint256); function representativeBalanceOf(address asset_, address user_) external view returns (uint256); function getMilestoneAmount() external view returns (uint256); }
{ "optimizer": { "enabled": true, "runs": 750 }, "viaIR": true, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"treasury_","type":"address"},{"internalType":"address[]","name":"stables_","type":"address[]"},{"internalType":"address","name":"pyth_","type":"address"},{"internalType":"bytes32","name":"pythNativePriceFeedId_","type":"bytes32"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"bytes32[]","name":"pythIds","type":"bytes32[]"}],"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":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"Representative","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"representative","type":"address"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":true,"internalType":"enum ITokenStore.Option","name":"option","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"tokensReleased","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"saleMilestone","type":"uint256"}],"name":"DepositedNative","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"representative","type":"address"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":false,"internalType":"enum ITokenStore.Option","name":"option","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"tokensReleased","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"saleMilestone","type":"uint256"}],"name":"DepositedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFIED_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"milestone_","type":"uint256"},{"internalType":"address","name":"user_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets_","type":"address[]"}],"name":"claimRepresentativeRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"close","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultPythThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"enum ITokenStore.Option","name":"option_","type":"uint8"},{"internalType":"address","name":"representative_","type":"address"}],"name":"depositCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"enum ITokenStore.Option","name":"option_","type":"uint8"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"address","name":"representative_","type":"address"}],"name":"depositCollateralFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITokenStore.Option","name":"option_","type":"uint8"},{"internalType":"address","name":"representative_","type":"address"}],"name":"depositNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum ITokenStore.Option","name":"option_","type":"uint8"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"address","name":"representative_","type":"address"}],"name":"depositNativeFor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"enum ITokenStore.Option","name":"option_","type":"uint8"},{"internalType":"address","name":"representative_","type":"address"}],"name":"depositToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"enum ITokenStore.Option","name":"option_","type":"uint8"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"address","name":"representative_","type":"address"}],"name":"depositTokenFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rep_","type":"address"}],"name":"disableRepresentative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rep_","type":"address"}],"name":"enableRepresentative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"finishMilestone","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"name":"getAllowedToken","outputs":[{"components":[{"internalType":"bool","name":"defined","type":"bool"},{"internalType":"bytes32","name":"pythId","type":"bytes32"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"threshold","type":"uint256"}],"internalType":"struct ITokenStore.TokenConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentMilestoneIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ITokenStore.Option","name":"option_","type":"uint8"}],"name":"getCurrentMilestonePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"}],"name":"getDepositedByToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMilestoneAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"getMilestoneInfo","outputs":[{"components":[{"internalType":"bool","name":"defined","type":"bool"},{"internalType":"enum ITokenStore.Status","name":"state","type":"uint8"},{"internalType":"uint256","name":"sPrice","type":"uint256"},{"internalType":"uint256","name":"lPrice","type":"uint256"},{"internalType":"uint256","name":"sold","type":"uint256"},{"internalType":"uint256","name":"supply","type":"uint256"}],"internalType":"struct ITokenStore.Milestone","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinimalDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user_","type":"address"},{"internalType":"address","name":"rep_","type":"address"}],"name":"getRepresentative","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rep_","type":"address"}],"name":"getRepresentativeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRepresentativeRates","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":[],"name":"getTotalDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalSoldTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"isSaleActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSaleInactive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"}],"name":"isStableSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user_","type":"address"}],"name":"isVerified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user_","type":"address"}],"name":"maxDepositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"open","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"precision","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"recoverErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user_","type":"address"}],"name":"regularDepositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"asset_","type":"address"},{"internalType":"address","name":"user_","type":"address"}],"name":"representativeBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"setMaxDepositAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"sPrice_","type":"uint256"},{"internalType":"uint256","name":"lPrice_","type":"uint256"},{"internalType":"uint256","name":"supply_","type":"uint256"}],"name":"setMilestone","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"setMinDepositAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pythNativeThreshold_","type":"uint256"}],"name":"setNativePythThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"firstRepRate_","type":"uint256"},{"internalType":"uint256","name":"secondRepRate_","type":"uint256"}],"name":"setRepresentativeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"treasury_","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user_","type":"address"},{"internalType":"bool","name":"value_","type":"bool"}],"name":"setVerified","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users_","type":"address[]"},{"internalType":"bool[]","name":"values_","type":"bool[]"}],"name":"setVerifiedBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"reps_","type":"address[]"},{"internalType":"uint256[]","name":"firstRepRates_","type":"uint256[]"},{"internalType":"uint256[]","name":"secondRepRates_","type":"uint256[]"}],"name":"setupRepresentatives","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"start","outputs":[],"stateMutability":"nonpayable","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":"tokens_","type":"address[]"},{"internalType":"bytes32[]","name":"pythIds_","type":"bytes32[]"},{"internalType":"uint256[]","name":"thresholds_","type":"uint256[]"},{"internalType":"bool[]","name":"statuses_","type":"bool[]"}],"name":"toggleAllowedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index_","type":"uint256"},{"internalType":"uint256","name":"sPrice_","type":"uint256"},{"internalType":"uint256","name":"lPrice_","type":"uint256"}],"name":"updateMilestonePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index_","type":"uint256"},{"internalType":"uint256","name":"supply_","type":"uint256"}],"name":"updateMilestoneSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234620004685762004c8c803803806200001d816200046d565b92833981019060c0818303126200046857620000398162000493565b60208201519091906001600160401b0381116200046857836200005e918301620004c0565b926200006d6040830162000493565b90606083015193608084015160018060401b03811162000468578262000095918601620004c0565b60a085015190946001600160401b0382116200046857019180601f8401121562000468578251620000d0620000ca82620004a8565b6200046d565b9360208086848152019260051b8201019283116200046857602001905b828210620004575750506001600055506002805460ff1916905560326009819055600a556001600160a01b0316801562000412576001600160a01b03831615620003c15783518251036200036e57600b80546001600160a01b03191691909117905560005b855181101562000264576001600160a01b036200017082886200054c565b5116156200020f5760408051919082018083116001600160401b0390911117620001f957816040620001f393016040526001815260016020820160008152818060a01b03620001c0858c6200054c565b51166000526010602052620001e9604060002093511515849060ff801983541691151516179055565b5191015562000526565b62000152565b634e487b7160e01b600052604160045260246000fd5b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a2063616e7420736574207a65726f206173736574206044820152666164647265737360c81b6064820152608490fd5b508360005b845181101562000321576200027f81846200054c565b516040519091906001600160401b036080820190811190821117620001f95760036200031b9360808301604052600183526020830190815260408301600081526060840191617080835260018060a01b03620002dc878d6200054c565b5116600052601760205262000305604060002095511515869060ff801983541691151516179055565b5160018501555160028401555191015562000526565b62000269565b50600480546001600160a01b0319166001600160a01b038516179055617080600555600655620003513362000577565b506200035d33620005f8565b506040516145d090816200069c8239f35b60405162461bcd60e51b815260206004820152602560248201527f546f6b656e53746f72653a20617272617973206c656e67746873206e6f7420656044820152647175616c7360d81b6064820152608490fd5b60405162461bcd60e51b815260206004820152602360248201527f546f6b656e53746f72653a2063616e7420736574207a65726f2061646472657360448201526273657360e81b6064820152608490fd5b60405162461bcd60e51b815260206004820152601d60248201527f546f6b656e53746f72653a207a65726f2062616e6b20616464726573730000006044820152606490fd5b8151815260209182019101620000ed565b600080fd5b6040519190601f01601f191682016001600160401b03811183821017620001f957604052565b51906001600160a01b03821682036200046857565b6001600160401b038111620001f95760051b60200190565b9080601f830112156200046857815190602091620004e2620000ca82620004a8565b93838086848152019260051b82010192831162000468578301905b8282106200050c575050505090565b8380916200051a8462000493565b815201910190620004fd565b6000198114620005365760010190565b634e487b7160e01b600052601160045260246000fd5b8051821015620005615760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b031660008181527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602052604081205490919060ff16620005f45781805260016020526040822081835260205260408220600160ff19825416179055339160008051602062004c6c8339815191528180a4600190565b5090565b6001600160a01b031660008181527ffdb122eb892c6b3193f8499f050265ce5458caab5f6480270d8972921f24f42960205260408120549091907f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b089060ff16620006965780835260016020526040832082845260205260408320600160ff1982541617905560008051602062004c6c833981519152339380a4600190565b50509056fe6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c918262ff3b9214612e0b5750816301ffc9a714612db5578163059f8b1614612d925781630790241914612d565781630af6e01a14612cb5578163248a9ca314612c8b57816327ea6f2b14612c0557816329bf4077146129cb5781632a80cda3146129875781632f2ff15d1461295d5781632f362b811461270c57816336568abe146126c65781633656eec2146126865781633b19e84a1461265e5781633c9b97fc1461263f5781633edd9262146125655781633f4ba83a146124fb578163403cca7a146122b357816343d726d614612220578163564566a8146122035781635726a356146121e4578163590d889a146121a657816359b7aa351461216b57816359be5e451461214c5781635a54db86146121225781635c975abb146120fe57816361fd6545146120e15781636a30c1e9146120bc5781636eeb6dac1461208c578163738a8ce61461205457816377fe1f2414611da95781638456cb5914611d4e57816385b7583d14611d065781638886789314611c1a5781638d8e1ad714611bf45781638ed8409e14611bce57816391d1485414611b8857816395805dad14611a0e57816399e37f1f146118bb5781639a0a1504146117ee5781639a4eb422146116935781639c46e68e146115b65781639cf5c6131461155c578163a14e3cb114611451578163a217fddf14611436578163a70ef24f14611417578163b295a00e146113f8578163b7ea0d12146111f7578163b9209e33146111bb578163ba12897b14610e97578163bac34b9214610b43578163c3d3df5814610a29578163c4511c6a146109e2578163d3b5dc3b146109c6578163d547741f14610987578163d58c434114610953578163d6d65f3d14610934578163d9465dbb14610912578163e84112ab146108f3578163ea1ea81f146108cd578163ec87621c14610892578163f0f44260146107f9578163fa5b2cf514610737578163fcfff16f14610689578163fde0735b14610343575063ff32de1c146103075780610012565b3461033f57602036600319011261033f576001816020936001600160a01b0361032e612eb3565b168152601085522001549051908152f35b5080fd5b919050606036600319011261068557813591600283101561068157610366612ece565b916044356001600160a01b03918282169384830361067d5761038661302d565b61038e61398f565b6103966139b2565b6103b0848716956103a88715156139d0565b861415613a1c565b6103bb341515613a77565b6103cb6103c6613545565b613ac3565b6103df6103d9600d54613274565b506132c5565b6020810151600381101561066a57906103fd60016104219314613b1a565b61041a608060a08301519201516104148b346144ca565b90613b72565b1115613b7f565b8381541690608060065460248551809581936396834ad360e01b8352868301525afa918215610660578992610630575b5061046c606083015161046660055442613332565b10614061565b67ffffffffffffffff60ff6104868585015160030b6140bc565b16925116966104958834613c0a565b94670de0b6b3a7640000938487029680880486149015171561061d57601201958660121161061d57906104f66104d76104ff936104d18a613c1d565b90613c2b565b6104e0856133a5565b906104ef600f54821015613c4b565b1115613cbd565b8a349184614473565b94919690938c8080808c600b54166105178a34613332565b905af161052261382d565b50156105cc5761053434600354613b72565b60035561054b6105448d346144ca565b9b34613c0a565b8381029381850414901517156105b9575092868a61059d9461059760609a98956104d17fff61679fd42b9ad16062cd1c3719eefccc8fcec5083eb954c52d23841a23e36e9d9b99613c1d565b90613d3b565b600d549080519734895260208901528701521693a46001815580f35b634e487b7160e01b8d526011905260248cfd5b608490602088519162461bcd60e51b8352820152602560248201527f546f6b656e53746f72653a207472616e73666572206973206e6f742070726f63604482015264195cdcd95960da1b6064820152fd5b634e487b7160e01b8c526011845260248cfd5b61065291925060803d8111610659575b61064a8183613252565b810190613ffe565b9038610451565b503d610640565b83513d8b823e3d90fd5b634e487b7160e01b8a526021835260248afd5b8780fd5b8380fd5b8280fd5b9050346106855782600319360112610685576106a3612fd5565b600b549160ff8360a01c166003811015610724576106e157837401000000000000000000000000000000000000000060ff60a01b19851617600b5580f35b906020606492519162461bcd60e51b8352820152602060248201527f546f6b656e53746f72653a2073616c6520616c726561647920737461727465646044820152fd5b634e487b7160e01b855260218352602485fd5b90503461068557602036600319011261068557803591610755613089565b61076b60ff61076385613274565b5054166136c8565b60ff61077684613274565b505460081c166003811015610724576001036107a7578361079684613274565b50805461ff00191661020017905580f35b906020608492519162461bcd60e51b8352820152602660248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c642062652060448201526561637469766560d01b6064820152fd5b905034610685576020366003190112610685576001600160a01b0361081c612eb3565b610824612fd5565b1691821561084f57505073ffffffffffffffffffffffffffffffffffffffff19600b541617600b5580f35b906020606492519162461bcd60e51b8352820152601d60248201527f546f6b656e53746f72653a207a65726f2062616e6b20616464726573730000006044820152fd5b50503461033f578160031936011261033f57602090517f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088152f35b50503461033f578160031936011261033f576020906108ea61355d565b90519015158152f35b50503461033f578160031936011261033f57602090600c549051908152f35b83903461033f57602036600319011261033f5761092d612fd5565b3560055580f35b50503461033f578160031936011261033f57602090600d549051908152f35b9050346106855760203660031901126106855735916002831015610984575061097d602092613575565b9051908152f35b80fd5b919050346106855780600319360112610685576109c291356109bd60016109ac612ece565b9383875281602052862001546130e5565b61318c565b5080f35b50503461033f578160031936011261033f576020905160128152f35b83903461033f57602036600319011261033f57356109fe612fd5565b610a156a084595161401484a00000082111561373a565b610a23600f54821015613786565b600e5580f35b9190503461068557610a3a36612fbf565b929091610a45612fd5565b610a56610a5061355d565b1561360a565b6103e8808411610ada578411610a71575050600955600a5580f35b906020608492519162461bcd60e51b8352820152602f60248201527f546f6b656e53746f72653a2063616e7420736574207365636f6e64207261746560448201527f206d6f7265207468656e203130302500000000000000000000000000000000006064820152fd5b815162461bcd60e51b8152602081850152602e60248201527f546f6b656e53746f72653a2063616e742073657420666972737420726174652060448201527f6d6f7265207468656e20313030250000000000000000000000000000000000006064820152608490fd5b90503461068557610b5336612f57565b949195610b6193919361398f565b610b6961302d565b610b716139b2565b6001600160a01b039384811695610b898715156139d0565b610b97868916881415613a1c565b610ba2841515613a77565b85811697888b526020956017875260ff858d20541615610e4857610bc76103c6613545565b610bd56103d9600d54613274565b878101516003811015610e355790610bf26001610c0b9314613b1a565b61041a8d610414608060a0850151940151918b896142ba565b8b888254168b82526017895260806001888420015460248951809481936396834ad360e01b8352888301525afa908115610e2b579082918d9391610e0d575b50610c6a606082015184845260178c5261046660038b8620015442613332565b838a67ffffffffffffffff835116948a519283809263313ce56760e01b82525afa928315610e0257908b8a939294610dc4575b5050610cb3610cbb9260ff92015160030b6140bc565b169289613c0a565b92670de0b6b3a764000093848102948186041490151715610db15750918d939160ff8d9416610ce991613b72565b610cf290613c1d565b610cfb91613c2b565b94868d89610d08846133a5565b600f548a1015610d1790613c4b565b891115610d2390613cbd565b610d2f918589866141bf565b96919b909588878d3392610d42936140d0565b8252601790522060020188815490610d5991613b72565b9055610d668d89876142ba565b95610d72958792613eaa565b600d5491519485941697610d869385613d17565b037f176c329b62e92f50c6c9db5ca025ab96129e1dd260177211150f772adf0ef5e291a46001815580f35b634e487b7160e01b8f526011905260248efd5b60ff92945092610df0610cb39285610cbb96903d10610dfb575b610de88183613252565b810190613bf1565b94925092508b610c9d565b503d610dde565b8951903d90823e3d90fd5b610e25915060803d81116106595761064a8183613252565b38610c4a565b87513d84823e3d90fd5b634e487b7160e01b8e526021835260248efd5b845162461bcd60e51b8152908101879052602360248201527f546f6b656e53746f72653a20746f6b656e206973206e6f7420636f6e666967756044820152621c995960ea1b6064820152608490fd5b9190503461068557610ea836612f15565b610eb79592939594919461398f565b610ebf6139b2565b610eca3315156139d0565b6001600160a01b0392610ee1848316331415613a1c565b610eec851515613a77565b8387168852601760205260ff83892054161561116c57610f0d6103c6613545565b610f1b6103d9600d54613274565b6020810151600381101561066a5790610f396001610f519314613b1a565b61041a608060a08301519201516104148a8a8d6142ba565b838154168488168952601760205260806001858b20015460248651809481936396834ad360e01b8352878301525afa908115611162578991611144575b50610fb16060820151868a168b5260176020526104666003878d20015442613332565b8051845163313ce56760e01b815267ffffffffffffffff9091169160208285818a8e165afa91821561113a579086918c9361110c575b50610ffc6110049260ff92015160030b6140bc565b169288613c0a565b92670de0b6b3a7640000938481029481860414901517156110f957506110da89886110ae966002898f8c8f98867f176c329b62e92f50c6c9db5ca025ab96129e1dd260177211150f772adf0ef5e29f9e9b6110ef9d6104d16110706110759360ff6110a1971690613b72565b613c1d565b9a6110998c61109161108633613355565b91600f541115613c4b565b8d1115613cbd565b878a336141bf565b98919d90809883336140d0565b168152601760205220016110c38c8254613b72565b90558c6110d18d8d836142ba565b95869133613eaa565b84600d54925195869516991697339785613d17565b0390a46001815580f35b634e487b7160e01b8b526011905260248afd5b60ff91935061100492611130610ffc9260203d602011610dfb57610de88183613252565b9492509250610fe7565b86513d8d823e3d90fd5b61115c915060803d81116106595761064a8183613252565b38610f8e565b84513d8b823e3d90fd5b608490602084519162461bcd60e51b8352820152602360248201527f546f6b656e53746f72653a20746f6b656e206973206e6f7420636f6e666967756044820152621c995960ea1b6064820152fd5b50503461033f57602036600319011261033f5760ff816020936001600160a01b036111e4612eb3565b1681526013855220541690519015158152f35b919050346106855760803660031901126106855767ffffffffffffffff9180358381116113f45761122b9036908301612ee4565b916024358581116113f0576112439036908301612ee4565b94906044358781116113ec5761125c9036908501612ee4565b9390976064359081116113e8576112769036908301612ee4565b959091611281612fd5565b888814806113df575b806113d6575b156113855750895b8a8882106112a35780f35b88828989898f958f968a878b888f94816001600160a01b039485916112c891866135d9565b6112d1906135e9565b168752816017968160209789895260029e8f8d8d2001549e6112f2926135d9565b6112fb906135fd565b9f611305926135d9565b3599611310926135d9565b359a87519c61131e8e613236565b15158d52848d01988952878d01998a5260608d019b8c5261133e926135d9565b611347906135e9565b16835252209451151561136690869060ff801983541691151516179055565b5160018501555190830155519060030155611380906135ca565b611298565b608490602086519162461bcd60e51b8352820152602560248201527f546f6b656e53746f72653a20617272617973206c656e67746873206e6f7420656044820152647175616c7360d81b6064820152fd5b50858814611290565b5086881461128a565b8980fd5b8880fd5b8680fd5b8480fd5b50503461033f578160031936011261033f576020906007549051908152f35b50503461033f578160031936011261033f57602090600f549051908152f35b50503461033f578160031936011261033f5751908152602090f35b9050346106855761146136612fa5565b91939061146c612fd5565b611477610a5061355d565b81519461148386613204565b600186526020860192878452860190815260608601918252608086019287845260a08701948552600c5468010000000000000000811015611549578060016114ce9201600c55613274565b979097611537576114ee90511515889060ff801983541691151516179055565b5160038110156115245761ff0087549160081b169061ff0019161786555160018601555160028501555160038401555191015580f35b634e487b7160e01b885260218652602488fd5b634e487b7160e01b8952888752602489fd5b634e487b7160e01b895260418752602489fd5b50503461033f578060031936011261033f57611576612eb3565b90602435908115158203610681576001600160a01b036115b393611598613089565b168452601360205283209060ff801983541691151516179055565b80f35b905034610685576020366003190112610685576001600160a01b036115d9612eb3565b6115e1612fd5565b169081845260146020526115fa60ff84862054166137d2565b818452601460205260ff8385205460081c1661162a5750825260146020528120805461ff00191661010017905580f35b608490602084519162461bcd60e51b8352820152602a60248201527f546f6b656e53746f72653a20526570726573656e74617469766520616c72656160448201527f647920656e61626c6564000000000000000000000000000000000000000000006064820152fd5b905034610685576116a336612fbf565b926116ac612fd5565b6116b7610a5061355d565b6116c560ff61076384613274565b60ff6116d083613274565b505460081c1660038110156117db57600214611773578360036116f284613274565b500154101561170b575061170590613274565b50015580f35b5162461bcd60e51b8152602081840152603660248201527f546f6b656e53746f72653a206e657720737570706c79206d757374206265206260448201527f6967676572207468656e20736f6c6420746f6b656e73000000000000000000006064820152608490fd5b5162461bcd60e51b8152602081840152602a60248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c64206e6f7460448201527f20626520636c6f736564000000000000000000000000000000000000000000006064820152608490fd5b634e487b7160e01b865260218452602486fd5b90503461068557816003193601126106855767ffffffffffffffff9181358381116113f4576118209036908401612ee4565b9390926024359182116118b75761183991369101612ee4565b611844949194613089565b61184f818314613656565b855b82811061185c578680f35b806118ad6118766118716118b294868b6135d9565b6135fd565b6001600160a01b0361189161188c85898c6135d9565b6135e9565b168a526013602052868a209060ff801983541691151516179055565b6135ca565b611851565b8580fd5b9190503461068557606090816003193601126106815767ffffffffffffffff83358181116118b7576118f09036908601612ee4565b93909260243583811161067d5761190a9036908801612ee4565b9390966044359182116113ec5761192391369101612ee4565b909361192d613089565b611938610a5061355d565b80871480611a05575b61194a90613656565b88805b888110611958575080f35b8060028a8a8a8a8f8b6119fe9960146119828a8f8f8261197b916119db996135d9565b35986135d9565b35976001600160a01b036119c061188c86519d8e946119a086613236565b60019c8d9b8c88526020978881019d8e528b81019e8f52019e8f526135d9565b168352522096511515879060ff801983541691151516179055565b51855461ff00191690151560081b61ff00161785555190840155519101556135ca565b899061194d565b50868214611941565b90503461068557602036600319011261068557803591611a2c613089565b611a34613545565b15611b4557611a4760ff61076385613274565b60ff611a5284613274565b505460081c16600381101561072457611adc5750600d549060ff611a7583613274565b505460081c16906003821015611ac95750600114611aac575b50611a9881613274565b50805461ff001916610100179055600d5580f35b611ab590613274565b50805461ff00191661020017905538611a8e565b634e487b7160e01b855260219052602484fd5b906020608492519162461bcd60e51b8352820152602860248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c64206e6f7460448201527f20626520757365640000000000000000000000000000000000000000000000006064820152fd5b906020606492519162461bcd60e51b8352820152601b60248201527f546f6b656e53746f72653a2073616c65206e6f742061637469766500000000006044820152fd5b9050346106855781600319360112610685578160209360ff92611ba9612ece565b90358252600186526001600160a01b0383832091168252855220541690519015158152f35b50503461033f57602036600319011261033f5760209061097d611bef612eb3565b613355565b50503461033f57602036600319011261033f5760209061097d611c15612eb3565b6133a5565b9190503461068557611c2b36612fa5565b93909192611c37612fd5565b611c42610a5061355d565b611c5060ff61076386613274565b60ff611c5b85613274565b505460081c166003811015611cf357611c8a57505081611705916001611c82600295613274565b500155613274565b906020608492519162461bcd60e51b8352820152602b60248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c64206e6f7460448201527f20626520737461727465640000000000000000000000000000000000000000006064820152fd5b634e487b7160e01b875260218352602487fd5b50503461033f578060031936011261033f5780602092611d24612eb3565b6001600160a01b0380611d35612ece565b1683526016865283832091168252845220549051908152f35b50503461033f578160031936011261033f5760207f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25891611d8c612fd5565b611d946139b2565b600160ff19600254161760025551338152a180f35b90508160031936011261068557803591600283101561068157611dca612ece565b611dd261398f565b611dda6139b2565b611de53315156139d0565b6001600160a01b0391611dfc838316331415613a1c565b611e07341515613a77565b611e126103c6613545565b611e206103d9600d54613274565b602081015160038110156115245790611e3e6001611e559314613b1a565b61041a608060a083015192015161041489346144ca565b82845416608060065460248451809481936396834ad360e01b83528a8301525afa90811561204a57879161202c575b50611e99606082015161046660055442613332565b67ffffffffffffffff60ff611eb38484015160030b6140bc565b1691511694611ec28634613c0a565b93670de0b6b3a764000092838602958087048514901517156120195760120194856012116120195790611f07611efe611f10936104d189613c1d565b6104e033613355565b88349133614473565b93919590928a8080808b600b5416611f288934613332565b905af1611f3361382d565b5015611fc857611f4534600354613b72565b600355611f5c611f558b346144ca565b9934613c0a565b8381029381850414901517156110f9575087611f81611f879594936104d18994613c1d565b33613d3b565b600d5490805194348652602086015284015216907fff61679fd42b9ad16062cd1c3719eefccc8fcec5083eb954c52d23841a23e36e60603392a46001815580f35b608490602087519162461bcd60e51b8352820152602560248201527f546f6b656e53746f72653a207472616e73666572206973206e6f742070726f63604482015264195cdcd95960da1b6064820152fd5b634e487b7160e01b8a526011835260248afd5b612044915060803d81116106595761064a8183613252565b38611e84565b82513d89823e3d90fd5b50503461033f57366003190112610984576115b3612070612eb3565b612078612fd5565b602435906001600160a01b0333911661386d565b82843461098457602036600319011261098457506120b06120ab612eb3565b6134bb565b82519182526020820152f35b82843461098457806003193601126109845750600954600a5482519182526020820152f35b50503461033f578160031936011261033f57602090516170808152f35b50503461033f578160031936011261033f5760209060ff6002541690519015158152f35b833461098457806003193601126109845761213b612fd5565b8080808047335af1506109c261382d565b50503461033f578160031936011261033f576020906008549051908152f35b50503461033f578160031936011261033f57602090517f4f72063d6dc4cf4bb4e008e0815997320f78a862b3e71fe66fa9ae685d1cd12f8152f35b50503461033f578060031936011261033f576020906001600160a01b036121dc6121ce612eb3565b6121d6612ece565b906133d2565b915191168152f35b50503461033f578160031936011261033f57602090600e549051908152f35b50503461033f578160031936011261033f576020906108ea613545565b9190503461068557826003193601126106855761223b612fd5565b612243613545565b1561227057827402000000000000000000000000000000000000000060ff60a01b19600b541617600b5580f35b906020606492519162461bcd60e51b8352820152601c60248201527f546f6b656e53746f72653a2073616c65206e6f742073746172746564000000006044820152fd5b905034610685576122c336612f57565b92909391956122d061398f565b6122d861302d565b6122e06139b2565b6001600160a01b0393848616956122f88715156139d0565b612306868316881415613a1c565b898415926123148415613a77565b878716998a835260ff8660209460108652205416156124ba576123386103c6613545565b6123466103d9600d54613274565b8381015160038110156124a7579061041a8a8f6104149061236c600161237d9714613b1a565b8c608060a087015196015193614209565b8c81848d89519283809263313ce56760e01b82525afa91821561249c579060ff9261247f575b501690670de0b6b3a7640000958689029689880414171561246c57509081888d8f898f91898d8589888f6123d7859e613c1d565b6123e091613c2b565b6123e9866133a5565b90600f548110156123f990613c4b565b111561240490613cbd565b61240d9461415f565b9a919f90809a339261241e936140d0565b838252601081528d838320600101549061243791613b72565b93825260109052206001015561244e908a83614209565b966124598893613c1d565b61246291613c2b565b90610d7296613eaa565b634e487b7160e01b8e526011905260248dfd5b6124969150853d8711610dfb57610de88183613252565b386123a3565b8851903d90823e3d90fd5b634e487b7160e01b8f526021835260248ffd5b606490838088519262461bcd60e51b845283015260248201527f546f6b656e53746f72653a206173736574206973206e6f7420616c6c6f7765646044820152fd5b905034610685578260031936011261068557612515612fd5565b6002549060ff821615612557575060ff1916600255513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602090a180f35b8251638dfc202b60e01b8152fd5b905034610685576020366003190112610685576001600160a01b03612588612eb3565b612590612fd5565b169081845260146020526125a960ff84862054166137d2565b818452601460205260ff8385205460081c16156125d65750825260146020528120805461ff001916905580f35b608490602084519162461bcd60e51b8352820152602b60248201527f546f6b656e53746f72653a20526570726573656e74617469766520616c72656160448201527f64792064697361626c65640000000000000000000000000000000000000000006064820152fd5b50503461033f578160031936011261033f576020906003549051908152f35b50503461033f578160031936011261033f576020906001600160a01b03600b54169051908152f35b90503461068557816003193601126106855760209282916001600160a01b036126ad612ece565b1682526012855282822090358252845220549051908152f35b83833461033f578060031936011261033f576126e0612ece565b90336001600160a01b038316036126fd57506109c291923561318c565b5163334bd91960e11b81528390fd5b919050346106855761271d36612f15565b9361272a9392919361398f565b6127326139b2565b61273d3315156139d0565b6001600160a01b0392612754848716331415613a1c565b8215966127618815613a77565b84821696878a526020916010835260ff858c2054161561291c576127866103c6613545565b6127946103d9600d54613274565b83810151600381101561290957906127b160016127c99314613b1a565b61041a608060a08301519201516104148c8b8a614209565b845163313ce56760e01b8152838183818d5afa9081156128ff579060ff918d916128e2575b501690670de0b6b3a76400009a8b88029b888d041417156128cf575091849392918261281c8d989794613c1d565b612826908d613c2b565b61282f33613355565b90600f5481101561283f90613c4b565b111561284a90613cbd565b8a612858888c85893361415f565b96919a909588878c339261286b936140d0565b838252601081528a838320600101549061288491613b72565b93825260109052206001015561289b8a8887614209565b9b6128a68d92613c1d565b6128af91613c2b565b6128b99533613eaa565b600d54905193849316963395610d869385613d17565b634e487b7160e01b8c526011905260248bfd5b6128f99150853d8711610dfb57610de88183613252565b386127ee565b86513d8e823e3d90fd5b634e487b7160e01b8d526021835260248dfd5b606490838087519262461bcd60e51b845283015260248201527f546f6b656e53746f72653a206173736574206973206e6f7420616c6c6f7765646044820152fd5b919050346106855780600319360112610685576109c2913561298260016109ac612ece565b61310b565b83903461033f57602036600319011261033f57356129a3612fd5565b6129b767016345785d8a0000821015613786565b6129c5600e5482111561373a565b600f5580f35b905034610685576020908160031936011261068157803567ffffffffffffffff81116113f4576129fe9036908301612ee4565b612a0993919361398f565b8015612bb85733865260148252612a2560ff86882054166137d2565b3386526014825260ff8587205460081c1615612b6657855b818110612a4c57866001815580f35b612a5a61188c8284886135d9565b33885260168085526001600160a01b03888a20921691828a52855287892054908115612b5a57338a528552878920828a528552888881205573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8214600014612b44578880808084335af1612ac061382d565b5015612b015790612afc92915b88519081527ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd3992683863392a36135ca565b612a3d565b875162461bcd60e51b8152808701869052601e60248201527f546f6b656e53746f72653a206e617469766520636c61696d206572726f7200006044820152606490fd5b9081612b55612afc9493338461386d565b612acd565b505050612afc906135ca565b845162461bcd60e51b8152808401839052602660248201527f546f6b656e53746f72653a20526570726573656e746174697665206e6f7420656044820152651b98589b195960d21b6064820152608490fd5b845162461bcd60e51b8152808401839052602160248201527f546f6b656e53746f72653a206e6f20737461626c657320746f2070726f6365736044820152607360f81b6064820152608490fd5b90503461068557602036600319011261068557803591612c23612fd5565b600f5483101580612c7f575b15612c3c57505060075580f35b906020606492519162461bcd60e51b8352820152601960248201527f546f6b656e53746f72653a20696e76616c69642076616c7565000000000000006044820152fd5b50600e54831115612c2f565b90503461068557602036600319011261068557816020936001923581528285522001549051908152f35b50503461033f57602036600319011261033f57806080926001600160a01b03612cdc612eb3565b8260608551612cea81613236565b8281528260208201528287820152015216815260176020522090805190612d1082613236565b60ff835416151592838352600181015460208401908152606060036002840154938587019485520154940193845282519485525160208501525190830152516060820152f35b50503461033f57602036600319011261033f5760ff816020936001600160a01b03612d7f612eb3565b1681526010855220541690519015158152f35b50503461033f578160031936011261033f5760209051670de0b6b3a76400008152f35b90503461068557602036600319011261068557359063ffffffff60e01b82168092036106855760209250637965db0b60e01b8214918215612dfa575b50519015158152f35b6301ffc9a760e01b14915038612df1565b838591346106855760203660031901126106855760a081612e2c8593613204565b82815282602082015282848201528260608201528260808201520152612e556103d98435613274565b908051928251151584526020830151906003821015612ea05760c08560a0868686602085015280820151908401526060810151606084015260808101516080840152015160a0820152f35b634e487b7160e01b815260218652602490fd5b600435906001600160a01b0382168203612ec957565b600080fd5b602435906001600160a01b0382168203612ec957565b9181601f84011215612ec95782359167ffffffffffffffff8311612ec9576020808501948460051b010111612ec957565b6080906003190112612ec9576001600160a01b03906004358281168103612ec95791602435916044356002811015612ec957916064359081168103612ec95790565b60a0906003190112612ec9576001600160a01b036004358181168103612ec95791602435916044356002811015612ec957916064358281168103612ec957916084359081168103612ec95790565b6060906003190112612ec957600435906024359060443590565b6040906003190112612ec9576004359060243590565b3360009081527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602052604081205460ff161561300f5750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b3360009081527f0e781e1119f5cbdef17d282bb110c51d6016f6a6b0fe3e5a22e72588fdb32b9160205260409020547f4f72063d6dc4cf4bb4e008e0815997320f78a862b3e71fe66fa9ae685d1cd12f9060ff161561300f5750565b3360009081527ffdb122eb892c6b3193f8499f050265ce5458caab5f6480270d8972921f24f42960205260409020547f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b089060ff161561300f5750565b80600052600160205260406000203360005260205260ff604060002054161561300f5750565b9060009180835260016020526001600160a01b036040842092169182845260205260ff604084205416156000146131875780835260016020526040832082845260205260408320600160ff198254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b505090565b9060009180835260016020526001600160a01b036040842092169182845260205260ff604084205416600014613187578083526001602052604083208284526020526040832060ff1981541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b60c0810190811067ffffffffffffffff82111761322057604052565b634e487b7160e01b600052604160045260246000fd5b6080810190811067ffffffffffffffff82111761322057604052565b90601f8019910116810190811067ffffffffffffffff82111761322057604052565b600c548110156132af57600590600c600052027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70190600090565b634e487b7160e01b600052603260045260246000fd5b906040516132d281613204565b809260ff81548181161515845260081c16600381101561331c5760a09160049160208501526001810154604085015260028101546060850152600381015460808501520154910152565b634e487b7160e01b600052602160045260246000fd5b9190820391821161333f57565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0316600052601160205260406000205460075490601360205260ff6040600020541661339b575b60009180821015613187576133989250613332565b90565b600e549150613383565b6001600160a01b0316600090815260116020526040812054600e5480821015613187576133989250613332565b906001600160a01b038092166000928184526020906015825260409281848720541686526014835283862084519061340982613236565b8054916060600260ff80861615159586855260081c16151593848985015260018101548a8501520154910152816134b3575b506134a25750831684526014815281842091805161345881613236565b6060600285549560ff8716159460ff86159889875260081c161515809786015260018201549085015201549101529161349a575b50613495575090565b905090565b90503861348c565b856015939296949550525220541690565b90503861343b565b906001600160a01b0360609216600052601460205260406000206040516134e181613236565b81549060ff80831615159283835260081c16151560208201526002600184015493846040840152015494859101526135205750905060095490600a5490565b6009548082111561353d5750915b600a5480821115613495575090565b90509161352e565b60ff600b5460a01c16600381101561331c5760011490565b60ff600b5460a01c16600381101561331c5760021490565b600d549060ff61358483613274565b505460081c16600381101561331c576001146135a1575050600090565b600281101561331c576135bf576135b9600191613274565b50015490565b6135b9600291613274565b600019811461333f5760010190565b91908110156132af5760051b0190565b356001600160a01b0381168103612ec95790565b358015158103612ec95790565b1561361157565b60405162461bcd60e51b815260206004820152601760248201527f546f6b656e53746f72653a2073616c6520636c6f7365640000000000000000006044820152606490fd5b1561365d57565b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a20696e76616c696420617272617973206c656e677460448201527f68207365747570000000000000000000000000000000000000000000000000006064820152608490fd5b156136cf57565b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c642062652060448201527f646566696e6564000000000000000000000000000000000000000000000000006064820152608490fd5b1561374157565b60405162461bcd60e51b815260206004820152601c60248201527f546f6b656e53746f72653a2076616c756520697320746f6f20626967000000006044820152606490fd5b1561378d57565b60405162461bcd60e51b815260206004820152601e60248201527f546f6b656e53746f72653a2076616c756520697320746f6f20736d616c6c00006044820152606490fd5b156137d957565b60405162461bcd60e51b815260206004820152602660248201527f546f6b656e53746f72653a20526570726573656e746174697665206e6f74206460448201526519599a5b995960d21b6064820152608490fd5b3d15613868573d9067ffffffffffffffff8211613220576040519161385c601f8201601f191660200184613252565b82523d6000602084013e565b606090565b6138a7926001600160a01b036040519363a9059cbb60e01b60208601521660248401526044830152604482526138a282613236565b6138a9565b565b6001600160a01b0316906138d4600080836020829551910182875af16138cd61382d565b908461392c565b908151918215159283613904575b5050506138ec5750565b60249060405190635274afe760e01b82526004820152fd5b81929350906020918101031261033f57602001519081159182150361098457503880806138e2565b90613953575080511561394157805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580613986575b613964575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561395c565b6002600054146139a0576002600055565b604051633ee5aeb560e01b8152600490fd5b60ff600254166139be57565b60405163d93c066560e01b8152600490fd5b156139d757565b60405162461bcd60e51b815260206004820152601c60248201527f546f6b656e53746f72653a207265636569766572206973207a65726f000000006044820152606490fd5b15613a2357565b60405162461bcd60e51b815260206004820152602660248201527f546f6b656e53746f72653a2073656c662d726566657272696e672069732064696044820152651cd8589b195960d21b6064820152608490fd5b15613a7e57565b60405162461bcd60e51b815260206004820152601a60248201527f546f6b656e53746f72653a20616d6f756e74206973207a65726f0000000000006044820152606490fd5b15613aca57565b60405162461bcd60e51b815260206004820152602260248201527f546f6b656e53746f72653a2073616c6520697320616c726561647920636c6f73604482015261195960f21b6064820152608490fd5b15613b2157565b60405162461bcd60e51b815260206004820152602360248201527f546f6b656e53746f72653a206d696c6573746f6e65206973206e6f742061637460448201526269766560e81b6064820152608490fd5b9190820180921161333f57565b15613b8657565b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a206d696c6573746f6e6520616c6c6f636174696f6e60448201527f20657863656564000000000000000000000000000000000000000000000000006064820152608490fd5b90816020910312612ec9575160ff81168103612ec95790565b8181029291811591840414171561333f57565b604d811161333f57600a0a90565b8115613c35570490565b634e487b7160e01b600052601260045260246000fd5b15613c5257565b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a206465706f73697420616d6f756e7420697320746f60448201527f6f20736d616c6c000000000000000000000000000000000000000000000000006064820152608490fd5b15613cc457565b60405162461bcd60e51b815260206004820152602560248201527f546f6b656e53746f72653a206465706f73697420616d6f756e7420697320746f6044820152646f2062696760d81b6064820152608490fd5b90815260808101949392600283101561331c57606092602083015260408201520152565b939190936001600160a01b038091169060009482865260209360118552613d6760409889892054613b72565b8488526011865288882055613d7e81600854613b72565b600855600d546003613da5613d9f8483613d9786613274565b500154613b72565b92613274565b50015583875260128552613dc888882091600d5492838a52875289892054613b72565b9084885260128652888820908852855287872055169586613ded575b50505050505050565b60159387865260148452868620805460ff811615613e98575b50506016845286862073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee87528452613e36878720918254613b72565b90558685526016835285852073888888888888888888888888888888888888888886528352613e69868620918254613b72565b9055835252209073ffffffffffffffffffffffffffffffffffffffff1982541617905538808080808080613de4565b61ffff19166101011790553880613e06565b92919490956001600160a01b03809416918460009684885260209560118752613ed860409a8b8b2054613b72565b868a52601188528a8a2055613eef81600854613b72565b600855600d546003613f08613d9f8483613d9786613274565b50015585895260128752613f2b8a8a2091600d5492838c5289528b8b2054613b72565b90868a52601288528a8a20908a52875289892055169788613f52575b505050505050505050565b60159589885260148652888820805460ff811615613fec575b505060168652888820911687528452613f88878720918254613b72565b90558685526016835285852073888888888888888888888888888888888888888886528352613fbb868620918254613b72565b9055835252209073ffffffffffffffffffffffffffffffffffffffff19825416179055388080808080808080613f47565b61ffff19166101011790553880613f6b565b90816080910312612ec9576040519061401682613236565b80518060070b8103612ec9578252602081015167ffffffffffffffff81168103612ec95760208301526040810151908160030b8203612ec95760609160408401520151606082015290565b1561406857565b60405162461bcd60e51b815260206004820152602660248201527f546f6b656e53746f72653a2050797468204f7261636c65207072696365206f756044820152651d19185d195960d21b6064820152608490fd5b60030b600003908160030b91820361333f57565b9291906140f8906140f0846001600160a01b0380600b5416931694613332565b908584614109565b8161410257505050565b6138a79230915b9290604051926323b872dd60e01b60208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff841117613220576138a7926040526138a9565b9161416d91949593926133d2565b926001600160a01b038416156141b257906141ac9161419e6141a5614191876134bb565b906103e89384918b613c0a565b0498613c0a565b0490614209565b91929190565b5050915090600090600090565b916141cd91949593926133d2565b926001600160a01b038416156141b257906141ac9161419e6141f1614191876134bb565b04906142ba565b60ff16604d811161333f57600a0a90565b9060206001600160a01b03939260046040518096819363313ce56760e01b8352165afa9283156142ae5760009361428e575b50670de0b6b3a7640000908181029080820483148115171561333f576ec097ce7bc90715b34b9f10000000000291818304149015171561333f576142886104d1916104d1613398956141f8565b91613575565b6142a791935060203d8111610dfb57610de88183613252565b913861423b565b6040513d6000823e3d90fd5b9291926001600160a01b039360049480865416921690600092828452601760205260409460806001878720015460248851809581936396834ad360e01b83528d8301525afa918215614469578592614449575b5061432e606083015185875260176020526104666003898920015442613332565b87602060ff61434e8967ffffffffffffffff87511696015160030b6140bc565b169588519283809263313ce56760e01b82525afa9687156144405750859661441a575b509061437c91613c0a565b90670de0b6b3a76400009182810290808204841481151715614407576ec097ce7bc90715b34b9f1000000000029281840414901517156143f45760ff916104d16143c592613575565b9316019060ff82116143e157506133989293506104d1906141f8565b634e487b7160e01b815260118552602490fd5b634e487b7160e01b845260118752602484fd5b634e487b7160e01b865260118952602486fd5b61437c929196506144389060203d8111610dfb57610de88183613252565b959091614371565b513d87823e3d90fd5b61446291925060803d81116106595761064a8183613252565b903861430d565b86513d87823e3d90fd5b9061448191949293946133d2565b916001600160a01b038316156144be576141ac906144b16144b86144a4866134bb565b906103e89384918a613c0a565b0497613c0a565b046144ca565b50915090600090600090565b6001600160a01b03600454169060806006546024604051809581936396834ad360e01b835260048301525afa9182156142ae57600092614576575b506145439061451e606084015161046660055442613332565b67ffffffffffffffff60ff614539604086015160030b6140bc565b1693511690613c0a565b670de0b6b3a76400009081810291818304149015171561333f576145706104d1916104d161339895613575565b916141f8565b6145439192506145939060803d81116106595761064a8183613252565b919061450556fea2646970667358221220cee57220dbe211a9d8005be3eb4aebede70715b4242b0b5ff85d45e5761e7ecf64736f6c634300081500332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d0000000000000000000000002c9d77a9107cb4551a2bb3b1beded22f520e9ced00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000004305fb66699c3b2702d4d05cf36551390a4c69c6ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000c5f0f7b66764f6ec8c8dff7ba683102295e16409000000000000000000000000000000000000000000000000000000000000000100000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce0000000000000000000000000000000000000000000000000000000000000001f0d57deca57b3da2fe63a493f4c25925fdfd8edf834b20f93e1f84dbd1504d4a
Deployed Bytecode
0x6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c918262ff3b9214612e0b5750816301ffc9a714612db5578163059f8b1614612d925781630790241914612d565781630af6e01a14612cb5578163248a9ca314612c8b57816327ea6f2b14612c0557816329bf4077146129cb5781632a80cda3146129875781632f2ff15d1461295d5781632f362b811461270c57816336568abe146126c65781633656eec2146126865781633b19e84a1461265e5781633c9b97fc1461263f5781633edd9262146125655781633f4ba83a146124fb578163403cca7a146122b357816343d726d614612220578163564566a8146122035781635726a356146121e4578163590d889a146121a657816359b7aa351461216b57816359be5e451461214c5781635a54db86146121225781635c975abb146120fe57816361fd6545146120e15781636a30c1e9146120bc5781636eeb6dac1461208c578163738a8ce61461205457816377fe1f2414611da95781638456cb5914611d4e57816385b7583d14611d065781638886789314611c1a5781638d8e1ad714611bf45781638ed8409e14611bce57816391d1485414611b8857816395805dad14611a0e57816399e37f1f146118bb5781639a0a1504146117ee5781639a4eb422146116935781639c46e68e146115b65781639cf5c6131461155c578163a14e3cb114611451578163a217fddf14611436578163a70ef24f14611417578163b295a00e146113f8578163b7ea0d12146111f7578163b9209e33146111bb578163ba12897b14610e97578163bac34b9214610b43578163c3d3df5814610a29578163c4511c6a146109e2578163d3b5dc3b146109c6578163d547741f14610987578163d58c434114610953578163d6d65f3d14610934578163d9465dbb14610912578163e84112ab146108f3578163ea1ea81f146108cd578163ec87621c14610892578163f0f44260146107f9578163fa5b2cf514610737578163fcfff16f14610689578163fde0735b14610343575063ff32de1c146103075780610012565b3461033f57602036600319011261033f576001816020936001600160a01b0361032e612eb3565b168152601085522001549051908152f35b5080fd5b919050606036600319011261068557813591600283101561068157610366612ece565b916044356001600160a01b03918282169384830361067d5761038661302d565b61038e61398f565b6103966139b2565b6103b0848716956103a88715156139d0565b861415613a1c565b6103bb341515613a77565b6103cb6103c6613545565b613ac3565b6103df6103d9600d54613274565b506132c5565b6020810151600381101561066a57906103fd60016104219314613b1a565b61041a608060a08301519201516104148b346144ca565b90613b72565b1115613b7f565b8381541690608060065460248551809581936396834ad360e01b8352868301525afa918215610660578992610630575b5061046c606083015161046660055442613332565b10614061565b67ffffffffffffffff60ff6104868585015160030b6140bc565b16925116966104958834613c0a565b94670de0b6b3a7640000938487029680880486149015171561061d57601201958660121161061d57906104f66104d76104ff936104d18a613c1d565b90613c2b565b6104e0856133a5565b906104ef600f54821015613c4b565b1115613cbd565b8a349184614473565b94919690938c8080808c600b54166105178a34613332565b905af161052261382d565b50156105cc5761053434600354613b72565b60035561054b6105448d346144ca565b9b34613c0a565b8381029381850414901517156105b9575092868a61059d9461059760609a98956104d17fff61679fd42b9ad16062cd1c3719eefccc8fcec5083eb954c52d23841a23e36e9d9b99613c1d565b90613d3b565b600d549080519734895260208901528701521693a46001815580f35b634e487b7160e01b8d526011905260248cfd5b608490602088519162461bcd60e51b8352820152602560248201527f546f6b656e53746f72653a207472616e73666572206973206e6f742070726f63604482015264195cdcd95960da1b6064820152fd5b634e487b7160e01b8c526011845260248cfd5b61065291925060803d8111610659575b61064a8183613252565b810190613ffe565b9038610451565b503d610640565b83513d8b823e3d90fd5b634e487b7160e01b8a526021835260248afd5b8780fd5b8380fd5b8280fd5b9050346106855782600319360112610685576106a3612fd5565b600b549160ff8360a01c166003811015610724576106e157837401000000000000000000000000000000000000000060ff60a01b19851617600b5580f35b906020606492519162461bcd60e51b8352820152602060248201527f546f6b656e53746f72653a2073616c6520616c726561647920737461727465646044820152fd5b634e487b7160e01b855260218352602485fd5b90503461068557602036600319011261068557803591610755613089565b61076b60ff61076385613274565b5054166136c8565b60ff61077684613274565b505460081c166003811015610724576001036107a7578361079684613274565b50805461ff00191661020017905580f35b906020608492519162461bcd60e51b8352820152602660248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c642062652060448201526561637469766560d01b6064820152fd5b905034610685576020366003190112610685576001600160a01b0361081c612eb3565b610824612fd5565b1691821561084f57505073ffffffffffffffffffffffffffffffffffffffff19600b541617600b5580f35b906020606492519162461bcd60e51b8352820152601d60248201527f546f6b656e53746f72653a207a65726f2062616e6b20616464726573730000006044820152fd5b50503461033f578160031936011261033f57602090517f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088152f35b50503461033f578160031936011261033f576020906108ea61355d565b90519015158152f35b50503461033f578160031936011261033f57602090600c549051908152f35b83903461033f57602036600319011261033f5761092d612fd5565b3560055580f35b50503461033f578160031936011261033f57602090600d549051908152f35b9050346106855760203660031901126106855735916002831015610984575061097d602092613575565b9051908152f35b80fd5b919050346106855780600319360112610685576109c291356109bd60016109ac612ece565b9383875281602052862001546130e5565b61318c565b5080f35b50503461033f578160031936011261033f576020905160128152f35b83903461033f57602036600319011261033f57356109fe612fd5565b610a156a084595161401484a00000082111561373a565b610a23600f54821015613786565b600e5580f35b9190503461068557610a3a36612fbf565b929091610a45612fd5565b610a56610a5061355d565b1561360a565b6103e8808411610ada578411610a71575050600955600a5580f35b906020608492519162461bcd60e51b8352820152602f60248201527f546f6b656e53746f72653a2063616e7420736574207365636f6e64207261746560448201527f206d6f7265207468656e203130302500000000000000000000000000000000006064820152fd5b815162461bcd60e51b8152602081850152602e60248201527f546f6b656e53746f72653a2063616e742073657420666972737420726174652060448201527f6d6f7265207468656e20313030250000000000000000000000000000000000006064820152608490fd5b90503461068557610b5336612f57565b949195610b6193919361398f565b610b6961302d565b610b716139b2565b6001600160a01b039384811695610b898715156139d0565b610b97868916881415613a1c565b610ba2841515613a77565b85811697888b526020956017875260ff858d20541615610e4857610bc76103c6613545565b610bd56103d9600d54613274565b878101516003811015610e355790610bf26001610c0b9314613b1a565b61041a8d610414608060a0850151940151918b896142ba565b8b888254168b82526017895260806001888420015460248951809481936396834ad360e01b8352888301525afa908115610e2b579082918d9391610e0d575b50610c6a606082015184845260178c5261046660038b8620015442613332565b838a67ffffffffffffffff835116948a519283809263313ce56760e01b82525afa928315610e0257908b8a939294610dc4575b5050610cb3610cbb9260ff92015160030b6140bc565b169289613c0a565b92670de0b6b3a764000093848102948186041490151715610db15750918d939160ff8d9416610ce991613b72565b610cf290613c1d565b610cfb91613c2b565b94868d89610d08846133a5565b600f548a1015610d1790613c4b565b891115610d2390613cbd565b610d2f918589866141bf565b96919b909588878d3392610d42936140d0565b8252601790522060020188815490610d5991613b72565b9055610d668d89876142ba565b95610d72958792613eaa565b600d5491519485941697610d869385613d17565b037f176c329b62e92f50c6c9db5ca025ab96129e1dd260177211150f772adf0ef5e291a46001815580f35b634e487b7160e01b8f526011905260248efd5b60ff92945092610df0610cb39285610cbb96903d10610dfb575b610de88183613252565b810190613bf1565b94925092508b610c9d565b503d610dde565b8951903d90823e3d90fd5b610e25915060803d81116106595761064a8183613252565b38610c4a565b87513d84823e3d90fd5b634e487b7160e01b8e526021835260248efd5b845162461bcd60e51b8152908101879052602360248201527f546f6b656e53746f72653a20746f6b656e206973206e6f7420636f6e666967756044820152621c995960ea1b6064820152608490fd5b9190503461068557610ea836612f15565b610eb79592939594919461398f565b610ebf6139b2565b610eca3315156139d0565b6001600160a01b0392610ee1848316331415613a1c565b610eec851515613a77565b8387168852601760205260ff83892054161561116c57610f0d6103c6613545565b610f1b6103d9600d54613274565b6020810151600381101561066a5790610f396001610f519314613b1a565b61041a608060a08301519201516104148a8a8d6142ba565b838154168488168952601760205260806001858b20015460248651809481936396834ad360e01b8352878301525afa908115611162578991611144575b50610fb16060820151868a168b5260176020526104666003878d20015442613332565b8051845163313ce56760e01b815267ffffffffffffffff9091169160208285818a8e165afa91821561113a579086918c9361110c575b50610ffc6110049260ff92015160030b6140bc565b169288613c0a565b92670de0b6b3a7640000938481029481860414901517156110f957506110da89886110ae966002898f8c8f98867f176c329b62e92f50c6c9db5ca025ab96129e1dd260177211150f772adf0ef5e29f9e9b6110ef9d6104d16110706110759360ff6110a1971690613b72565b613c1d565b9a6110998c61109161108633613355565b91600f541115613c4b565b8d1115613cbd565b878a336141bf565b98919d90809883336140d0565b168152601760205220016110c38c8254613b72565b90558c6110d18d8d836142ba565b95869133613eaa565b84600d54925195869516991697339785613d17565b0390a46001815580f35b634e487b7160e01b8b526011905260248afd5b60ff91935061100492611130610ffc9260203d602011610dfb57610de88183613252565b9492509250610fe7565b86513d8d823e3d90fd5b61115c915060803d81116106595761064a8183613252565b38610f8e565b84513d8b823e3d90fd5b608490602084519162461bcd60e51b8352820152602360248201527f546f6b656e53746f72653a20746f6b656e206973206e6f7420636f6e666967756044820152621c995960ea1b6064820152fd5b50503461033f57602036600319011261033f5760ff816020936001600160a01b036111e4612eb3565b1681526013855220541690519015158152f35b919050346106855760803660031901126106855767ffffffffffffffff9180358381116113f45761122b9036908301612ee4565b916024358581116113f0576112439036908301612ee4565b94906044358781116113ec5761125c9036908501612ee4565b9390976064359081116113e8576112769036908301612ee4565b959091611281612fd5565b888814806113df575b806113d6575b156113855750895b8a8882106112a35780f35b88828989898f958f968a878b888f94816001600160a01b039485916112c891866135d9565b6112d1906135e9565b168752816017968160209789895260029e8f8d8d2001549e6112f2926135d9565b6112fb906135fd565b9f611305926135d9565b3599611310926135d9565b359a87519c61131e8e613236565b15158d52848d01988952878d01998a5260608d019b8c5261133e926135d9565b611347906135e9565b16835252209451151561136690869060ff801983541691151516179055565b5160018501555190830155519060030155611380906135ca565b611298565b608490602086519162461bcd60e51b8352820152602560248201527f546f6b656e53746f72653a20617272617973206c656e67746873206e6f7420656044820152647175616c7360d81b6064820152fd5b50858814611290565b5086881461128a565b8980fd5b8880fd5b8680fd5b8480fd5b50503461033f578160031936011261033f576020906007549051908152f35b50503461033f578160031936011261033f57602090600f549051908152f35b50503461033f578160031936011261033f5751908152602090f35b9050346106855761146136612fa5565b91939061146c612fd5565b611477610a5061355d565b81519461148386613204565b600186526020860192878452860190815260608601918252608086019287845260a08701948552600c5468010000000000000000811015611549578060016114ce9201600c55613274565b979097611537576114ee90511515889060ff801983541691151516179055565b5160038110156115245761ff0087549160081b169061ff0019161786555160018601555160028501555160038401555191015580f35b634e487b7160e01b885260218652602488fd5b634e487b7160e01b8952888752602489fd5b634e487b7160e01b895260418752602489fd5b50503461033f578060031936011261033f57611576612eb3565b90602435908115158203610681576001600160a01b036115b393611598613089565b168452601360205283209060ff801983541691151516179055565b80f35b905034610685576020366003190112610685576001600160a01b036115d9612eb3565b6115e1612fd5565b169081845260146020526115fa60ff84862054166137d2565b818452601460205260ff8385205460081c1661162a5750825260146020528120805461ff00191661010017905580f35b608490602084519162461bcd60e51b8352820152602a60248201527f546f6b656e53746f72653a20526570726573656e74617469766520616c72656160448201527f647920656e61626c6564000000000000000000000000000000000000000000006064820152fd5b905034610685576116a336612fbf565b926116ac612fd5565b6116b7610a5061355d565b6116c560ff61076384613274565b60ff6116d083613274565b505460081c1660038110156117db57600214611773578360036116f284613274565b500154101561170b575061170590613274565b50015580f35b5162461bcd60e51b8152602081840152603660248201527f546f6b656e53746f72653a206e657720737570706c79206d757374206265206260448201527f6967676572207468656e20736f6c6420746f6b656e73000000000000000000006064820152608490fd5b5162461bcd60e51b8152602081840152602a60248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c64206e6f7460448201527f20626520636c6f736564000000000000000000000000000000000000000000006064820152608490fd5b634e487b7160e01b865260218452602486fd5b90503461068557816003193601126106855767ffffffffffffffff9181358381116113f4576118209036908401612ee4565b9390926024359182116118b75761183991369101612ee4565b611844949194613089565b61184f818314613656565b855b82811061185c578680f35b806118ad6118766118716118b294868b6135d9565b6135fd565b6001600160a01b0361189161188c85898c6135d9565b6135e9565b168a526013602052868a209060ff801983541691151516179055565b6135ca565b611851565b8580fd5b9190503461068557606090816003193601126106815767ffffffffffffffff83358181116118b7576118f09036908601612ee4565b93909260243583811161067d5761190a9036908801612ee4565b9390966044359182116113ec5761192391369101612ee4565b909361192d613089565b611938610a5061355d565b80871480611a05575b61194a90613656565b88805b888110611958575080f35b8060028a8a8a8a8f8b6119fe9960146119828a8f8f8261197b916119db996135d9565b35986135d9565b35976001600160a01b036119c061188c86519d8e946119a086613236565b60019c8d9b8c88526020978881019d8e528b81019e8f52019e8f526135d9565b168352522096511515879060ff801983541691151516179055565b51855461ff00191690151560081b61ff00161785555190840155519101556135ca565b899061194d565b50868214611941565b90503461068557602036600319011261068557803591611a2c613089565b611a34613545565b15611b4557611a4760ff61076385613274565b60ff611a5284613274565b505460081c16600381101561072457611adc5750600d549060ff611a7583613274565b505460081c16906003821015611ac95750600114611aac575b50611a9881613274565b50805461ff001916610100179055600d5580f35b611ab590613274565b50805461ff00191661020017905538611a8e565b634e487b7160e01b855260219052602484fd5b906020608492519162461bcd60e51b8352820152602860248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c64206e6f7460448201527f20626520757365640000000000000000000000000000000000000000000000006064820152fd5b906020606492519162461bcd60e51b8352820152601b60248201527f546f6b656e53746f72653a2073616c65206e6f742061637469766500000000006044820152fd5b9050346106855781600319360112610685578160209360ff92611ba9612ece565b90358252600186526001600160a01b0383832091168252855220541690519015158152f35b50503461033f57602036600319011261033f5760209061097d611bef612eb3565b613355565b50503461033f57602036600319011261033f5760209061097d611c15612eb3565b6133a5565b9190503461068557611c2b36612fa5565b93909192611c37612fd5565b611c42610a5061355d565b611c5060ff61076386613274565b60ff611c5b85613274565b505460081c166003811015611cf357611c8a57505081611705916001611c82600295613274565b500155613274565b906020608492519162461bcd60e51b8352820152602b60248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c64206e6f7460448201527f20626520737461727465640000000000000000000000000000000000000000006064820152fd5b634e487b7160e01b875260218352602487fd5b50503461033f578060031936011261033f5780602092611d24612eb3565b6001600160a01b0380611d35612ece565b1683526016865283832091168252845220549051908152f35b50503461033f578160031936011261033f5760207f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25891611d8c612fd5565b611d946139b2565b600160ff19600254161760025551338152a180f35b90508160031936011261068557803591600283101561068157611dca612ece565b611dd261398f565b611dda6139b2565b611de53315156139d0565b6001600160a01b0391611dfc838316331415613a1c565b611e07341515613a77565b611e126103c6613545565b611e206103d9600d54613274565b602081015160038110156115245790611e3e6001611e559314613b1a565b61041a608060a083015192015161041489346144ca565b82845416608060065460248451809481936396834ad360e01b83528a8301525afa90811561204a57879161202c575b50611e99606082015161046660055442613332565b67ffffffffffffffff60ff611eb38484015160030b6140bc565b1691511694611ec28634613c0a565b93670de0b6b3a764000092838602958087048514901517156120195760120194856012116120195790611f07611efe611f10936104d189613c1d565b6104e033613355565b88349133614473565b93919590928a8080808b600b5416611f288934613332565b905af1611f3361382d565b5015611fc857611f4534600354613b72565b600355611f5c611f558b346144ca565b9934613c0a565b8381029381850414901517156110f9575087611f81611f879594936104d18994613c1d565b33613d3b565b600d5490805194348652602086015284015216907fff61679fd42b9ad16062cd1c3719eefccc8fcec5083eb954c52d23841a23e36e60603392a46001815580f35b608490602087519162461bcd60e51b8352820152602560248201527f546f6b656e53746f72653a207472616e73666572206973206e6f742070726f63604482015264195cdcd95960da1b6064820152fd5b634e487b7160e01b8a526011835260248afd5b612044915060803d81116106595761064a8183613252565b38611e84565b82513d89823e3d90fd5b50503461033f57366003190112610984576115b3612070612eb3565b612078612fd5565b602435906001600160a01b0333911661386d565b82843461098457602036600319011261098457506120b06120ab612eb3565b6134bb565b82519182526020820152f35b82843461098457806003193601126109845750600954600a5482519182526020820152f35b50503461033f578160031936011261033f57602090516170808152f35b50503461033f578160031936011261033f5760209060ff6002541690519015158152f35b833461098457806003193601126109845761213b612fd5565b8080808047335af1506109c261382d565b50503461033f578160031936011261033f576020906008549051908152f35b50503461033f578160031936011261033f57602090517f4f72063d6dc4cf4bb4e008e0815997320f78a862b3e71fe66fa9ae685d1cd12f8152f35b50503461033f578060031936011261033f576020906001600160a01b036121dc6121ce612eb3565b6121d6612ece565b906133d2565b915191168152f35b50503461033f578160031936011261033f57602090600e549051908152f35b50503461033f578160031936011261033f576020906108ea613545565b9190503461068557826003193601126106855761223b612fd5565b612243613545565b1561227057827402000000000000000000000000000000000000000060ff60a01b19600b541617600b5580f35b906020606492519162461bcd60e51b8352820152601c60248201527f546f6b656e53746f72653a2073616c65206e6f742073746172746564000000006044820152fd5b905034610685576122c336612f57565b92909391956122d061398f565b6122d861302d565b6122e06139b2565b6001600160a01b0393848616956122f88715156139d0565b612306868316881415613a1c565b898415926123148415613a77565b878716998a835260ff8660209460108652205416156124ba576123386103c6613545565b6123466103d9600d54613274565b8381015160038110156124a7579061041a8a8f6104149061236c600161237d9714613b1a565b8c608060a087015196015193614209565b8c81848d89519283809263313ce56760e01b82525afa91821561249c579060ff9261247f575b501690670de0b6b3a7640000958689029689880414171561246c57509081888d8f898f91898d8589888f6123d7859e613c1d565b6123e091613c2b565b6123e9866133a5565b90600f548110156123f990613c4b565b111561240490613cbd565b61240d9461415f565b9a919f90809a339261241e936140d0565b838252601081528d838320600101549061243791613b72565b93825260109052206001015561244e908a83614209565b966124598893613c1d565b61246291613c2b565b90610d7296613eaa565b634e487b7160e01b8e526011905260248dfd5b6124969150853d8711610dfb57610de88183613252565b386123a3565b8851903d90823e3d90fd5b634e487b7160e01b8f526021835260248ffd5b606490838088519262461bcd60e51b845283015260248201527f546f6b656e53746f72653a206173736574206973206e6f7420616c6c6f7765646044820152fd5b905034610685578260031936011261068557612515612fd5565b6002549060ff821615612557575060ff1916600255513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602090a180f35b8251638dfc202b60e01b8152fd5b905034610685576020366003190112610685576001600160a01b03612588612eb3565b612590612fd5565b169081845260146020526125a960ff84862054166137d2565b818452601460205260ff8385205460081c16156125d65750825260146020528120805461ff001916905580f35b608490602084519162461bcd60e51b8352820152602b60248201527f546f6b656e53746f72653a20526570726573656e74617469766520616c72656160448201527f64792064697361626c65640000000000000000000000000000000000000000006064820152fd5b50503461033f578160031936011261033f576020906003549051908152f35b50503461033f578160031936011261033f576020906001600160a01b03600b54169051908152f35b90503461068557816003193601126106855760209282916001600160a01b036126ad612ece565b1682526012855282822090358252845220549051908152f35b83833461033f578060031936011261033f576126e0612ece565b90336001600160a01b038316036126fd57506109c291923561318c565b5163334bd91960e11b81528390fd5b919050346106855761271d36612f15565b9361272a9392919361398f565b6127326139b2565b61273d3315156139d0565b6001600160a01b0392612754848716331415613a1c565b8215966127618815613a77565b84821696878a526020916010835260ff858c2054161561291c576127866103c6613545565b6127946103d9600d54613274565b83810151600381101561290957906127b160016127c99314613b1a565b61041a608060a08301519201516104148c8b8a614209565b845163313ce56760e01b8152838183818d5afa9081156128ff579060ff918d916128e2575b501690670de0b6b3a76400009a8b88029b888d041417156128cf575091849392918261281c8d989794613c1d565b612826908d613c2b565b61282f33613355565b90600f5481101561283f90613c4b565b111561284a90613cbd565b8a612858888c85893361415f565b96919a909588878c339261286b936140d0565b838252601081528a838320600101549061288491613b72565b93825260109052206001015561289b8a8887614209565b9b6128a68d92613c1d565b6128af91613c2b565b6128b99533613eaa565b600d54905193849316963395610d869385613d17565b634e487b7160e01b8c526011905260248bfd5b6128f99150853d8711610dfb57610de88183613252565b386127ee565b86513d8e823e3d90fd5b634e487b7160e01b8d526021835260248dfd5b606490838087519262461bcd60e51b845283015260248201527f546f6b656e53746f72653a206173736574206973206e6f7420616c6c6f7765646044820152fd5b919050346106855780600319360112610685576109c2913561298260016109ac612ece565b61310b565b83903461033f57602036600319011261033f57356129a3612fd5565b6129b767016345785d8a0000821015613786565b6129c5600e5482111561373a565b600f5580f35b905034610685576020908160031936011261068157803567ffffffffffffffff81116113f4576129fe9036908301612ee4565b612a0993919361398f565b8015612bb85733865260148252612a2560ff86882054166137d2565b3386526014825260ff8587205460081c1615612b6657855b818110612a4c57866001815580f35b612a5a61188c8284886135d9565b33885260168085526001600160a01b03888a20921691828a52855287892054908115612b5a57338a528552878920828a528552888881205573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8214600014612b44578880808084335af1612ac061382d565b5015612b015790612afc92915b88519081527ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd3992683863392a36135ca565b612a3d565b875162461bcd60e51b8152808701869052601e60248201527f546f6b656e53746f72653a206e617469766520636c61696d206572726f7200006044820152606490fd5b9081612b55612afc9493338461386d565b612acd565b505050612afc906135ca565b845162461bcd60e51b8152808401839052602660248201527f546f6b656e53746f72653a20526570726573656e746174697665206e6f7420656044820152651b98589b195960d21b6064820152608490fd5b845162461bcd60e51b8152808401839052602160248201527f546f6b656e53746f72653a206e6f20737461626c657320746f2070726f6365736044820152607360f81b6064820152608490fd5b90503461068557602036600319011261068557803591612c23612fd5565b600f5483101580612c7f575b15612c3c57505060075580f35b906020606492519162461bcd60e51b8352820152601960248201527f546f6b656e53746f72653a20696e76616c69642076616c7565000000000000006044820152fd5b50600e54831115612c2f565b90503461068557602036600319011261068557816020936001923581528285522001549051908152f35b50503461033f57602036600319011261033f57806080926001600160a01b03612cdc612eb3565b8260608551612cea81613236565b8281528260208201528287820152015216815260176020522090805190612d1082613236565b60ff835416151592838352600181015460208401908152606060036002840154938587019485520154940193845282519485525160208501525190830152516060820152f35b50503461033f57602036600319011261033f5760ff816020936001600160a01b03612d7f612eb3565b1681526010855220541690519015158152f35b50503461033f578160031936011261033f5760209051670de0b6b3a76400008152f35b90503461068557602036600319011261068557359063ffffffff60e01b82168092036106855760209250637965db0b60e01b8214918215612dfa575b50519015158152f35b6301ffc9a760e01b14915038612df1565b838591346106855760203660031901126106855760a081612e2c8593613204565b82815282602082015282848201528260608201528260808201520152612e556103d98435613274565b908051928251151584526020830151906003821015612ea05760c08560a0868686602085015280820151908401526060810151606084015260808101516080840152015160a0820152f35b634e487b7160e01b815260218652602490fd5b600435906001600160a01b0382168203612ec957565b600080fd5b602435906001600160a01b0382168203612ec957565b9181601f84011215612ec95782359167ffffffffffffffff8311612ec9576020808501948460051b010111612ec957565b6080906003190112612ec9576001600160a01b03906004358281168103612ec95791602435916044356002811015612ec957916064359081168103612ec95790565b60a0906003190112612ec9576001600160a01b036004358181168103612ec95791602435916044356002811015612ec957916064358281168103612ec957916084359081168103612ec95790565b6060906003190112612ec957600435906024359060443590565b6040906003190112612ec9576004359060243590565b3360009081527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602052604081205460ff161561300f5750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b3360009081527f0e781e1119f5cbdef17d282bb110c51d6016f6a6b0fe3e5a22e72588fdb32b9160205260409020547f4f72063d6dc4cf4bb4e008e0815997320f78a862b3e71fe66fa9ae685d1cd12f9060ff161561300f5750565b3360009081527ffdb122eb892c6b3193f8499f050265ce5458caab5f6480270d8972921f24f42960205260409020547f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b089060ff161561300f5750565b80600052600160205260406000203360005260205260ff604060002054161561300f5750565b9060009180835260016020526001600160a01b036040842092169182845260205260ff604084205416156000146131875780835260016020526040832082845260205260408320600160ff198254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b505090565b9060009180835260016020526001600160a01b036040842092169182845260205260ff604084205416600014613187578083526001602052604083208284526020526040832060ff1981541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b60c0810190811067ffffffffffffffff82111761322057604052565b634e487b7160e01b600052604160045260246000fd5b6080810190811067ffffffffffffffff82111761322057604052565b90601f8019910116810190811067ffffffffffffffff82111761322057604052565b600c548110156132af57600590600c600052027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70190600090565b634e487b7160e01b600052603260045260246000fd5b906040516132d281613204565b809260ff81548181161515845260081c16600381101561331c5760a09160049160208501526001810154604085015260028101546060850152600381015460808501520154910152565b634e487b7160e01b600052602160045260246000fd5b9190820391821161333f57565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0316600052601160205260406000205460075490601360205260ff6040600020541661339b575b60009180821015613187576133989250613332565b90565b600e549150613383565b6001600160a01b0316600090815260116020526040812054600e5480821015613187576133989250613332565b906001600160a01b038092166000928184526020906015825260409281848720541686526014835283862084519061340982613236565b8054916060600260ff80861615159586855260081c16151593848985015260018101548a8501520154910152816134b3575b506134a25750831684526014815281842091805161345881613236565b6060600285549560ff8716159460ff86159889875260081c161515809786015260018201549085015201549101529161349a575b50613495575090565b905090565b90503861348c565b856015939296949550525220541690565b90503861343b565b906001600160a01b0360609216600052601460205260406000206040516134e181613236565b81549060ff80831615159283835260081c16151560208201526002600184015493846040840152015494859101526135205750905060095490600a5490565b6009548082111561353d5750915b600a5480821115613495575090565b90509161352e565b60ff600b5460a01c16600381101561331c5760011490565b60ff600b5460a01c16600381101561331c5760021490565b600d549060ff61358483613274565b505460081c16600381101561331c576001146135a1575050600090565b600281101561331c576135bf576135b9600191613274565b50015490565b6135b9600291613274565b600019811461333f5760010190565b91908110156132af5760051b0190565b356001600160a01b0381168103612ec95790565b358015158103612ec95790565b1561361157565b60405162461bcd60e51b815260206004820152601760248201527f546f6b656e53746f72653a2073616c6520636c6f7365640000000000000000006044820152606490fd5b1561365d57565b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a20696e76616c696420617272617973206c656e677460448201527f68207365747570000000000000000000000000000000000000000000000000006064820152608490fd5b156136cf57565b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a204d696c6573746f6e652073686f756c642062652060448201527f646566696e6564000000000000000000000000000000000000000000000000006064820152608490fd5b1561374157565b60405162461bcd60e51b815260206004820152601c60248201527f546f6b656e53746f72653a2076616c756520697320746f6f20626967000000006044820152606490fd5b1561378d57565b60405162461bcd60e51b815260206004820152601e60248201527f546f6b656e53746f72653a2076616c756520697320746f6f20736d616c6c00006044820152606490fd5b156137d957565b60405162461bcd60e51b815260206004820152602660248201527f546f6b656e53746f72653a20526570726573656e746174697665206e6f74206460448201526519599a5b995960d21b6064820152608490fd5b3d15613868573d9067ffffffffffffffff8211613220576040519161385c601f8201601f191660200184613252565b82523d6000602084013e565b606090565b6138a7926001600160a01b036040519363a9059cbb60e01b60208601521660248401526044830152604482526138a282613236565b6138a9565b565b6001600160a01b0316906138d4600080836020829551910182875af16138cd61382d565b908461392c565b908151918215159283613904575b5050506138ec5750565b60249060405190635274afe760e01b82526004820152fd5b81929350906020918101031261033f57602001519081159182150361098457503880806138e2565b90613953575080511561394157805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580613986575b613964575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561395c565b6002600054146139a0576002600055565b604051633ee5aeb560e01b8152600490fd5b60ff600254166139be57565b60405163d93c066560e01b8152600490fd5b156139d757565b60405162461bcd60e51b815260206004820152601c60248201527f546f6b656e53746f72653a207265636569766572206973207a65726f000000006044820152606490fd5b15613a2357565b60405162461bcd60e51b815260206004820152602660248201527f546f6b656e53746f72653a2073656c662d726566657272696e672069732064696044820152651cd8589b195960d21b6064820152608490fd5b15613a7e57565b60405162461bcd60e51b815260206004820152601a60248201527f546f6b656e53746f72653a20616d6f756e74206973207a65726f0000000000006044820152606490fd5b15613aca57565b60405162461bcd60e51b815260206004820152602260248201527f546f6b656e53746f72653a2073616c6520697320616c726561647920636c6f73604482015261195960f21b6064820152608490fd5b15613b2157565b60405162461bcd60e51b815260206004820152602360248201527f546f6b656e53746f72653a206d696c6573746f6e65206973206e6f742061637460448201526269766560e81b6064820152608490fd5b9190820180921161333f57565b15613b8657565b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a206d696c6573746f6e6520616c6c6f636174696f6e60448201527f20657863656564000000000000000000000000000000000000000000000000006064820152608490fd5b90816020910312612ec9575160ff81168103612ec95790565b8181029291811591840414171561333f57565b604d811161333f57600a0a90565b8115613c35570490565b634e487b7160e01b600052601260045260246000fd5b15613c5257565b60405162461bcd60e51b815260206004820152602760248201527f546f6b656e53746f72653a206465706f73697420616d6f756e7420697320746f60448201527f6f20736d616c6c000000000000000000000000000000000000000000000000006064820152608490fd5b15613cc457565b60405162461bcd60e51b815260206004820152602560248201527f546f6b656e53746f72653a206465706f73697420616d6f756e7420697320746f6044820152646f2062696760d81b6064820152608490fd5b90815260808101949392600283101561331c57606092602083015260408201520152565b939190936001600160a01b038091169060009482865260209360118552613d6760409889892054613b72565b8488526011865288882055613d7e81600854613b72565b600855600d546003613da5613d9f8483613d9786613274565b500154613b72565b92613274565b50015583875260128552613dc888882091600d5492838a52875289892054613b72565b9084885260128652888820908852855287872055169586613ded575b50505050505050565b60159387865260148452868620805460ff811615613e98575b50506016845286862073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee87528452613e36878720918254613b72565b90558685526016835285852073888888888888888888888888888888888888888886528352613e69868620918254613b72565b9055835252209073ffffffffffffffffffffffffffffffffffffffff1982541617905538808080808080613de4565b61ffff19166101011790553880613e06565b92919490956001600160a01b03809416918460009684885260209560118752613ed860409a8b8b2054613b72565b868a52601188528a8a2055613eef81600854613b72565b600855600d546003613f08613d9f8483613d9786613274565b50015585895260128752613f2b8a8a2091600d5492838c5289528b8b2054613b72565b90868a52601288528a8a20908a52875289892055169788613f52575b505050505050505050565b60159589885260148652888820805460ff811615613fec575b505060168652888820911687528452613f88878720918254613b72565b90558685526016835285852073888888888888888888888888888888888888888886528352613fbb868620918254613b72565b9055835252209073ffffffffffffffffffffffffffffffffffffffff19825416179055388080808080808080613f47565b61ffff19166101011790553880613f6b565b90816080910312612ec9576040519061401682613236565b80518060070b8103612ec9578252602081015167ffffffffffffffff81168103612ec95760208301526040810151908160030b8203612ec95760609160408401520151606082015290565b1561406857565b60405162461bcd60e51b815260206004820152602660248201527f546f6b656e53746f72653a2050797468204f7261636c65207072696365206f756044820152651d19185d195960d21b6064820152608490fd5b60030b600003908160030b91820361333f57565b9291906140f8906140f0846001600160a01b0380600b5416931694613332565b908584614109565b8161410257505050565b6138a79230915b9290604051926323b872dd60e01b60208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff841117613220576138a7926040526138a9565b9161416d91949593926133d2565b926001600160a01b038416156141b257906141ac9161419e6141a5614191876134bb565b906103e89384918b613c0a565b0498613c0a565b0490614209565b91929190565b5050915090600090600090565b916141cd91949593926133d2565b926001600160a01b038416156141b257906141ac9161419e6141f1614191876134bb565b04906142ba565b60ff16604d811161333f57600a0a90565b9060206001600160a01b03939260046040518096819363313ce56760e01b8352165afa9283156142ae5760009361428e575b50670de0b6b3a7640000908181029080820483148115171561333f576ec097ce7bc90715b34b9f10000000000291818304149015171561333f576142886104d1916104d1613398956141f8565b91613575565b6142a791935060203d8111610dfb57610de88183613252565b913861423b565b6040513d6000823e3d90fd5b9291926001600160a01b039360049480865416921690600092828452601760205260409460806001878720015460248851809581936396834ad360e01b83528d8301525afa918215614469578592614449575b5061432e606083015185875260176020526104666003898920015442613332565b87602060ff61434e8967ffffffffffffffff87511696015160030b6140bc565b169588519283809263313ce56760e01b82525afa9687156144405750859661441a575b509061437c91613c0a565b90670de0b6b3a76400009182810290808204841481151715614407576ec097ce7bc90715b34b9f1000000000029281840414901517156143f45760ff916104d16143c592613575565b9316019060ff82116143e157506133989293506104d1906141f8565b634e487b7160e01b815260118552602490fd5b634e487b7160e01b845260118752602484fd5b634e487b7160e01b865260118952602486fd5b61437c929196506144389060203d8111610dfb57610de88183613252565b959091614371565b513d87823e3d90fd5b61446291925060803d81116106595761064a8183613252565b903861430d565b86513d87823e3d90fd5b9061448191949293946133d2565b916001600160a01b038316156144be576141ac906144b16144b86144a4866134bb565b906103e89384918a613c0a565b0497613c0a565b046144ca565b50915090600090600090565b6001600160a01b03600454169060806006546024604051809581936396834ad360e01b835260048301525afa9182156142ae57600092614576575b506145439061451e606084015161046660055442613332565b67ffffffffffffffff60ff614539604086015160030b6140bc565b1693511690613c0a565b670de0b6b3a76400009081810291818304149015171561333f576145706104d1916104d161339895613575565b916141f8565b6145439192506145939060803d81116106595761064a8183613252565b919061450556fea2646970667358221220cee57220dbe211a9d8005be3eb4aebede70715b4242b0b5ff85d45e5761e7ecf64736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002c9d77a9107cb4551a2bb3b1beded22f520e9ced00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000004305fb66699c3b2702d4d05cf36551390a4c69c6ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000c5f0f7b66764f6ec8c8dff7ba683102295e16409000000000000000000000000000000000000000000000000000000000000000100000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce0000000000000000000000000000000000000000000000000000000000000001f0d57deca57b3da2fe63a493f4c25925fdfd8edf834b20f93e1f84dbd1504d4a
-----Decoded View---------------
Arg [0] : treasury_ (address): 0x2C9d77a9107cB4551a2BB3b1beDEd22f520E9CeD
Arg [1] : stables_ (address[]): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48,0xdAC17F958D2ee523a2206206994597C13D831ec7,0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409
Arg [2] : pyth_ (address): 0x4305FB66699C3B2702D4d05CF36551390A4c69C6
Arg [3] : pythNativePriceFeedId_ (bytes32): 0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace
Arg [4] : tokens (address[]): 0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE
Arg [5] : pythIds (bytes32[]): System.Byte[]
-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 0000000000000000000000002c9d77a9107cb4551a2bb3b1beded22f520e9ced
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000004305fb66699c3b2702d4d05cf36551390a4c69c6
Arg [3] : ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [7] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [8] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [9] : 000000000000000000000000c5f0f7b66764f6ec8c8dff7ba683102295e16409
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [11] : 00000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [13] : f0d57deca57b3da2fe63a493f4c25925fdfd8edf834b20f93e1f84dbd1504d4a
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.