Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 612 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Stake | 20458512 | 147 days ago | IN | 0 ETH | 0.0004954 | ||||
Emergency Unstak... | 18453542 | 427 days ago | IN | 0 ETH | 0.00861856 | ||||
Emergency Unstak... | 18312416 | 447 days ago | IN | 0 ETH | 0.00693732 | ||||
Emergency Unstak... | 18290399 | 450 days ago | IN | 0 ETH | 0.00556417 | ||||
Emergency Unstak... | 18290376 | 450 days ago | IN | 0 ETH | 0.00062096 | ||||
Unstake | 18181992 | 465 days ago | IN | 0 ETH | 0.00616059 | ||||
Stake | 18181980 | 465 days ago | IN | 0 ETH | 0.00168153 | ||||
Emergency Unstak... | 18181960 | 465 days ago | IN | 0 ETH | 0.00642891 | ||||
Unstake | 18172395 | 467 days ago | IN | 0 ETH | 0.00177891 | ||||
Stake | 18172384 | 467 days ago | IN | 0 ETH | 0.00204661 | ||||
Stake | 18171869 | 467 days ago | IN | 0 ETH | 0.00420828 | ||||
Emergency Unstak... | 17962163 | 496 days ago | IN | 0 ETH | 0.01066523 | ||||
Emergency Unstak... | 17954112 | 497 days ago | IN | 0 ETH | 0.00086615 | ||||
Emergency Unstak... | 17954101 | 497 days ago | IN | 0 ETH | 0.00109426 | ||||
Emergency Unstak... | 17934428 | 500 days ago | IN | 0 ETH | 0.01127005 | ||||
Emergency Unstak... | 17910708 | 503 days ago | IN | 0 ETH | 0.01199959 | ||||
Emergency Unstak... | 17701022 | 533 days ago | IN | 0 ETH | 0.00112615 | ||||
Emergency Unstak... | 17695131 | 534 days ago | IN | 0 ETH | 0.02090178 | ||||
Emergency Unstak... | 17661777 | 538 days ago | IN | 0 ETH | 0.01157238 | ||||
Emergency Unstak... | 17659027 | 539 days ago | IN | 0 ETH | 0.00103192 | ||||
Emergency Unstak... | 17658947 | 539 days ago | IN | 0 ETH | 0.0540343 | ||||
Emergency Unstak... | 17607777 | 546 days ago | IN | 0 ETH | 0.01142375 | ||||
Emergency Unstak... | 17572488 | 551 days ago | IN | 0 ETH | 0.01151598 | ||||
Emergency Unstak... | 17568454 | 551 days ago | IN | 0 ETH | 0.01415965 | ||||
Emergency Unstak... | 17560503 | 552 days ago | IN | 0 ETH | 0.01593907 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
AceStaking
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // Creator: andreitoma8 pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol"; import "@openzeppelin/contracts/token/ERC777/IERC777Sender.sol"; import "@openzeppelin/contracts/token/ERC777/IERC777.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol"; import "@openzeppelin/contracts/utils/introspection/ERC1820Implementer.sol"; contract AceStaking is Ownable, ReentrancyGuard, IERC721Receiver, IERC777Sender, IERC777Recipient, ERC1820Implementer { // Interfaces for ERC777 and ERC721 IERC777 public immutable rewardsToken; mapping(address => IERC721) public nftContracts; address[] public nftContractAddresses; // Reward Settings mapping(address => uint256) public rewardsForContract; mapping(address => mapping(uint256 => uint256)) public additionalRewardsForToken; uint256 public rewardPeriodInSeconds; uint256 public totalTokensStakedCount; address internal REWARD_UPDATER; // Definition of Staker struct Staker { uint256 unclaimedRewards; uint256 lifetimeRewards; uint256 lastRewardedAt; uint256 lastClaimedAt; } // This is how we expect Tokens to be sent struct TokenData { address contractAddress; uint256 tokenIdentifier; } // How we keep track of a Staked token struct StakedToken { address contractAddress; uint256 tokenIdentifier; uint256 lastRewardedAt; uint256 stakedAt; } event UnstakedNFT(StakedToken stakedToken, address indexed staker); event StakedNFT(StakedToken stakedToken, address indexed staker); event RewardClaimed(address indexed staker, uint256 indexed amount); address[] public currentStakers; mapping(address => Staker) public stakers; mapping(address => StakedToken[]) public stakedTokensForAddress; mapping(address => mapping(uint256 => address)) public stakedTokenOwner; mapping(uint256 => mapping(address => uint256)) internal sharesForWalletInRound; mapping(uint256 => address[]) internal walletsToRewardInRound; uint256 internal currentRoundId; uint256 public slashingPeriod = 24; // ERC777 Definitions event TokensToSendCalled( address operator, address from, address to, uint256 amount, bytes data, bytes operatorData, address token, uint256 fromBalance, uint256 toBalance ); event TokensReceivedCalled( address operator, address from, address to, uint256 amount, bytes data, bytes operatorData, address token, uint256 fromBalance, uint256 toBalance ); bool private _shouldRevertSend; bool private _shouldRevertReceive; IERC1820Registry internal constant _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24); bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender"); bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient"); /** * @dev Setsup the new Contract. * * @param _rewardsToken A ERC777 Token. Can't be changed! * @param _rewardPeriodInSeconds Every x Seconds the Reward gets emitted. Can't be changed! Needs to be at least 60 Seconds but at least a day is recommneded. */ constructor(IERC777 _rewardsToken, uint256 _rewardPeriodInSeconds) { require( _rewardPeriodInSeconds > 60, "AceStaking: Rewards need to be paid at least once per minute" ); rewardsToken = _rewardsToken; rewardPeriodInSeconds = _rewardPeriodInSeconds; REWARD_UPDATER = msg.sender; _ERC1820_REGISTRY.setInterfaceImplementer( address(this), _TOKENS_RECIPIENT_INTERFACE_HASH, address(this) ); _ERC1820_REGISTRY.setInterfaceImplementer( address(this), _TOKENS_SENDER_INTERFACE_HASH, address(this) ); } /** * @dev Call this function to add a new NFT Contract to be accepted for staking. * Each contract can have differen rewards. * * Requirements: onlyOwner can add new Contracts; Contract needs to be ERC721 compliant. * @param _nftContract A ERC721 Contract that can be used for staking. * @param _reward ERC777 Token Value that is rewarded for each token every rewardPeriodInSeconds. */ function addNFTContract(IERC721 _nftContract, uint256 _reward) public onlyOwner { nftContracts[address(_nftContract)] = _nftContract; nftContractAddresses.push(address(_nftContract)); rewardsForContract[address(_nftContract)] = _reward; } /** * @dev Call this function to remove a NFT contract from beeing accepted for staking. * All tokens remain in the contract but wont receive any further rewards. They can be withdrawn by * the token owner. * Warning: Additional Rewards might stay in place, so call setAdditionalRewardsForTokens first and set their reward to 0. * * Requirements: onlyOwner can remove Contracts; Contract needs to be ERC721 compliant and already added through addNFTContract. * @param _nftContract A ERC721 Contract that should be removed from staking. */ function removeNFTContract(address _nftContract) public onlyOwner { require( nftContracts[_nftContract] == IERC721(_nftContract), "AceStaking: Unkown Contract" ); nftContracts[address(_nftContract)] = IERC721(address(0)); rewardsForContract[address(_nftContract)] = 0; for (uint256 i; i < nftContractAddresses.length; i = unsafe_inc(i)) { if (nftContractAddresses[i] == _nftContract) { nftContractAddresses[i] = nftContractAddresses[ nftContractAddresses.length - 1 ]; nftContractAddresses.pop(); } } } /** * @dev This function allows the contract owner to set an additional bonus that is * added for each token. The reward is added on top to the default reward for the contract. * * Requirements: onlyOwner or rewardUpdate (external contract) can remove Contracts; Contract needs to be ERC721 compliant * and already added through addNFTContract. * @param _nftContract A ERC721 Contract that is accepted by the contract. * @param _tokenIdentifiers Array of Identifiers that should receive the additional reward * @param _additionalReward ERC777 Token Value that is rewarded for each token every rewardPeriodInSeconds additionally to the default reward. */ function setAdditionalRewardsForTokens( IERC721 _nftContract, uint256[] memory _tokenIdentifiers, uint256 _additionalReward ) external onlyRewardUpdater { require( nftContracts[address(_nftContract)] == IERC721(_nftContract), "AceStaking: Unkown Contract" ); uint256 tokenCounter = _tokenIdentifiers.length; for (uint256 i; i < tokenCounter; i = unsafe_inc(i)) { additionalRewardsForToken[address(_nftContract)][ _tokenIdentifiers[i] ] = _additionalReward; } } /** * @dev You need to claim your rewards at least once within this period. * If not you won't get any new rewards until you claim again. * * Requirements: onlyOwner can change that value * * @param _slashingPeriod Amount of Periods after that rewards get slashed */ function setSlashingPeriod(uint256 _slashingPeriod) external onlyOwner { slashingPeriod = _slashingPeriod; } /** * @dev We reward a Bonus depending on different traits in some periods. * The choosen traits and to be rewareded tokens are calculated off-chain. * Tokens need to be staked when the reward is paid and already staked in the Snapshot of Tokens that is sent. * If you want to learn more about how our trait based bonus works take a look at our website. * * @param _tokens Array of TokenData(contractAddress, tokenId) * @param _totalBonus Amount of Tokens that should be distributed among sent tokens */ function rewardBonus(TokenData[] calldata _tokens, uint256 _totalBonus) external onlyRewardUpdater { uint256 stakedTokensLength = _tokens.length; require(stakedTokensLength > 0, "AceStaking: No Tokens"); require( _totalBonus > 0, "AceStaking: No Bonus to be distributed" ); uint256 totalShares; currentRoundId += 1; for (uint256 i; i < stakedTokensLength; i = unsafe_inc(i)) { address _staker = stakedTokenOwner[_tokens[i].contractAddress][ _tokens[i].tokenIdentifier ]; if (_staker != address(0)) { sharesForWalletInRound[currentRoundId][_staker] += 100; walletsToRewardInRound[currentRoundId].push(_staker); totalShares += 1; } } require(totalShares > 0, "AceStaking: No shares to distribute"); uint256 walletsToRewardLength = walletsToRewardInRound[currentRoundId] .length; for (uint256 i; i < walletsToRewardLength; i = unsafe_inc(i)) { address walletToCheck = walletsToRewardInRound[currentRoundId][i]; if (sharesForWalletInRound[currentRoundId][walletToCheck] > 0) { uint256 rewardsForWallet = (sharesForWalletInRound[ currentRoundId ][walletToCheck] / totalShares) * (_totalBonus / 100); stakers[walletToCheck].unclaimedRewards += rewardsForWallet; stakers[walletToCheck].lifetimeRewards += rewardsForWallet; sharesForWalletInRound[currentRoundId][walletToCheck] = 0; } } } /** * @dev Function to estimate rewards for specific token on a contract in one period. * Token ID could be out of range we don't care since this is just for * simulating unstaked token rewards for UI. * * Requirements: nftContractAddress needs to be registereed on the staking contract. * @param nftContractAddress A ERC721 Contract of the token * @param tokenIdentifier Token Identifier that you want an estimation for */ function estimateRewardsForToken( address nftContractAddress, uint256 tokenIdentifier ) public view returns (uint256) { require( nftContracts[nftContractAddress] == IERC721(nftContractAddress), "AceStaking: Unkown Contract" ); return rewardsForToken(nftContractAddress, tokenIdentifier); } /** * @dev Returns multiple stats for the address. Returns those values: * - totalTokensStaked: Count of Tokens for this Wallet on the Staking Contract * - unclaimedRewards: Rewards that can be claimed but are unclaimed by the user * - unaccountedRewards: Rewards that are not ready to be claimed * because the current period did not finish yet. If tokens were staked on different * start times this number might never be 0. * - lifetimeRewards: Just counting up what a user earned over life * * @param _stakerAddress Wallet Address that has staked tokens on the contract */ function stakerStats(address _stakerAddress) public view returns ( uint256 totalTokensStaked, uint256 unclaimedRewards, uint256 unaccountedRewards, uint256 lifetimeRewards ) { Staker memory staker = stakers[_stakerAddress]; uint256 claimableRewards = calculateUnaccountedRewards( _stakerAddress, false ); return ( stakedTokensForAddress[_stakerAddress].length, staker.unclaimedRewards + claimableRewards, calculateUnaccountedRewards(_stakerAddress, true), staker.lifetimeRewards + claimableRewards ); } /** * @dev Function to unstake all tokens for the msg.sender. * Also rewards msg.sender for all of his staked tokens his staked tokens and ejects all tokens after this. * If you have many tokens staked (50+) we recommend unstaking them in badges to not hit the gas limit of a block. */ function unstakeAllTokens() external nonReentrant { StakedToken[] memory stakedTokens = stakedTokensForAddress[msg.sender]; uint256 stakedTokensLength = stakedTokens.length; require(stakedTokensLength > 0, "AceStaking: No Tokens found"); rewardStaker(msg.sender); for (uint256 i; i < stakedTokensLength; i = unsafe_inc(i)) { ejectToken( stakedTokens[i].contractAddress, stakedTokens[i].tokenIdentifier ); } } /** * @dev Unstake a Set of Tokens for msg.sender. * Also rewards msg.sender for all of his staked tokens his staked tokens and ejects all sent tokens after this. * * @param _tokens Array of TokenData(contractAddress, tokenId) */ function unstake(TokenData[] calldata _tokens) external nonReentrant { uint256 stakedTokensLength = _tokens.length; require(stakedTokensLength > 0, "AceStaking: No Tokens found"); rewardStaker(msg.sender); for (uint256 i; i < stakedTokensLength; i = unsafe_inc(i)) { ejectToken(_tokens[i].contractAddress, _tokens[i].tokenIdentifier); } } /** * @dev Emergency Unstake Function: Unstake without any reward calculation. * !!! NOT RECOMMENDED, YOU MIGHT LOSE UNACCOUNTED REWARDS !!! * When to use? This function consumes less gas then the normal unstake since we do not reward all tokens before unstaking. * In case you hit the block limit for gas (very unlikely) we have a way to withdrawal your tokens somehow. * @param _tokens Array of TokenData(contractAddress, tokenId) */ function emergencyUnstake(TokenData[] calldata _tokens) external nonReentrant { uint256 stakedTokensLength = _tokens.length; require(stakedTokensLength > 0, "AceStaking: No Tokens in calldata"); for (uint256 i; i < stakedTokensLength; i = unsafe_inc(i)) { ejectToken(_tokens[i].contractAddress, _tokens[i].tokenIdentifier); } } /** * @dev This function transfers tokens to the contract with transferFrom. * thusfor we need to call addToken manually but we save a little on gas. * * Requirements: All token contracts need to be added to this contract and be approved by the user. * * @param _tokens Array of TokenData(contractAddress, tokenId) */ function stake(TokenData[] calldata _tokens) external { beforeTokensAdded(msg.sender); uint256 tokensLength = _tokens.length; for (uint256 i; i < tokensLength; i = unsafe_inc(i)) { IERC721(_tokens[i].contractAddress).transferFrom( msg.sender, address(this), _tokens[i].tokenIdentifier ); addToken( _tokens[i].contractAddress, _tokens[i].tokenIdentifier, msg.sender ); } } /** * @dev Call this function to get your ERC777 Token rewards transfered to your wallet. * This is an expensive call since we calculate your current earnings and send them in one * Transaction to your wallet. * */ function claimRewards() external nonReentrant { rewardStaker(msg.sender); require( stakers[msg.sender].unclaimedRewards > 0, "AceStaking: Nothing to claim" ); IERC777(rewardsToken).send( msg.sender, stakers[msg.sender].unclaimedRewards, "" ); emit RewardClaimed(msg.sender, stakers[msg.sender].unclaimedRewards); stakers[msg.sender].unclaimedRewards = 0; stakers[msg.sender].lastClaimedAt = block.timestamp; } /** * @dev This function determains how many periods should be calculated for rewarding. * * @param _lastRewardedAt timestamp when the token was rewarded last * @param _lastClaimedAt timestamp when ist was last claimed * */ function rewardPeriods(uint256 _lastRewardedAt, uint256 _lastClaimedAt) internal view returns (uint256 _rewardPeriodCounter) { uint256 referenceTimestamp = block.timestamp; if ( referenceTimestamp > (_lastClaimedAt + slashingPeriod * rewardPeriodInSeconds) ) { referenceTimestamp = _lastClaimedAt + slashingPeriod * rewardPeriodInSeconds; } return (referenceTimestamp - _lastRewardedAt) / rewardPeriodInSeconds; } /** * @dev Calculates Rewards for a User and accounts them to his entry. * * @param _stakerAddress staker that should be rewarded * */ function rewardUnaccountedRewards(address _stakerAddress) internal returns (uint256 _rewards) { StakedToken[] memory stakedTokens = stakedTokensForAddress[ _stakerAddress ]; uint256 totalRewards; uint256 stakedTokensCount = stakedTokens.length; for (uint256 i; i < stakedTokensCount; i = unsafe_inc(i)) { uint256 periodsToReward = rewardPeriods( stakedTokens[i].lastRewardedAt, stakers[_stakerAddress].lastClaimedAt ); if (periodsToReward > 0) { totalRewards += periodsToReward * rewardsForToken( stakedTokens[i].contractAddress, stakedTokens[i].tokenIdentifier ); if (periodsToReward == slashingPeriod) { stakedTokensForAddress[_stakerAddress][i].lastRewardedAt = stakedTokensForAddress[_stakerAddress][i].stakedAt + ( uint256( (block.timestamp - stakedTokensForAddress[_stakerAddress][i] .stakedAt) / rewardPeriodInSeconds ) ) * rewardPeriodInSeconds; } else { stakedTokensForAddress[_stakerAddress][i].lastRewardedAt = stakedTokensForAddress[_stakerAddress][i].stakedAt + periodsToReward * rewardPeriodInSeconds; } } } return totalRewards; } /** * @dev Calculates Rewards for a User but does not account them. * * @param _stakerAddress staker that should be rewarded * @param _simulateUnaccounted include unaccounted rewards that can't be claimed yet * */ function calculateUnaccountedRewards( address _stakerAddress, bool _simulateUnaccounted ) internal view returns (uint256 _rewards) { StakedToken[] memory stakedTokens = stakedTokensForAddress[ _stakerAddress ]; uint256 totalRewards; uint256 stakedTokensCount = stakedTokens.length; for (uint256 i; i < stakedTokensCount; i = unsafe_inc(i)) { uint256 periodsToReward = rewardPeriods( stakedTokens[i].lastRewardedAt, stakers[_stakerAddress].lastClaimedAt ); uint256 tokenReward = rewardsForToken( stakedTokens[i].contractAddress, stakedTokens[i].tokenIdentifier ); if (_simulateUnaccounted) { totalRewards += ((((block.timestamp - stakedTokens[i].lastRewardedAt) * 100) / rewardPeriodInSeconds) * tokenReward) / 100 - periodsToReward * tokenReward; } else { totalRewards += tokenReward * periodsToReward; } } return totalRewards; } /** * @dev Summarize rewards for a specific token on a contract. * Sums up default rewards for contract and bonus for token identifier. * * @param nftContractAddress Contract to check * @param tokenIdentifier Token Identifier to check * */ function rewardsForToken( address nftContractAddress, uint256 tokenIdentifier ) internal view returns (uint256) { return rewardsForContract[nftContractAddress] + additionalRewardsForToken[nftContractAddress][tokenIdentifier]; } /** * @dev Function that moves all unaccounted rewards to unclaimed. * This call is required to keep our internal balance sheets up to date. * Depending on Token Amount this is very expensive to call since we loop through all tokens! * * @param _address Wallet Address that should be rewarded * */ function rewardStaker(address _address) internal { uint256 unaccountedRewards = rewardUnaccountedRewards(_address); stakers[_address].lastRewardedAt = block.timestamp; stakers[_address].unclaimedRewards += unaccountedRewards; stakers[_address].lifetimeRewards += unaccountedRewards; } /** * @dev Internal function to send a token back to a user. Also * removes / updates all contract internal trackings. * * Requirements: msg.sender needs to be the wallet that sent the token to the contract. * * @param nftContractAddress Contract for the token to be ejected * @param tokenIdentifier Token Identifier for the token to be ejected * */ function ejectToken(address nftContractAddress, uint256 tokenIdentifier) internal { require( stakedTokenOwner[nftContractAddress][tokenIdentifier] == msg.sender, "AceStaking: Not your token..." ); IERC721(nftContractAddress).transferFrom( address(this), msg.sender, tokenIdentifier ); for ( uint256 i; i < stakedTokensForAddress[msg.sender].length; i = unsafe_inc(i) ) { if ( stakedTokensForAddress[msg.sender][i].tokenIdentifier == tokenIdentifier && stakedTokensForAddress[msg.sender][i].contractAddress == nftContractAddress ) { emit UnstakedNFT( stakedTokensForAddress[msg.sender][i], msg.sender ); stakedTokensForAddress[msg.sender][i] = stakedTokensForAddress[ msg.sender ][stakedTokensForAddress[msg.sender].length - 1]; stakedTokensForAddress[msg.sender].pop(); } } if (stakedTokensForAddress[msg.sender].length == 0) { for (uint256 i; i < currentStakers.length; i = unsafe_inc(i)) { if (currentStakers[i] == msg.sender) { currentStakers[i] = currentStakers[ currentStakers.length - 1 ]; currentStakers.pop(); } } } stakedTokenOwner[msg.sender][tokenIdentifier] = address(0); totalTokensStakedCount -= 1; } /** * @dev Helper that should be called before any token is added. Needs to be called * only once per batch. It basically setup the staker object. * * @param _staker Wallet Address for Staker */ function beforeTokensAdded(address _staker) internal { if (stakedTokensForAddress[_staker].length == 0) { if (stakers[_staker].lastRewardedAt > 0) { // This wallet already staked before and was at least rewarded once. stakers[_staker].lastRewardedAt = block.timestamp; stakers[_staker].lastClaimedAt = block.timestamp; } else { // This wallet is new to us stakers[_staker] = Staker( stakers[_staker].unclaimedRewards, stakers[_staker].lifetimeRewards, block.timestamp, block.timestamp ); } currentStakers.push(_staker); } } /** * @dev Function to add a token and regiter it in all mappings that we need to * return and reward a token. * * @param nftContractAddress Contract of the token * @param tokenIdentifier The Identifier of a token * @param tokenOwnerAddress The address of the current owner */ function addToken( address nftContractAddress, uint256 tokenIdentifier, address tokenOwnerAddress ) internal { require( nftContracts[nftContractAddress] == IERC721(nftContractAddress), "AceStaking: Unkown Contract" ); StakedToken memory newToken = StakedToken( nftContractAddress, tokenIdentifier, block.timestamp, block.timestamp ); stakedTokenOwner[nftContractAddress][ tokenIdentifier ] = tokenOwnerAddress; stakedTokensForAddress[tokenOwnerAddress].push(newToken); totalTokensStakedCount += 1; emit StakedNFT(newToken, tokenOwnerAddress); } function unsafe_inc(uint256 x) private pure returns (uint256) { unchecked { return x + 1; } } /** * @dev See {IERC721Receiver-onERC721Received}. Also registers token in our TokenRegistry. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address, // operator not required address tokenOwnerAddress, uint256 tokenIdentifier, bytes memory ) public virtual override returns (bytes4) { beforeTokensAdded(tokenOwnerAddress); addToken(msg.sender, tokenIdentifier, tokenOwnerAddress); return this.onERC721Received.selector; } function tokensToSend( address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external override { if (_shouldRevertSend) { revert(); } IERC777 token = IERC777(_msgSender()); uint256 fromBalance = token.balanceOf(from); // when called due to burn, to will be the zero address, which will have a balance of 0 uint256 toBalance = token.balanceOf(to); emit TokensToSendCalled( operator, from, to, amount, userData, operatorData, address(token), fromBalance, toBalance ); } function tokensReceived( address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external override { if (_shouldRevertReceive) { revert(); } IERC777 token = IERC777(_msgSender()); uint256 fromBalance = token.balanceOf(from); // when called due to burn, to will be the zero address, which will have a balance of 0 uint256 toBalance = token.balanceOf(to); emit TokensReceivedCalled( operator, from, to, amount, userData, operatorData, address(token), fromBalance, toBalance ); } /** * @dev This address is allowed to change the rewards for a specific token. * Since opening a chest door results in a different reward, this is implemented in the chest door opener contract later. * * @param _REWARD_UPDATER Address that is allowed to modify rewards */ function setRewardUpdater(address _REWARD_UPDATER) external onlyOwner { REWARD_UPDATER = _REWARD_UPDATER; } modifier onlyRewardUpdater() { require( msg.sender == REWARD_UPDATER || msg.sender == owner(), "AceStaking: Only REWARD_UPDATE or OWNER." ); _; } } /** created with bowline.app **/
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC1820Registry.sol) pragma solidity ^0.8.0; /** * @dev Interface of the global ERC1820 Registry, as defined in the * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register * implementers for interfaces in this registry, as well as query support. * * Implementers may be shared by multiple accounts, and can also implement more * than a single interface for each account. Contracts can implement interfaces * for themselves, but externally-owned accounts (EOA) must delegate this to a * contract. * * {IERC165} interfaces can also be queried via the registry. * * For an in-depth explanation and source code analysis, see the EIP text. */ interface IERC1820Registry { /** * @dev Sets `newManager` as the manager for `account`. A manager of an * account is able to set interface implementers for it. * * By default, each account is its own manager. Passing a value of `0x0` in * `newManager` will reset the manager to this initial state. * * Emits a {ManagerChanged} event. * * Requirements: * * - the caller must be the current manager for `account`. */ function setManager(address account, address newManager) external; /** * @dev Returns the manager for `account`. * * See {setManager}. */ function getManager(address account) external view returns (address); /** * @dev Sets the `implementer` contract as ``account``'s implementer for * `interfaceHash`. * * `account` being the zero address is an alias for the caller's address. * The zero address can also be used in `implementer` to remove an old one. * * See {interfaceHash} to learn how these are created. * * Emits an {InterfaceImplementerSet} event. * * Requirements: * * - the caller must be the current manager for `account`. * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not * end in 28 zeroes). * - `implementer` must implement {IERC1820Implementer} and return true when * queried for support, unless `implementer` is the caller. See * {IERC1820Implementer-canImplementInterfaceForAddress}. */ function setInterfaceImplementer( address account, bytes32 _interfaceHash, address implementer ) external; /** * @dev Returns the implementer of `interfaceHash` for `account`. If no such * implementer is registered, returns the zero address. * * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28 * zeroes), `account` will be queried for support of it. * * `account` being the zero address is an alias for the caller's address. */ function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address); /** * @dev Returns the interface hash for an `interfaceName`, as defined in the * corresponding * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP]. */ function interfaceHash(string calldata interfaceName) external pure returns (bytes32); /** * @notice Updates the cache with whether the contract implements an ERC165 interface or not. * @param account Address of the contract for which to update the cache. * @param interfaceId ERC165 interface for which to update the cache. */ function updateERC165Cache(address account, bytes4 interfaceId) external; /** * @notice Checks whether a contract implements an ERC165 interface or not. * If the result is not cached a direct lookup on the contract address is performed. * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling * {updateERC165Cache} with the contract address. * @param account Address of the contract to check. * @param interfaceId ERC165 interface to check. * @return True if `account` implements `interfaceId`, false otherwise. */ function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool); /** * @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache. * @param account Address of the contract to check. * @param interfaceId ERC165 interface to check. * @return True if `account` implements `interfaceId`, false otherwise. */ function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool); event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer); event ManagerChanged(address indexed account, address indexed newManager); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC1820Implementer.sol) pragma solidity ^0.8.0; /** * @dev Interface for an ERC1820 implementer, as defined in the * https://eips.ethereum.org/EIPS/eip-1820#interface-implementation-erc1820implementerinterface[EIP]. * Used by contracts that will be registered as implementers in the * {IERC1820Registry}. */ interface IERC1820Implementer { /** * @dev Returns a special value (`ERC1820_ACCEPT_MAGIC`) if this contract * implements `interfaceHash` for `account`. * * See {IERC1820Registry-setInterfaceImplementer}. */ function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @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 v4.4.0 (utils/introspection/ERC1820Implementer.sol) pragma solidity ^0.8.0; import "./IERC1820Implementer.sol"; /** * @dev Implementation of the {IERC1820Implementer} interface. * * Contracts may inherit from this and call {_registerInterfaceForAddress} to * declare their willingness to be implementers. * {IERC1820Registry-setInterfaceImplementer} should then be called for the * registration to be complete. */ contract ERC1820Implementer is IERC1820Implementer { bytes32 private constant _ERC1820_ACCEPT_MAGIC = keccak256("ERC1820_ACCEPT_MAGIC"); mapping(bytes32 => mapping(address => bool)) private _supportedInterfaces; /** * @dev See {IERC1820Implementer-canImplementInterfaceForAddress}. */ function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) public view virtual override returns (bytes32) { return _supportedInterfaces[interfaceHash][account] ? _ERC1820_ACCEPT_MAGIC : bytes32(0x00); } /** * @dev Declares the contract as willing to be an implementer of * `interfaceHash` for `account`. * * See {IERC1820Registry-setInterfaceImplementer} and * {IERC1820Registry-interfaceHash}. */ function _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal virtual { _supportedInterfaces[interfaceHash][account] = true; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC777/IERC777Sender.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777TokensSender standard as defined in the EIP. * * {IERC777} Token holders can be notified of operations performed on their * tokens by having a contract implement this interface (contract holders can be * their own implementer) and registering it on the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry]. * * See {IERC1820Registry} and {ERC1820Implementer}. */ interface IERC777Sender { /** * @dev Called by an {IERC777} token contract whenever a registered holder's * (`from`) tokens are about to be moved or destroyed. The type of operation * is conveyed by `to` being the zero address or not. * * This call occurs _before_ the token contract's state is updated, so * {IERC777-balanceOf}, etc., can be used to query the pre-operation state. * * This function may revert to prevent the operation from being executed. */ function tokensToSend( address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC777/IERC777Recipient.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP. * * Accounts can be notified of {IERC777} tokens being sent to them by having a * contract implement this interface (contract holders can be their own * implementer) and registering it on the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry]. * * See {IERC1820Registry} and {ERC1820Implementer}. */ interface IERC777Recipient { /** * @dev Called by an {IERC777} token contract whenever tokens are being * moved or created into a registered account (`to`). The type of operation * is conveyed by `from` being the zero address or not. * * This call occurs _after_ the token contract's state is updated, so * {IERC777-balanceOf}, etc., can be used to query the post-operation state. * * This function may revert to prevent the operation from being executed. */ function tokensReceived( address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC777/IERC777.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777Token standard as defined in the EIP. * * This contract uses the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let * token holders and recipients react to token movements by using setting implementers * for the associated interfaces in said registry. See {IERC1820Registry} and * {ERC1820Implementer}. */ interface IERC777 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * For most token contracts, this value will equal 1. */ function granularity() external view returns (uint256); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by an account (`owner`). */ function balanceOf(address owner) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `data` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send( address recipient, uint256 amount, bytes calldata data ) external; /** * @dev Destroys `amount` tokens from the caller's account, reducing the * total supply. * * If a send hook is registered for the caller, the corresponding function * will be called with `data` and empty `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - the caller must have at least `amount` tokens. */ function burn(uint256 amount, bytes calldata data) external; /** * @dev Returns true if an account is an operator of `tokenHolder`. * Operators can send and burn tokens on behalf of their owners. All * accounts are their own operator. * * See {operatorSend} and {operatorBurn}. */ function isOperatorFor(address operator, address tokenHolder) external view returns (bool); /** * @dev Make an account an operator of the caller. * * See {isOperatorFor}. * * Emits an {AuthorizedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external; /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * Emits a {RevokedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function revokeOperator(address operator) external; /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `data` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; /** * @dev Destroys `amount` tokens from `account`, reducing the total supply. * The caller must be an operator of `account`. * * If a send hook is registered for `account`, the corresponding function * will be called with `data` and `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn( address account, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; event Sent( address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData ); event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); event AuthorizedOperator(address indexed operator, address indexed tokenHolder); event RevokedOperator(address indexed operator, address indexed tokenHolder); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
{ "remappings": [], "optimizer": { "enabled": false, "runs": 200 }, "evmVersion": "london", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IERC777","name":"_rewardsToken","type":"address"},{"internalType":"uint256","name":"_rewardPeriodInSeconds","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"},{"internalType":"uint256","name":"lastRewardedAt","type":"uint256"},{"internalType":"uint256","name":"stakedAt","type":"uint256"}],"indexed":false,"internalType":"struct AceStaking.StakedToken","name":"stakedToken","type":"tuple"},{"indexed":true,"internalType":"address","name":"staker","type":"address"}],"name":"StakedNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toBalance","type":"uint256"}],"name":"TokensReceivedCalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toBalance","type":"uint256"}],"name":"TokensToSendCalled","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"},{"internalType":"uint256","name":"lastRewardedAt","type":"uint256"},{"internalType":"uint256","name":"stakedAt","type":"uint256"}],"indexed":false,"internalType":"struct AceStaking.StakedToken","name":"stakedToken","type":"tuple"},{"indexed":true,"internalType":"address","name":"staker","type":"address"}],"name":"UnstakedNFT","type":"event"},{"inputs":[{"internalType":"contract IERC721","name":"_nftContract","type":"address"},{"internalType":"uint256","name":"_reward","type":"uint256"}],"name":"addNFTContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"additionalRewardsForToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"interfaceHash","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"canImplementInterfaceForAddress","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"currentStakers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"}],"internalType":"struct AceStaking.TokenData[]","name":"_tokens","type":"tuple[]"}],"name":"emergencyUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContractAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"}],"name":"estimateRewardsForToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftContractAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nftContracts","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"tokenOwnerAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContract","type":"address"}],"name":"removeNFTContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"}],"internalType":"struct AceStaking.TokenData[]","name":"_tokens","type":"tuple[]"},{"internalType":"uint256","name":"_totalBonus","type":"uint256"}],"name":"rewardBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPeriodInSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsForContract","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC777","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_nftContract","type":"address"},{"internalType":"uint256[]","name":"_tokenIdentifiers","type":"uint256[]"},{"internalType":"uint256","name":"_additionalReward","type":"uint256"}],"name":"setAdditionalRewardsForTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_REWARD_UPDATER","type":"address"}],"name":"setRewardUpdater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_slashingPeriod","type":"uint256"}],"name":"setSlashingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slashingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"}],"internalType":"struct AceStaking.TokenData[]","name":"_tokens","type":"tuple[]"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakedTokenOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakedTokensForAddress","outputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"},{"internalType":"uint256","name":"lastRewardedAt","type":"uint256"},{"internalType":"uint256","name":"stakedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_stakerAddress","type":"address"}],"name":"stakerStats","outputs":[{"internalType":"uint256","name":"totalTokensStaked","type":"uint256"},{"internalType":"uint256","name":"unclaimedRewards","type":"uint256"},{"internalType":"uint256","name":"unaccountedRewards","type":"uint256"},{"internalType":"uint256","name":"lifetimeRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakers","outputs":[{"internalType":"uint256","name":"unclaimedRewards","type":"uint256"},{"internalType":"uint256","name":"lifetimeRewards","type":"uint256"},{"internalType":"uint256","name":"lastRewardedAt","type":"uint256"},{"internalType":"uint256","name":"lastClaimedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"tokensReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"tokensToSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalTokensStakedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenIdentifier","type":"uint256"}],"internalType":"struct AceStaking.TokenData[]","name":"_tokens","type":"tuple[]"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakeAllTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a060405260186011553480156200001657600080fd5b506040516200586e3803806200586e83398181016040528101906200003c919062000400565b6200005c620000506200027b60201b60201c565b6200028360201b60201c565b60018081905550603c8111620000a9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000a090620004ce565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508060078190555033600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff166329965a1d307fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b306040518463ffffffff1660e01b815260040162000198939291906200051c565b600060405180830381600087803b158015620001b357600080fd5b505af1158015620001c8573d6000803e3d6000fd5b50505050731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff166329965a1d307f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895306040518463ffffffff1660e01b81526004016200023f939291906200051c565b600060405180830381600087803b1580156200025a57600080fd5b505af11580156200026f573d6000803e3d6000fd5b50505050505062000559565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000379826200034c565b9050919050565b60006200038d826200036c565b9050919050565b6200039f8162000380565b8114620003ab57600080fd5b50565b600081519050620003bf8162000394565b92915050565b6000819050919050565b620003da81620003c5565b8114620003e657600080fd5b50565b600081519050620003fa81620003cf565b92915050565b600080604083850312156200041a576200041962000347565b5b60006200042a85828601620003ae565b92505060206200043d85828601620003e9565b9150509250929050565b600082825260208201905092915050565b7f4163655374616b696e673a2052657761726473206e65656420746f206265207060008201527f616964206174206c65617374206f6e636520706572206d696e75746500000000602082015250565b6000620004b6603c8362000447565b9150620004c38262000458565b604082019050919050565b60006020820190508181036000830152620004e981620004a7565b9050919050565b620004fb816200036c565b82525050565b6000819050919050565b620005168162000501565b82525050565b6000606082019050620005336000830186620004f0565b6200054260208301856200050b565b620005516040830184620004f0565b949350505050565b6080516152f26200057c60003960008181610adc0152611b0201526152f26000f3fe608060405234801561001057600080fd5b50600436106101ef5760003560e01c8063889dc3051161010f578063d1af0c7d116100a2578063dce9f7aa11610071578063dce9f7aa146105cf578063ed24f661146105eb578063f2fde38b14610609578063ffac2ae314610625576101ef565b8063d1af0c7d1461055b578063d5dbbce514610579578063d64f152a14610595578063da1af08f146105b1576101ef565b806394d8d7e9116100de57806394d8d7e9146104be578063a65ae961146104da578063ada0f98f1461050d578063bf91d8e41461053d576101ef565b8063889dc305146104355780638da5cb5b146104515780638fc67c261461046f5780639168ae721461048b576101ef565b8063385bfbb411610187578063715018a611610156578063715018a6146103c357806375ab9782146103cd5780637dad54c8146103e9578063801c523614610419576101ef565b8063385bfbb41461033a5780634258fcf614610356578063499d9d94146103895780635d85f3a1146103b9576101ef565b806318b85e33116101c357806318b85e33146102a05780631bbd8a41146102d0578063249cb3fa14610300578063372500ab14610330576101ef565b806223de29146101f45780630c4735b814610210578063145778d614610240578063150b7a0214610270575b600080fd5b61020e60048036038101906102099190613f53565b610641565b005b61022a60048036038101906102259190614022565b6107bb565b6040516102379190614071565b60405180910390f35b61025a6004803603810190610255919061408c565b61089c565b60405161026791906140c8565b60405180910390f35b61028a60048036038101906102859190614224565b6108db565b60405161029791906142e2565b60405180910390f35b6102ba60048036038101906102b5919061408c565b610903565b6040516102c791906140c8565b60405180910390f35b6102ea60048036038101906102e59190614022565b610942565b6040516102f79190614071565b60405180910390f35b61031a60048036038101906103159190614333565b610967565b6040516103279190614382565b60405180910390f35b6103386109fe565b005b610354600480360381019061034f919061439d565b610cc7565b005b610370600480360381019061036b919061439d565b61105e565b60405161038094939291906143ca565b60405180910390f35b6103a3600480360381019061039e919061439d565b611168565b6040516103b09190614071565b60405180910390f35b6103c1611180565b005b6103cb61139a565b005b6103e760048036038101906103e29190613f53565b611422565b005b61040360048036038101906103fe9190614022565b61159c565b60405161041091906140c8565b60405180910390f35b610433600480360381019061042e9190614465565b6115de565b005b61044f600480360381019061044a9190614465565b611716565b005b610459611827565b60405161046691906140c8565b60405180910390f35b6104896004803603810190610484919061439d565b611850565b005b6104a560048036038101906104a0919061439d565b611910565b6040516104b594939291906143ca565b60405180910390f35b6104d860048036038101906104d39190614465565b611940565b005b6104f460048036038101906104ef9190614022565b611a5a565b60405161050494939291906144b2565b60405180910390f35b6105276004803603810190610522919061439d565b611ac7565b6040516105349190614556565b60405180910390f35b610545611afa565b6040516105529190614071565b60405180910390f35b610563611b00565b6040516105709190614592565b60405180910390f35b610593600480360381019061058e91906146ae565b611b24565b005b6105af60048036038101906105aa919061408c565b611d55565b005b6105b9611ddb565b6040516105c69190614071565b60405180910390f35b6105e960048036038101906105e4919061471d565b611de1565b005b6105f3611f86565b6040516106009190614071565b60405180910390f35b610623600480360381019061061e919061439d565b611f8c565b005b61063f600480360381019061063a919061475d565b612084565b005b601260019054906101000a900460ff161561065b57600080fd5b60006106656126b2565b905060008173ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b81526004016106a291906140c8565b602060405180830381865afa1580156106bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e391906147d2565b905060008273ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b815260040161072091906140c8565b602060405180830381865afa15801561073d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076191906147d2565b90507f47e915878c47f3ec4d7ff646a2becb229f64fd2abe4d2b5e2bb4275b0cf50d4e8b8b8b8b8b8b8b8b8b8b8b6040516107a69b9a9998979695949392919061483d565b60405180910390a15050505050505050505050565b60008273ffffffffffffffffffffffffffffffffffffffff16600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461088a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088190614939565b60405180910390fd5b61089483836126ba565b905092915050565b600481815481106108ac57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006108e68461275f565b6108f13384866129ff565b63150b7a0260e01b9050949350505050565b600a818154811061091357600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6006602052816000526040600020602052806000526040600020600091509150505481565b60006002600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166109d4576000801b6109f6565b7fa2ef4600d742022d532d4747cb3547474667d6f13804902513b2ec01c848f4b45b905092915050565b60026001541415610a44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3b906149a5565b60405180910390fd5b6002600181905550610a5533612cd4565b6000600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015411610ada576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad190614a11565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bd9bbc633600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546040518363ffffffff1660e01b8152600401610b77929190614a57565b600060405180830381600087803b158015610b9157600080fd5b505af1158015610ba5573d6000803e3d6000fd5b50505050600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001543373ffffffffffffffffffffffffffffffffffffffff167f106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f724160405160405180910390a36000600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018190555042600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003018190555060018081905550565b610ccf6126b2565b73ffffffffffffffffffffffffffffffffffffffff16610ced611827565b73ffffffffffffffffffffffffffffffffffffffff1614610d43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3a90614adf565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0790614939565b60405180910390fd5b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060005b60048054905081101561105a578173ffffffffffffffffffffffffffffffffffffffff1660048281548110610f0f57610f0e614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561104a5760046001600480549050610f6a9190614b5d565b81548110610f7b57610f7a614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660048281548110610fba57610fb9614aff565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600480548061101457611013614b91565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590555b61105381612dde565b9050610ed7565b5050565b6000806000806000600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020604051806080016040529081600082015481526020016001820154815260200160028201548152602001600382015481525050905060006110e7876000612deb565b9050600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905081836000015161113c9190614bc0565b611147896001612deb565b8385602001516111579190614bc0565b955095509550955050509193509193565b60056020528060005260406000206000915090505481565b600260015414156111c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bd906149a5565b60405180910390fd5b60026001819055506000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156112d557838290600052602060002090600402016040518060800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201548152602001600282015481526020016003820154815250508152602001906001019061122f565b50505050905060008151905060008111611324576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131b90614c62565b60405180910390fd5b61132d33612cd4565b60005b8181101561138e5761137e83828151811061134e5761134d614aff565b5b60200260200101516000015184838151811061136d5761136c614aff565b5b602002602001015160200151613084565b61138781612dde565b9050611330565b50505060018081905550565b6113a26126b2565b73ffffffffffffffffffffffffffffffffffffffff166113c0611827565b73ffffffffffffffffffffffffffffffffffffffff1614611416576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161140d90614adf565b60405180910390fd5b61142060006138bb565b565b601260009054906101000a900460ff161561143c57600080fd5b60006114466126b2565b905060008173ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b815260040161148391906140c8565b602060405180830381865afa1580156114a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c491906147d2565b905060008273ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b815260040161150191906140c8565b602060405180830381865afa15801561151e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154291906147d2565b90507faa3e88aca472e90221daf7d3d601abafb62b120319089d7a2c2f63588da855298b8b8b8b8b8b8b8b8b8b8b6040516115879b9a9998979695949392919061483d565b60405180910390a15050505050505050505050565b600d6020528160005260406000206020528060005260406000206000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6115e73361275f565b600082829050905060005b818110156117105783838281811061160d5761160c614aff565b5b9050604002016000016020810190611625919061439d565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd333087878681811061165557611654614aff565b5b905060400201602001356040518463ffffffff1660e01b815260040161167d93929190614c82565b600060405180830381600087803b15801561169757600080fd5b505af11580156116ab573d6000803e3d6000fd5b505050506117008484838181106116c5576116c4614aff565b5b90506040020160000160208101906116dd919061439d565b8585848181106116f0576116ef614aff565b5b90506040020160200135336129ff565b61170981612dde565b90506115f2565b50505050565b6002600154141561175c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611753906149a5565b60405180910390fd5b60026001819055506000828290509050600081116117af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a690614d2b565b60405180910390fd5b60005b8181101561181a5761180a8484838181106117d0576117cf614aff565b5b90506040020160000160208101906117e8919061439d565b8585848181106117fb576117fa614aff565b5b90506040020160200135613084565b61181381612dde565b90506117b2565b5050600180819055505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6118586126b2565b73ffffffffffffffffffffffffffffffffffffffff16611876611827565b73ffffffffffffffffffffffffffffffffffffffff16146118cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c390614adf565b60405180910390fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600b6020528060005260406000206000915090508060000154908060010154908060020154908060030154905084565b60026001541415611986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197d906149a5565b60405180910390fd5b60026001819055506000828290509050600081116119d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d090614c62565b60405180910390fd5b6119e233612cd4565b60005b81811015611a4d57611a3d848483818110611a0357611a02614aff565b5b9050604002016000016020810190611a1b919061439d565b858584818110611a2e57611a2d614aff565b5b90506040020160200135613084565b611a4681612dde565b90506119e5565b5050600180819055505050565b600c6020528160005260406000208181548110611a7657600080fd5b9060005260206000209060040201600091509150508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154905084565b60036020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60075481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611bb25750611b83611827565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611bf1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be890614dbd565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff16600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611cbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cb590614939565b60405180910390fd5b60008251905060005b81811015611d4e5782600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000868481518110611d2457611d23614aff565b5b6020026020010151815260200190815260200160002081905550611d4781612dde565b9050611cc7565b5050505050565b611d5d6126b2565b73ffffffffffffffffffffffffffffffffffffffff16611d7b611827565b73ffffffffffffffffffffffffffffffffffffffff1614611dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc890614adf565b60405180910390fd5b8060118190555050565b60085481565b611de96126b2565b73ffffffffffffffffffffffffffffffffffffffff16611e07611827565b73ffffffffffffffffffffffffffffffffffffffff1614611e5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5490614adf565b60405180910390fd5b81600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506004829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b60115481565b611f946126b2565b73ffffffffffffffffffffffffffffffffffffffff16611fb2611827565b73ffffffffffffffffffffffffffffffffffffffff1614612008576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fff90614adf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206f90614e4f565b60405180910390fd5b612081816138bb565b50565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061211257506120e3611827565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612151576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161214890614dbd565b60405180910390fd5b60008383905090506000811161219c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219390614ebb565b60405180910390fd5b600082116121df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121d690614f4d565b60405180910390fd5b60006001601060008282546121f49190614bc0565b9250508190555060005b828110156123f6576000600d600088888581811061221f5761221e614aff565b5b9050604002016000016020810190612237919061439d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600088888581811061228657612285614aff565b5b90506040020160200135815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146123e5576064600e6000601054815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546123589190614bc0565b92505081905550600f60006010548152602001908152602001600020819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001836123e29190614bc0565b92505b506123ef81612dde565b90506121fe565b506000811161243a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161243190614fdf565b60405180910390fd5b6000600f6000601054815260200190815260200160002080549050905060005b818110156126a9576000600f60006010548152602001908152602001600020828154811061248b5761248a614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600e6000601054815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115612698576000606487612522919061502e565b85600e6000601054815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612580919061502e565b61258a919061505f565b905080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282546125de9190614bc0565b9250508190555080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008282546126379190614bc0565b925050819055506000600e6000601054815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b506126a281612dde565b905061245a565b50505050505050565b600033905090565b6000600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546127579190614bc0565b905092915050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905014156129fc576000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002015411156128885742600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018190555042600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030181905550612998565b6040518060800160405280600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001548152602001600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154815260200142815260200142815250600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050505b600a819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b8273ffffffffffffffffffffffffffffffffffffffff16600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612acc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac390614939565b60405180910390fd5b600060405180608001604052808573ffffffffffffffffffffffffffffffffffffffff16815260200184815260200142815260200142815250905081600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081908060018154018082558091505060019003906000526020600020906004020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015560408201518160020155606082015181600301555050600160086000828254612c799190614bc0565b925050819055508173ffffffffffffffffffffffffffffffffffffffff167fa5c6423d7b62a11b9a8a75349fbfc9865029364ea11b6ba86dabdaf8a406529d82604051612cc6919061512c565b60405180910390a250505050565b6000612cdf8261397f565b905042600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018190555080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000828254612d7a9190614bc0565b9250508190555080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000828254612dd39190614bc0565b925050819055505050565b6000600182019050919050565b600080600c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015612ef357838290600052602060002090600402016040518060800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820154815260200160038201548152505081526020019060010190612e4d565b5050505090506000808251905060005b81811015613077576000612f77858381518110612f2357612f22614aff565b5b602002602001015160400151600b60008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030154613dde565b90506000612fc1868481518110612f9157612f90614aff565b5b602002602001015160000151878581518110612fb057612faf614aff565b5b6020026020010151602001516126ba565b9050871561304b578082612fd5919061505f565b60648260075460648a8881518110612ff057612fef614aff565b5b602002602001015160400151426130079190614b5d565b613011919061505f565b61301b919061502e565b613025919061505f565b61302f919061502e565b6130399190614b5d565b856130449190614bc0565b9450613065565b8181613057919061505f565b856130629190614bc0565b94505b505061307081612dde565b9050612f03565b5081935050505092915050565b3373ffffffffffffffffffffffffffffffffffffffff16600d60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613162576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161315990615193565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd3033846040518463ffffffff1660e01b815260040161319f93929190614c82565b600060405180830381600087803b1580156131b957600080fd5b505af11580156131cd573d6000803e3d6000fd5b5050505060005b600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490508110156136395781600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106132705761326f614aff565b5b90600052602060002090600402016001015414801561333c57508273ffffffffffffffffffffffffffffffffffffffff16600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106132f2576132f1614aff565b5b906000526020600020906004020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15613629573373ffffffffffffffffffffffffffffffffffffffff167fe4303adcf299b488ab61917b621f0c76d6e78519f605a66909dcfe7f0167753b600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481106133ca576133c9614aff565b5b90600052602060002090600402016040516133e591906152a1565b60405180910390a2600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905061347b9190614b5d565b8154811061348c5761348b614aff565b5b9060005260206000209060040201600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106134eb576134ea614aff565b5b90600052602060002090600402016000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600182015481600101556002820154816002015560038201548160030155905050600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806135d0576135cf614b91565b5b6001900381819060005260206000209060040201600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182016000905560028201600090556003820160009055505090555b61363281612dde565b90506131d4565b506000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050141561380d5760005b600a8054905081101561380b573373ffffffffffffffffffffffffffffffffffffffff16600a82815481106136c0576136bf614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156137fb57600a6001600a8054905061371b9190614b5d565b8154811061372c5761372b614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600a828154811061376b5761376a614aff565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600a8054806137c5576137c4614b91565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590555b61380481612dde565b9050613688565b505b6000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600860008282546138b09190614b5d565b925050819055505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015613a8757838290600052602060002090600402016040518060800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820154815260200160028201548152602001600382015481525050815260200190600101906139e1565b5050505090506000808251905060005b81811015613dd2576000613b0b858381518110613ab757613ab6614aff565b5b602002602001015160400151600b60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030154613dde565b90506000811115613dc157613b5c858381518110613b2c57613b2b614aff565b5b602002602001015160000151868481518110613b4b57613b4a614aff565b5b6020026020010151602001516126ba565b81613b67919061505f565b84613b729190614bc0565b9350601154811415613cde57600754600754600c60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110613bd557613bd4614aff565b5b90600052602060002090600402016003015442613bf29190614b5d565b613bfc919061502e565b613c06919061505f565b600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613c5757613c56614aff565b5b906000526020600020906004020160030154613c739190614bc0565b600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613cc457613cc3614aff565b5b906000526020600020906004020160020181905550613dc0565b60075481613cec919061505f565b600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613d3d57613d3c614aff565b5b906000526020600020906004020160030154613d599190614bc0565b600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613daa57613da9614aff565b5b9060005260206000209060040201600201819055505b5b50613dcb81612dde565b9050613a97565b50819350505050919050565b600080429050600754601154613df4919061505f565b83613dff9190614bc0565b811115613e2457600754601154613e16919061505f565b83613e219190614bc0565b90505b6007548482613e339190614b5d565b613e3d919061502e565b91505092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613e8582613e5a565b9050919050565b613e9581613e7a565b8114613ea057600080fd5b50565b600081359050613eb281613e8c565b92915050565b6000819050919050565b613ecb81613eb8565b8114613ed657600080fd5b50565b600081359050613ee881613ec2565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112613f1357613f12613eee565b5b8235905067ffffffffffffffff811115613f3057613f2f613ef3565b5b602083019150836001820283011115613f4c57613f4b613ef8565b5b9250929050565b60008060008060008060008060c0898b031215613f7357613f72613e50565b5b6000613f818b828c01613ea3565b9850506020613f928b828c01613ea3565b9750506040613fa38b828c01613ea3565b9650506060613fb48b828c01613ed9565b955050608089013567ffffffffffffffff811115613fd557613fd4613e55565b5b613fe18b828c01613efd565b945094505060a089013567ffffffffffffffff81111561400457614003613e55565b5b6140108b828c01613efd565b92509250509295985092959890939650565b6000806040838503121561403957614038613e50565b5b600061404785828601613ea3565b925050602061405885828601613ed9565b9150509250929050565b61406b81613eb8565b82525050565b60006020820190506140866000830184614062565b92915050565b6000602082840312156140a2576140a1613e50565b5b60006140b084828501613ed9565b91505092915050565b6140c281613e7a565b82525050565b60006020820190506140dd60008301846140b9565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614131826140e8565b810181811067ffffffffffffffff821117156141505761414f6140f9565b5b80604052505050565b6000614163613e46565b905061416f8282614128565b919050565b600067ffffffffffffffff82111561418f5761418e6140f9565b5b614198826140e8565b9050602081019050919050565b82818337600083830152505050565b60006141c76141c284614174565b614159565b9050828152602081018484840111156141e3576141e26140e3565b5b6141ee8482856141a5565b509392505050565b600082601f83011261420b5761420a613eee565b5b813561421b8482602086016141b4565b91505092915050565b6000806000806080858703121561423e5761423d613e50565b5b600061424c87828801613ea3565b945050602061425d87828801613ea3565b935050604061426e87828801613ed9565b925050606085013567ffffffffffffffff81111561428f5761428e613e55565b5b61429b878288016141f6565b91505092959194509250565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6142dc816142a7565b82525050565b60006020820190506142f760008301846142d3565b92915050565b6000819050919050565b614310816142fd565b811461431b57600080fd5b50565b60008135905061432d81614307565b92915050565b6000806040838503121561434a57614349613e50565b5b60006143588582860161431e565b925050602061436985828601613ea3565b9150509250929050565b61437c816142fd565b82525050565b60006020820190506143976000830184614373565b92915050565b6000602082840312156143b3576143b2613e50565b5b60006143c184828501613ea3565b91505092915050565b60006080820190506143df6000830187614062565b6143ec6020830186614062565b6143f96040830185614062565b6144066060830184614062565b95945050505050565b60008083601f84011261442557614424613eee565b5b8235905067ffffffffffffffff81111561444257614441613ef3565b5b60208301915083604082028301111561445e5761445d613ef8565b5b9250929050565b6000806020838503121561447c5761447b613e50565b5b600083013567ffffffffffffffff81111561449a57614499613e55565b5b6144a68582860161440f565b92509250509250929050565b60006080820190506144c760008301876140b9565b6144d46020830186614062565b6144e16040830185614062565b6144ee6060830184614062565b95945050505050565b6000819050919050565b600061451c61451761451284613e5a565b6144f7565b613e5a565b9050919050565b600061452e82614501565b9050919050565b600061454082614523565b9050919050565b61455081614535565b82525050565b600060208201905061456b6000830184614547565b92915050565b600061457c82614523565b9050919050565b61458c81614571565b82525050565b60006020820190506145a76000830184614583565b92915050565b60006145b882613e7a565b9050919050565b6145c8816145ad565b81146145d357600080fd5b50565b6000813590506145e5816145bf565b92915050565b600067ffffffffffffffff821115614606576146056140f9565b5b602082029050602081019050919050565b600061462a614625846145eb565b614159565b9050808382526020820190506020840283018581111561464d5761464c613ef8565b5b835b8181101561467657806146628882613ed9565b84526020840193505060208101905061464f565b5050509392505050565b600082601f83011261469557614694613eee565b5b81356146a5848260208601614617565b91505092915050565b6000806000606084860312156146c7576146c6613e50565b5b60006146d5868287016145d6565b935050602084013567ffffffffffffffff8111156146f6576146f5613e55565b5b61470286828701614680565b925050604061471386828701613ed9565b9150509250925092565b6000806040838503121561473457614733613e50565b5b6000614742858286016145d6565b925050602061475385828601613ed9565b9150509250929050565b60008060006040848603121561477657614775613e50565b5b600084013567ffffffffffffffff81111561479457614793613e55565b5b6147a08682870161440f565b935093505060206147b386828701613ed9565b9150509250925092565b6000815190506147cc81613ec2565b92915050565b6000602082840312156147e8576147e7613e50565b5b60006147f6848285016147bd565b91505092915050565b600082825260208201905092915050565b600061481c83856147ff565b93506148298385846141a5565b614832836140e8565b840190509392505050565b600061012082019050614853600083018e6140b9565b614860602083018d6140b9565b61486d604083018c6140b9565b61487a606083018b614062565b818103608083015261488d81898b614810565b905081810360a08301526148a2818789614810565b90506148b160c08301866140b9565b6148be60e0830185614062565b6148cc610100830184614062565b9c9b505050505050505050505050565b600082825260208201905092915050565b7f4163655374616b696e673a20556e6b6f776e20436f6e74726163740000000000600082015250565b6000614923601b836148dc565b915061492e826148ed565b602082019050919050565b6000602082019050818103600083015261495281614916565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061498f601f836148dc565b915061499a82614959565b602082019050919050565b600060208201905081810360008301526149be81614982565b9050919050565b7f4163655374616b696e673a204e6f7468696e6720746f20636c61696d00000000600082015250565b60006149fb601c836148dc565b9150614a06826149c5565b602082019050919050565b60006020820190508181036000830152614a2a816149ee565b9050919050565b50565b6000614a416000836147ff565b9150614a4c82614a31565b600082019050919050565b6000606082019050614a6c60008301856140b9565b614a796020830184614062565b8181036040830152614a8a81614a34565b90509392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614ac96020836148dc565b9150614ad482614a93565b602082019050919050565b60006020820190508181036000830152614af881614abc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614b6882613eb8565b9150614b7383613eb8565b925082821015614b8657614b85614b2e565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000614bcb82613eb8565b9150614bd683613eb8565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614c0b57614c0a614b2e565b5b828201905092915050565b7f4163655374616b696e673a204e6f20546f6b656e7320666f756e640000000000600082015250565b6000614c4c601b836148dc565b9150614c5782614c16565b602082019050919050565b60006020820190508181036000830152614c7b81614c3f565b9050919050565b6000606082019050614c9760008301866140b9565b614ca460208301856140b9565b614cb16040830184614062565b949350505050565b7f4163655374616b696e673a204e6f20546f6b656e7320696e2063616c6c64617460008201527f6100000000000000000000000000000000000000000000000000000000000000602082015250565b6000614d156021836148dc565b9150614d2082614cb9565b604082019050919050565b60006020820190508181036000830152614d4481614d08565b9050919050565b7f4163655374616b696e673a204f6e6c79205245574152445f555044415445206f60008201527f72204f574e45522e000000000000000000000000000000000000000000000000602082015250565b6000614da76028836148dc565b9150614db282614d4b565b604082019050919050565b60006020820190508181036000830152614dd681614d9a565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614e396026836148dc565b9150614e4482614ddd565b604082019050919050565b60006020820190508181036000830152614e6881614e2c565b9050919050565b7f4163655374616b696e673a204e6f20546f6b656e730000000000000000000000600082015250565b6000614ea56015836148dc565b9150614eb082614e6f565b602082019050919050565b60006020820190508181036000830152614ed481614e98565b9050919050565b7f4163655374616b696e673a204e6f20426f6e757320746f20626520646973747260008201527f6962757465640000000000000000000000000000000000000000000000000000602082015250565b6000614f376026836148dc565b9150614f4282614edb565b604082019050919050565b60006020820190508181036000830152614f6681614f2a565b9050919050565b7f4163655374616b696e673a204e6f2073686172657320746f206469737472696260008201527f7574650000000000000000000000000000000000000000000000000000000000602082015250565b6000614fc96023836148dc565b9150614fd482614f6d565b604082019050919050565b60006020820190508181036000830152614ff881614fbc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061503982613eb8565b915061504483613eb8565b92508261505457615053614fff565b5b828204905092915050565b600061506a82613eb8565b915061507583613eb8565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156150ae576150ad614b2e565b5b828202905092915050565b6150c281613e7a565b82525050565b6150d181613eb8565b82525050565b6080820160008201516150ed60008501826150b9565b50602082015161510060208501826150c8565b50604082015161511360408501826150c8565b50606082015161512660608501826150c8565b50505050565b600060808201905061514160008301846150d7565b92915050565b7f4163655374616b696e673a204e6f7420796f757220746f6b656e2e2e2e000000600082015250565b600061517d601d836148dc565b915061518882615147565b602082019050919050565b600060208201905081810360008301526151ac81615170565b9050919050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006151f36151ee836151b3565b6151c0565b9050919050565b6000819050919050565b6000615217615212836151b3565b6151fa565b9050919050565b608082016000808301549050615233816151e0565b61524060008601826150b9565b506001830154905061525181615204565b61525e60208601826150c8565b506002830154905061526f81615204565b61527c60408601826150c8565b506003830154905061528d81615204565b61529a60608601826150c8565b5050505050565b60006080820190506152b6600083018461521e565b9291505056fea264697066735822122014cddb4bbe1d87685a22bd4ea40cc27813315a23ff054040b5b74e94b147c5a864736f6c634300080a0033000000000000000000000000917f7a44f93d76d70e254c96a2c7077375b369f10000000000000000000000000000000000000000000000000000000000278d00
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101ef5760003560e01c8063889dc3051161010f578063d1af0c7d116100a2578063dce9f7aa11610071578063dce9f7aa146105cf578063ed24f661146105eb578063f2fde38b14610609578063ffac2ae314610625576101ef565b8063d1af0c7d1461055b578063d5dbbce514610579578063d64f152a14610595578063da1af08f146105b1576101ef565b806394d8d7e9116100de57806394d8d7e9146104be578063a65ae961146104da578063ada0f98f1461050d578063bf91d8e41461053d576101ef565b8063889dc305146104355780638da5cb5b146104515780638fc67c261461046f5780639168ae721461048b576101ef565b8063385bfbb411610187578063715018a611610156578063715018a6146103c357806375ab9782146103cd5780637dad54c8146103e9578063801c523614610419576101ef565b8063385bfbb41461033a5780634258fcf614610356578063499d9d94146103895780635d85f3a1146103b9576101ef565b806318b85e33116101c357806318b85e33146102a05780631bbd8a41146102d0578063249cb3fa14610300578063372500ab14610330576101ef565b806223de29146101f45780630c4735b814610210578063145778d614610240578063150b7a0214610270575b600080fd5b61020e60048036038101906102099190613f53565b610641565b005b61022a60048036038101906102259190614022565b6107bb565b6040516102379190614071565b60405180910390f35b61025a6004803603810190610255919061408c565b61089c565b60405161026791906140c8565b60405180910390f35b61028a60048036038101906102859190614224565b6108db565b60405161029791906142e2565b60405180910390f35b6102ba60048036038101906102b5919061408c565b610903565b6040516102c791906140c8565b60405180910390f35b6102ea60048036038101906102e59190614022565b610942565b6040516102f79190614071565b60405180910390f35b61031a60048036038101906103159190614333565b610967565b6040516103279190614382565b60405180910390f35b6103386109fe565b005b610354600480360381019061034f919061439d565b610cc7565b005b610370600480360381019061036b919061439d565b61105e565b60405161038094939291906143ca565b60405180910390f35b6103a3600480360381019061039e919061439d565b611168565b6040516103b09190614071565b60405180910390f35b6103c1611180565b005b6103cb61139a565b005b6103e760048036038101906103e29190613f53565b611422565b005b61040360048036038101906103fe9190614022565b61159c565b60405161041091906140c8565b60405180910390f35b610433600480360381019061042e9190614465565b6115de565b005b61044f600480360381019061044a9190614465565b611716565b005b610459611827565b60405161046691906140c8565b60405180910390f35b6104896004803603810190610484919061439d565b611850565b005b6104a560048036038101906104a0919061439d565b611910565b6040516104b594939291906143ca565b60405180910390f35b6104d860048036038101906104d39190614465565b611940565b005b6104f460048036038101906104ef9190614022565b611a5a565b60405161050494939291906144b2565b60405180910390f35b6105276004803603810190610522919061439d565b611ac7565b6040516105349190614556565b60405180910390f35b610545611afa565b6040516105529190614071565b60405180910390f35b610563611b00565b6040516105709190614592565b60405180910390f35b610593600480360381019061058e91906146ae565b611b24565b005b6105af60048036038101906105aa919061408c565b611d55565b005b6105b9611ddb565b6040516105c69190614071565b60405180910390f35b6105e960048036038101906105e4919061471d565b611de1565b005b6105f3611f86565b6040516106009190614071565b60405180910390f35b610623600480360381019061061e919061439d565b611f8c565b005b61063f600480360381019061063a919061475d565b612084565b005b601260019054906101000a900460ff161561065b57600080fd5b60006106656126b2565b905060008173ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b81526004016106a291906140c8565b602060405180830381865afa1580156106bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e391906147d2565b905060008273ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b815260040161072091906140c8565b602060405180830381865afa15801561073d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076191906147d2565b90507f47e915878c47f3ec4d7ff646a2becb229f64fd2abe4d2b5e2bb4275b0cf50d4e8b8b8b8b8b8b8b8b8b8b8b6040516107a69b9a9998979695949392919061483d565b60405180910390a15050505050505050505050565b60008273ffffffffffffffffffffffffffffffffffffffff16600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461088a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088190614939565b60405180910390fd5b61089483836126ba565b905092915050565b600481815481106108ac57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006108e68461275f565b6108f13384866129ff565b63150b7a0260e01b9050949350505050565b600a818154811061091357600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6006602052816000526040600020602052806000526040600020600091509150505481565b60006002600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166109d4576000801b6109f6565b7fa2ef4600d742022d532d4747cb3547474667d6f13804902513b2ec01c848f4b45b905092915050565b60026001541415610a44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3b906149a5565b60405180910390fd5b6002600181905550610a5533612cd4565b6000600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015411610ada576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad190614a11565b60405180910390fd5b7f000000000000000000000000917f7a44f93d76d70e254c96a2c7077375b369f173ffffffffffffffffffffffffffffffffffffffff16639bd9bbc633600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546040518363ffffffff1660e01b8152600401610b77929190614a57565b600060405180830381600087803b158015610b9157600080fd5b505af1158015610ba5573d6000803e3d6000fd5b50505050600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001543373ffffffffffffffffffffffffffffffffffffffff167f106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f724160405160405180910390a36000600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018190555042600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003018190555060018081905550565b610ccf6126b2565b73ffffffffffffffffffffffffffffffffffffffff16610ced611827565b73ffffffffffffffffffffffffffffffffffffffff1614610d43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3a90614adf565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0790614939565b60405180910390fd5b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060005b60048054905081101561105a578173ffffffffffffffffffffffffffffffffffffffff1660048281548110610f0f57610f0e614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561104a5760046001600480549050610f6a9190614b5d565b81548110610f7b57610f7a614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660048281548110610fba57610fb9614aff565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600480548061101457611013614b91565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590555b61105381612dde565b9050610ed7565b5050565b6000806000806000600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020604051806080016040529081600082015481526020016001820154815260200160028201548152602001600382015481525050905060006110e7876000612deb565b9050600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905081836000015161113c9190614bc0565b611147896001612deb565b8385602001516111579190614bc0565b955095509550955050509193509193565b60056020528060005260406000206000915090505481565b600260015414156111c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bd906149a5565b60405180910390fd5b60026001819055506000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156112d557838290600052602060002090600402016040518060800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201548152602001600282015481526020016003820154815250508152602001906001019061122f565b50505050905060008151905060008111611324576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131b90614c62565b60405180910390fd5b61132d33612cd4565b60005b8181101561138e5761137e83828151811061134e5761134d614aff565b5b60200260200101516000015184838151811061136d5761136c614aff565b5b602002602001015160200151613084565b61138781612dde565b9050611330565b50505060018081905550565b6113a26126b2565b73ffffffffffffffffffffffffffffffffffffffff166113c0611827565b73ffffffffffffffffffffffffffffffffffffffff1614611416576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161140d90614adf565b60405180910390fd5b61142060006138bb565b565b601260009054906101000a900460ff161561143c57600080fd5b60006114466126b2565b905060008173ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b815260040161148391906140c8565b602060405180830381865afa1580156114a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c491906147d2565b905060008273ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b815260040161150191906140c8565b602060405180830381865afa15801561151e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154291906147d2565b90507faa3e88aca472e90221daf7d3d601abafb62b120319089d7a2c2f63588da855298b8b8b8b8b8b8b8b8b8b8b6040516115879b9a9998979695949392919061483d565b60405180910390a15050505050505050505050565b600d6020528160005260406000206020528060005260406000206000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6115e73361275f565b600082829050905060005b818110156117105783838281811061160d5761160c614aff565b5b9050604002016000016020810190611625919061439d565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd333087878681811061165557611654614aff565b5b905060400201602001356040518463ffffffff1660e01b815260040161167d93929190614c82565b600060405180830381600087803b15801561169757600080fd5b505af11580156116ab573d6000803e3d6000fd5b505050506117008484838181106116c5576116c4614aff565b5b90506040020160000160208101906116dd919061439d565b8585848181106116f0576116ef614aff565b5b90506040020160200135336129ff565b61170981612dde565b90506115f2565b50505050565b6002600154141561175c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611753906149a5565b60405180910390fd5b60026001819055506000828290509050600081116117af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a690614d2b565b60405180910390fd5b60005b8181101561181a5761180a8484838181106117d0576117cf614aff565b5b90506040020160000160208101906117e8919061439d565b8585848181106117fb576117fa614aff565b5b90506040020160200135613084565b61181381612dde565b90506117b2565b5050600180819055505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6118586126b2565b73ffffffffffffffffffffffffffffffffffffffff16611876611827565b73ffffffffffffffffffffffffffffffffffffffff16146118cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c390614adf565b60405180910390fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600b6020528060005260406000206000915090508060000154908060010154908060020154908060030154905084565b60026001541415611986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197d906149a5565b60405180910390fd5b60026001819055506000828290509050600081116119d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d090614c62565b60405180910390fd5b6119e233612cd4565b60005b81811015611a4d57611a3d848483818110611a0357611a02614aff565b5b9050604002016000016020810190611a1b919061439d565b858584818110611a2e57611a2d614aff565b5b90506040020160200135613084565b611a4681612dde565b90506119e5565b5050600180819055505050565b600c6020528160005260406000208181548110611a7657600080fd5b9060005260206000209060040201600091509150508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154905084565b60036020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60075481565b7f000000000000000000000000917f7a44f93d76d70e254c96a2c7077375b369f181565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611bb25750611b83611827565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611bf1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be890614dbd565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff16600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611cbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cb590614939565b60405180910390fd5b60008251905060005b81811015611d4e5782600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000868481518110611d2457611d23614aff565b5b6020026020010151815260200190815260200160002081905550611d4781612dde565b9050611cc7565b5050505050565b611d5d6126b2565b73ffffffffffffffffffffffffffffffffffffffff16611d7b611827565b73ffffffffffffffffffffffffffffffffffffffff1614611dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc890614adf565b60405180910390fd5b8060118190555050565b60085481565b611de96126b2565b73ffffffffffffffffffffffffffffffffffffffff16611e07611827565b73ffffffffffffffffffffffffffffffffffffffff1614611e5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5490614adf565b60405180910390fd5b81600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506004829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b60115481565b611f946126b2565b73ffffffffffffffffffffffffffffffffffffffff16611fb2611827565b73ffffffffffffffffffffffffffffffffffffffff1614612008576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fff90614adf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206f90614e4f565b60405180910390fd5b612081816138bb565b50565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061211257506120e3611827565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612151576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161214890614dbd565b60405180910390fd5b60008383905090506000811161219c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219390614ebb565b60405180910390fd5b600082116121df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121d690614f4d565b60405180910390fd5b60006001601060008282546121f49190614bc0565b9250508190555060005b828110156123f6576000600d600088888581811061221f5761221e614aff565b5b9050604002016000016020810190612237919061439d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600088888581811061228657612285614aff565b5b90506040020160200135815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146123e5576064600e6000601054815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546123589190614bc0565b92505081905550600f60006010548152602001908152602001600020819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001836123e29190614bc0565b92505b506123ef81612dde565b90506121fe565b506000811161243a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161243190614fdf565b60405180910390fd5b6000600f6000601054815260200190815260200160002080549050905060005b818110156126a9576000600f60006010548152602001908152602001600020828154811061248b5761248a614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600e6000601054815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115612698576000606487612522919061502e565b85600e6000601054815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612580919061502e565b61258a919061505f565b905080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282546125de9190614bc0565b9250508190555080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008282546126379190614bc0565b925050819055506000600e6000601054815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b506126a281612dde565b905061245a565b50505050505050565b600033905090565b6000600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546127579190614bc0565b905092915050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905014156129fc576000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002015411156128885742600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018190555042600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030181905550612998565b6040518060800160405280600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001548152602001600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154815260200142815260200142815250600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050505b600a819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b8273ffffffffffffffffffffffffffffffffffffffff16600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612acc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac390614939565b60405180910390fd5b600060405180608001604052808573ffffffffffffffffffffffffffffffffffffffff16815260200184815260200142815260200142815250905081600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081908060018154018082558091505060019003906000526020600020906004020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015560408201518160020155606082015181600301555050600160086000828254612c799190614bc0565b925050819055508173ffffffffffffffffffffffffffffffffffffffff167fa5c6423d7b62a11b9a8a75349fbfc9865029364ea11b6ba86dabdaf8a406529d82604051612cc6919061512c565b60405180910390a250505050565b6000612cdf8261397f565b905042600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018190555080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000828254612d7a9190614bc0565b9250508190555080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000828254612dd39190614bc0565b925050819055505050565b6000600182019050919050565b600080600c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015612ef357838290600052602060002090600402016040518060800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820154815260200160038201548152505081526020019060010190612e4d565b5050505090506000808251905060005b81811015613077576000612f77858381518110612f2357612f22614aff565b5b602002602001015160400151600b60008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030154613dde565b90506000612fc1868481518110612f9157612f90614aff565b5b602002602001015160000151878581518110612fb057612faf614aff565b5b6020026020010151602001516126ba565b9050871561304b578082612fd5919061505f565b60648260075460648a8881518110612ff057612fef614aff565b5b602002602001015160400151426130079190614b5d565b613011919061505f565b61301b919061502e565b613025919061505f565b61302f919061502e565b6130399190614b5d565b856130449190614bc0565b9450613065565b8181613057919061505f565b856130629190614bc0565b94505b505061307081612dde565b9050612f03565b5081935050505092915050565b3373ffffffffffffffffffffffffffffffffffffffff16600d60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613162576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161315990615193565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd3033846040518463ffffffff1660e01b815260040161319f93929190614c82565b600060405180830381600087803b1580156131b957600080fd5b505af11580156131cd573d6000803e3d6000fd5b5050505060005b600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490508110156136395781600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106132705761326f614aff565b5b90600052602060002090600402016001015414801561333c57508273ffffffffffffffffffffffffffffffffffffffff16600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106132f2576132f1614aff565b5b906000526020600020906004020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15613629573373ffffffffffffffffffffffffffffffffffffffff167fe4303adcf299b488ab61917b621f0c76d6e78519f605a66909dcfe7f0167753b600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481106133ca576133c9614aff565b5b90600052602060002090600402016040516133e591906152a1565b60405180910390a2600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905061347b9190614b5d565b8154811061348c5761348b614aff565b5b9060005260206000209060040201600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106134eb576134ea614aff565b5b90600052602060002090600402016000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600182015481600101556002820154816002015560038201548160030155905050600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806135d0576135cf614b91565b5b6001900381819060005260206000209060040201600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182016000905560028201600090556003820160009055505090555b61363281612dde565b90506131d4565b506000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050141561380d5760005b600a8054905081101561380b573373ffffffffffffffffffffffffffffffffffffffff16600a82815481106136c0576136bf614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156137fb57600a6001600a8054905061371b9190614b5d565b8154811061372c5761372b614aff565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600a828154811061376b5761376a614aff565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600a8054806137c5576137c4614b91565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590555b61380481612dde565b9050613688565b505b6000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600860008282546138b09190614b5d565b925050819055505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015613a8757838290600052602060002090600402016040518060800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820154815260200160028201548152602001600382015481525050815260200190600101906139e1565b5050505090506000808251905060005b81811015613dd2576000613b0b858381518110613ab757613ab6614aff565b5b602002602001015160400151600b60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030154613dde565b90506000811115613dc157613b5c858381518110613b2c57613b2b614aff565b5b602002602001015160000151868481518110613b4b57613b4a614aff565b5b6020026020010151602001516126ba565b81613b67919061505f565b84613b729190614bc0565b9350601154811415613cde57600754600754600c60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110613bd557613bd4614aff565b5b90600052602060002090600402016003015442613bf29190614b5d565b613bfc919061502e565b613c06919061505f565b600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613c5757613c56614aff565b5b906000526020600020906004020160030154613c739190614bc0565b600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613cc457613cc3614aff565b5b906000526020600020906004020160020181905550613dc0565b60075481613cec919061505f565b600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613d3d57613d3c614aff565b5b906000526020600020906004020160030154613d599190614bc0565b600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613daa57613da9614aff565b5b9060005260206000209060040201600201819055505b5b50613dcb81612dde565b9050613a97565b50819350505050919050565b600080429050600754601154613df4919061505f565b83613dff9190614bc0565b811115613e2457600754601154613e16919061505f565b83613e219190614bc0565b90505b6007548482613e339190614b5d565b613e3d919061502e565b91505092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613e8582613e5a565b9050919050565b613e9581613e7a565b8114613ea057600080fd5b50565b600081359050613eb281613e8c565b92915050565b6000819050919050565b613ecb81613eb8565b8114613ed657600080fd5b50565b600081359050613ee881613ec2565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112613f1357613f12613eee565b5b8235905067ffffffffffffffff811115613f3057613f2f613ef3565b5b602083019150836001820283011115613f4c57613f4b613ef8565b5b9250929050565b60008060008060008060008060c0898b031215613f7357613f72613e50565b5b6000613f818b828c01613ea3565b9850506020613f928b828c01613ea3565b9750506040613fa38b828c01613ea3565b9650506060613fb48b828c01613ed9565b955050608089013567ffffffffffffffff811115613fd557613fd4613e55565b5b613fe18b828c01613efd565b945094505060a089013567ffffffffffffffff81111561400457614003613e55565b5b6140108b828c01613efd565b92509250509295985092959890939650565b6000806040838503121561403957614038613e50565b5b600061404785828601613ea3565b925050602061405885828601613ed9565b9150509250929050565b61406b81613eb8565b82525050565b60006020820190506140866000830184614062565b92915050565b6000602082840312156140a2576140a1613e50565b5b60006140b084828501613ed9565b91505092915050565b6140c281613e7a565b82525050565b60006020820190506140dd60008301846140b9565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614131826140e8565b810181811067ffffffffffffffff821117156141505761414f6140f9565b5b80604052505050565b6000614163613e46565b905061416f8282614128565b919050565b600067ffffffffffffffff82111561418f5761418e6140f9565b5b614198826140e8565b9050602081019050919050565b82818337600083830152505050565b60006141c76141c284614174565b614159565b9050828152602081018484840111156141e3576141e26140e3565b5b6141ee8482856141a5565b509392505050565b600082601f83011261420b5761420a613eee565b5b813561421b8482602086016141b4565b91505092915050565b6000806000806080858703121561423e5761423d613e50565b5b600061424c87828801613ea3565b945050602061425d87828801613ea3565b935050604061426e87828801613ed9565b925050606085013567ffffffffffffffff81111561428f5761428e613e55565b5b61429b878288016141f6565b91505092959194509250565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6142dc816142a7565b82525050565b60006020820190506142f760008301846142d3565b92915050565b6000819050919050565b614310816142fd565b811461431b57600080fd5b50565b60008135905061432d81614307565b92915050565b6000806040838503121561434a57614349613e50565b5b60006143588582860161431e565b925050602061436985828601613ea3565b9150509250929050565b61437c816142fd565b82525050565b60006020820190506143976000830184614373565b92915050565b6000602082840312156143b3576143b2613e50565b5b60006143c184828501613ea3565b91505092915050565b60006080820190506143df6000830187614062565b6143ec6020830186614062565b6143f96040830185614062565b6144066060830184614062565b95945050505050565b60008083601f84011261442557614424613eee565b5b8235905067ffffffffffffffff81111561444257614441613ef3565b5b60208301915083604082028301111561445e5761445d613ef8565b5b9250929050565b6000806020838503121561447c5761447b613e50565b5b600083013567ffffffffffffffff81111561449a57614499613e55565b5b6144a68582860161440f565b92509250509250929050565b60006080820190506144c760008301876140b9565b6144d46020830186614062565b6144e16040830185614062565b6144ee6060830184614062565b95945050505050565b6000819050919050565b600061451c61451761451284613e5a565b6144f7565b613e5a565b9050919050565b600061452e82614501565b9050919050565b600061454082614523565b9050919050565b61455081614535565b82525050565b600060208201905061456b6000830184614547565b92915050565b600061457c82614523565b9050919050565b61458c81614571565b82525050565b60006020820190506145a76000830184614583565b92915050565b60006145b882613e7a565b9050919050565b6145c8816145ad565b81146145d357600080fd5b50565b6000813590506145e5816145bf565b92915050565b600067ffffffffffffffff821115614606576146056140f9565b5b602082029050602081019050919050565b600061462a614625846145eb565b614159565b9050808382526020820190506020840283018581111561464d5761464c613ef8565b5b835b8181101561467657806146628882613ed9565b84526020840193505060208101905061464f565b5050509392505050565b600082601f83011261469557614694613eee565b5b81356146a5848260208601614617565b91505092915050565b6000806000606084860312156146c7576146c6613e50565b5b60006146d5868287016145d6565b935050602084013567ffffffffffffffff8111156146f6576146f5613e55565b5b61470286828701614680565b925050604061471386828701613ed9565b9150509250925092565b6000806040838503121561473457614733613e50565b5b6000614742858286016145d6565b925050602061475385828601613ed9565b9150509250929050565b60008060006040848603121561477657614775613e50565b5b600084013567ffffffffffffffff81111561479457614793613e55565b5b6147a08682870161440f565b935093505060206147b386828701613ed9565b9150509250925092565b6000815190506147cc81613ec2565b92915050565b6000602082840312156147e8576147e7613e50565b5b60006147f6848285016147bd565b91505092915050565b600082825260208201905092915050565b600061481c83856147ff565b93506148298385846141a5565b614832836140e8565b840190509392505050565b600061012082019050614853600083018e6140b9565b614860602083018d6140b9565b61486d604083018c6140b9565b61487a606083018b614062565b818103608083015261488d81898b614810565b905081810360a08301526148a2818789614810565b90506148b160c08301866140b9565b6148be60e0830185614062565b6148cc610100830184614062565b9c9b505050505050505050505050565b600082825260208201905092915050565b7f4163655374616b696e673a20556e6b6f776e20436f6e74726163740000000000600082015250565b6000614923601b836148dc565b915061492e826148ed565b602082019050919050565b6000602082019050818103600083015261495281614916565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061498f601f836148dc565b915061499a82614959565b602082019050919050565b600060208201905081810360008301526149be81614982565b9050919050565b7f4163655374616b696e673a204e6f7468696e6720746f20636c61696d00000000600082015250565b60006149fb601c836148dc565b9150614a06826149c5565b602082019050919050565b60006020820190508181036000830152614a2a816149ee565b9050919050565b50565b6000614a416000836147ff565b9150614a4c82614a31565b600082019050919050565b6000606082019050614a6c60008301856140b9565b614a796020830184614062565b8181036040830152614a8a81614a34565b90509392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614ac96020836148dc565b9150614ad482614a93565b602082019050919050565b60006020820190508181036000830152614af881614abc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614b6882613eb8565b9150614b7383613eb8565b925082821015614b8657614b85614b2e565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000614bcb82613eb8565b9150614bd683613eb8565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614c0b57614c0a614b2e565b5b828201905092915050565b7f4163655374616b696e673a204e6f20546f6b656e7320666f756e640000000000600082015250565b6000614c4c601b836148dc565b9150614c5782614c16565b602082019050919050565b60006020820190508181036000830152614c7b81614c3f565b9050919050565b6000606082019050614c9760008301866140b9565b614ca460208301856140b9565b614cb16040830184614062565b949350505050565b7f4163655374616b696e673a204e6f20546f6b656e7320696e2063616c6c64617460008201527f6100000000000000000000000000000000000000000000000000000000000000602082015250565b6000614d156021836148dc565b9150614d2082614cb9565b604082019050919050565b60006020820190508181036000830152614d4481614d08565b9050919050565b7f4163655374616b696e673a204f6e6c79205245574152445f555044415445206f60008201527f72204f574e45522e000000000000000000000000000000000000000000000000602082015250565b6000614da76028836148dc565b9150614db282614d4b565b604082019050919050565b60006020820190508181036000830152614dd681614d9a565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614e396026836148dc565b9150614e4482614ddd565b604082019050919050565b60006020820190508181036000830152614e6881614e2c565b9050919050565b7f4163655374616b696e673a204e6f20546f6b656e730000000000000000000000600082015250565b6000614ea56015836148dc565b9150614eb082614e6f565b602082019050919050565b60006020820190508181036000830152614ed481614e98565b9050919050565b7f4163655374616b696e673a204e6f20426f6e757320746f20626520646973747260008201527f6962757465640000000000000000000000000000000000000000000000000000602082015250565b6000614f376026836148dc565b9150614f4282614edb565b604082019050919050565b60006020820190508181036000830152614f6681614f2a565b9050919050565b7f4163655374616b696e673a204e6f2073686172657320746f206469737472696260008201527f7574650000000000000000000000000000000000000000000000000000000000602082015250565b6000614fc96023836148dc565b9150614fd482614f6d565b604082019050919050565b60006020820190508181036000830152614ff881614fbc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061503982613eb8565b915061504483613eb8565b92508261505457615053614fff565b5b828204905092915050565b600061506a82613eb8565b915061507583613eb8565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156150ae576150ad614b2e565b5b828202905092915050565b6150c281613e7a565b82525050565b6150d181613eb8565b82525050565b6080820160008201516150ed60008501826150b9565b50602082015161510060208501826150c8565b50604082015161511360408501826150c8565b50606082015161512660608501826150c8565b50505050565b600060808201905061514160008301846150d7565b92915050565b7f4163655374616b696e673a204e6f7420796f757220746f6b656e2e2e2e000000600082015250565b600061517d601d836148dc565b915061518882615147565b602082019050919050565b600060208201905081810360008301526151ac81615170565b9050919050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006151f36151ee836151b3565b6151c0565b9050919050565b6000819050919050565b6000615217615212836151b3565b6151fa565b9050919050565b608082016000808301549050615233816151e0565b61524060008601826150b9565b506001830154905061525181615204565b61525e60208601826150c8565b506002830154905061526f81615204565b61527c60408601826150c8565b506003830154905061528d81615204565b61529a60608601826150c8565b5050505050565b60006080820190506152b6600083018461521e565b9291505056fea264697066735822122014cddb4bbe1d87685a22bd4ea40cc27813315a23ff054040b5b74e94b147c5a864736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000917f7a44f93d76d70e254c96a2c7077375b369f10000000000000000000000000000000000000000000000000000000000278d00
-----Decoded View---------------
Arg [0] : _rewardsToken (address): 0x917F7A44f93d76d70E254C96a2C7077375b369F1
Arg [1] : _rewardPeriodInSeconds (uint256): 2592000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000917f7a44f93d76d70e254c96a2c7077375b369f1
Arg [1] : 0000000000000000000000000000000000000000000000000000000000278d00
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.