Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 55 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create Pool | 16595715 | 729 days ago | IN | 0 ETH | 0.052554 | ||||
Create Pool | 16295956 | 771 days ago | IN | 0 ETH | 0.03528752 | ||||
Create Pool | 16151360 | 791 days ago | IN | 0 ETH | 0.03341765 | ||||
Create Pool | 16139376 | 793 days ago | IN | 0 ETH | 0.03177908 | ||||
Create Pool | 16124736 | 795 days ago | IN | 0 ETH | 0.02839582 | ||||
Create Pool | 16114524 | 796 days ago | IN | 0 ETH | 0.03099173 | ||||
Create Pool | 16109945 | 797 days ago | IN | 0 ETH | 0.02601258 | ||||
Create Pool | 16106362 | 798 days ago | IN | 0 ETH | 0.02657733 | ||||
Create Pool | 16099786 | 798 days ago | IN | 0 ETH | 0.0357729 | ||||
Create Pool | 16094738 | 799 days ago | IN | 0 ETH | 0.02785016 | ||||
Create Pool | 16081244 | 801 days ago | IN | 0 ETH | 0.02571458 | ||||
Create Pool | 16081155 | 801 days ago | IN | 0 ETH | 0.02497527 | ||||
Create Pool | 16071646 | 802 days ago | IN | 0 ETH | 0.02512274 | ||||
Create Pool | 16065134 | 803 days ago | IN | 0 ETH | 0.0243363 | ||||
Create Pool | 16023240 | 809 days ago | IN | 0 ETH | 0.02463419 | ||||
Create Pool | 15920703 | 823 days ago | IN | 0 ETH | 0.04760598 | ||||
Create Pool | 15899759 | 826 days ago | IN | 0 ETH | 0.03068173 | ||||
Create Pool | 15899740 | 826 days ago | IN | 0 ETH | 0.03054403 | ||||
Create Pool | 15899697 | 826 days ago | IN | 0 ETH | 0.03009832 | ||||
Create Pool | 15899658 | 826 days ago | IN | 0 ETH | 0.02705927 | ||||
Create Pool | 15899611 | 826 days ago | IN | 0 ETH | 0.02927446 | ||||
Create Pool | 15827835 | 836 days ago | IN | 0 ETH | 0.03780661 | ||||
Create Pool | 15741224 | 849 days ago | IN | 0 ETH | 0.0606435 | ||||
Create Pool | 15418160 | 896 days ago | IN | 0 ETH | 0.01697784 | ||||
Create Pool | 15373588 | 903 days ago | IN | 0 ETH | 0.03905054 |
Latest 25 internal transactions (View All)
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
AntePoolFactory
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only // ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━ // ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━ // ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓ // ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃ // ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫ // ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ pragma solidity ^0.7.0; import "./AntePool.sol"; import "./interfaces/IAnteTest.sol"; import "./interfaces/IAntePoolFactory.sol"; /// @title Ante V0.5 Ante Pool Factory smart contract /// @notice Contract that creates an AntePool wrapper for an AnteTest contract AntePoolFactory is IAntePoolFactory { /// @inheritdoc IAntePoolFactory mapping(address => address) public override poolMap; /// @inheritdoc IAntePoolFactory address[] public override allPools; /// @inheritdoc IAntePoolFactory function createPool(address testAddr) external override returns (address testPool) { // Checks that a non-zero AnteTest address is passed in and that // an AntePool has not already been created for that AnteTest require(testAddr != address(0), "ANTE: Test address is 0"); require(poolMap[testAddr] == address(0), "ANTE: Pool already created"); IAnteTest anteTest = IAnteTest(testAddr); bytes memory bytecode = type(AntePool).creationCode; bytes32 salt = keccak256(abi.encodePacked(testAddr)); assembly { testPool := create2(0, add(bytecode, 0x20), mload(bytecode), salt) } poolMap[testAddr] = testPool; allPools.push(testPool); AntePool(testPool).initialize(anteTest); emit AntePoolCreated(testAddr, testPool); } }
// SPDX-License-Identifier: GPL-3.0-only // ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━ // ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━ // ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓ // ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃ // ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫ // ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ pragma solidity ^0.7.0; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "./interfaces/IAnteTest.sol"; import "./libraries/IterableSet.sol"; import "./libraries/FullMath.sol"; import "./interfaces/IAntePool.sol"; /// @title Ante V0.5 Ante Pool smart contract /// @notice Deploys an Ante Pool and connects with the Ante Test, manages pools and interactions with users contract AntePool is IAntePool { using SafeMath for uint256; using FullMath for uint256; using Address for address; using IterableAddressSetUtils for IterableAddressSetUtils.IterableAddressSet; /// @notice Info related to a single user struct UserInfo { // How much ETH this user deposited. uint256 startAmount; // How much decay this side of the pool accrued between (0, this user's // entry block), stored as a multiplier expressed as an 18-decimal // mantissa. For example, if this side of the pool accrued a decay of // 20% during this time period, we'd store 1.2e18 (staking side) or // 0.8e18 (challenger side). uint256 startDecayMultiplier; } /// @notice Info related to one side of the pool struct PoolSideInfo { mapping(address => UserInfo) userInfo; // Number of users on this side of the pool. uint256 numUsers; // Amount staked across all users on this side of the pool, as of // `lastUpdateBlock`.` uint256 totalAmount; // How much decay this side of the pool accrued between (0, // lastUpdateBlock), stored as a multiplier expressed as an 18-decimal // mantissa. For example, if this side of the pool accrued a decay of // 20% during this time period, we'd store 1.2e18 (staking side) or // 0.8e18 (challenger side). uint256 decayMultiplier; } /// @notice Info related to eligible challengers struct ChallengerEligibilityInfo { // Used when test fails to determine which challengers should receive payout // i.e., those which haven't staked within 12 blocks prior to test failure mapping(address => uint256) lastStakedBlock; uint256 eligibleAmount; } /// @notice Info related to stakers who are currently withdrawing struct StakerWithdrawInfo { mapping(address => UserUnstakeInfo) userUnstakeInfo; uint256 totalAmount; } /// @notice Info related to a single withdrawing user struct UserUnstakeInfo { uint256 lastUnstakeTimestamp; uint256 amount; } /// @inheritdoc IAntePool IAnteTest public override anteTest; /// @inheritdoc IAntePool address public override factory; /// @inheritdoc IAntePool /// @dev pendingFailure set to true until pool is initialized to avoid /// people staking in uninitialized pools bool public override pendingFailure = true; /// @inheritdoc IAntePool uint256 public override numTimesVerified; /// @dev Percent of staked amount alloted for verifier bounty uint256 public constant VERIFIER_BOUNTY = 5; /// @inheritdoc IAntePool uint256 public override failedBlock; /// @inheritdoc IAntePool uint256 public override lastVerifiedBlock; /// @inheritdoc IAntePool address public override verifier; /// @inheritdoc IAntePool uint256 public override numPaidOut; /// @inheritdoc IAntePool uint256 public override totalPaidOut; /// @dev pool can only be initialized once bool internal _initialized = false; /// @dev Bounty amount, set when test fails uint256 internal _bounty; /// @dev Total staked value, after bounty is removed uint256 internal _remainingStake; /// @dev Amount of decay to charge each challengers ETH per block /// 100 gwei decay per block per ETH is ~20-25% decay per year uint256 public constant DECAY_RATE_PER_BLOCK = 100 gwei; /// @dev Number of blocks a challenger must be staking before they are /// eligible for paytout on test failure uint8 public constant CHALLENGER_BLOCK_DELAY = 12; /// @dev Minimum challenger stake is 0.01 ETH uint256 public constant MIN_CHALLENGER_STAKE = 1e16; /// @dev Time after initiating withdraw before staker can finally withdraw capital, /// starts when staker initiates the unstake action uint256 public constant UNSTAKE_DELAY = 24 hours; /// @dev convenience constant for 1 ether worth of wei uint256 private constant ONE = 1e18; /// @inheritdoc IAntePool PoolSideInfo public override stakingInfo; /// @inheritdoc IAntePool PoolSideInfo public override challengerInfo; /// @inheritdoc IAntePool ChallengerEligibilityInfo public override eligibilityInfo; /// @dev All addresses currently challenging the Ante Test IterableAddressSetUtils.IterableAddressSet private challengers; /// @inheritdoc IAntePool StakerWithdrawInfo public override withdrawInfo; /// @inheritdoc IAntePool uint256 public override lastUpdateBlock; /// @notice Modifier function to make sure test hasn't failed yet modifier testNotFailed() { _testNotFailed(); _; } modifier notInitialized() { require(!_initialized, "ANTE: Pool already initialized"); _; } /// @dev Ante Pools are deployed by Ante Pool Factory, and we store /// the address of the factory here constructor() { factory = msg.sender; stakingInfo.decayMultiplier = ONE; challengerInfo.decayMultiplier = ONE; lastUpdateBlock = block.number; } /// @inheritdoc IAntePool function initialize(IAnteTest _anteTest) external override notInitialized { require(msg.sender == factory, "ANTE: only factory can initialize AntePool"); require(address(_anteTest).isContract(), "ANTE: AnteTest must be a smart contract"); // Check that anteTest has checkTestPasses function and that it currently passes // place check here to minimize reentrancy risk - most external function calls are locked // while pendingFailure is true require(_anteTest.checkTestPasses(), "ANTE: AnteTest does not implement checkTestPasses or test fails"); _initialized = true; pendingFailure = false; anteTest = _anteTest; } /***************************************************** * ================ USER INTERFACE ================= * *****************************************************/ /// @inheritdoc IAntePool /// @dev Stake `msg.value` on the side given by `isChallenger` function stake(bool isChallenger) external payable override testNotFailed { uint256 amount = msg.value; require(amount > 0, "ANTE: Cannot stake zero"); updateDecay(); PoolSideInfo storage side; if (isChallenger) { require(amount >= MIN_CHALLENGER_STAKE, "ANTE: Challenger must stake more than 0.01 ETH"); side = challengerInfo; // Record challenger info for future use // Challengers are not eligible for rewards if challenging within 12 block window of test failure challengers.insert(msg.sender); eligibilityInfo.lastStakedBlock[msg.sender] = block.number; } else { side = stakingInfo; } UserInfo storage user = side.userInfo[msg.sender]; // Calculate how much the user already has staked, including the // effects of any previously accrued decay. // prevAmount = startAmount * decayMultipiler / startDecayMultiplier // newAmount = amount + prevAmount if (user.startAmount > 0) { user.startAmount = amount.add(_storedBalance(user, side)); } else { user.startAmount = amount; side.numUsers = side.numUsers.add(1); } side.totalAmount = side.totalAmount.add(amount); // Reset the startDecayMultiplier for this user, since we've updated // the startAmount to include any already-accrued decay. user.startDecayMultiplier = side.decayMultiplier; emit Stake(msg.sender, amount, isChallenger); } /// @inheritdoc IAntePool /// @dev Unstake `amount` on the side given by `isChallenger`. function unstake(uint256 amount, bool isChallenger) external override testNotFailed { require(amount > 0, "ANTE: Cannot unstake 0."); updateDecay(); PoolSideInfo storage side = isChallenger ? challengerInfo : stakingInfo; UserInfo storage user = side.userInfo[msg.sender]; _unstake(amount, isChallenger, side, user); } /// @inheritdoc IAntePool function unstakeAll(bool isChallenger) external override testNotFailed { updateDecay(); PoolSideInfo storage side = isChallenger ? challengerInfo : stakingInfo; UserInfo storage user = side.userInfo[msg.sender]; uint256 amount = _storedBalance(user, side); require(amount > 0, "ANTE: Nothing to unstake"); _unstake(amount, isChallenger, side, user); } /// @inheritdoc IAntePool function withdrawStake() external override testNotFailed { UserUnstakeInfo storage unstakeUser = withdrawInfo.userUnstakeInfo[msg.sender]; require( unstakeUser.lastUnstakeTimestamp < block.timestamp - UNSTAKE_DELAY, "ANTE: must wait 24 hours to withdraw stake" ); require(unstakeUser.amount > 0, "ANTE: Nothing to withdraw"); uint256 amount = unstakeUser.amount; withdrawInfo.totalAmount = withdrawInfo.totalAmount.sub(amount); unstakeUser.amount = 0; _safeTransfer(msg.sender, amount); emit WithdrawStake(msg.sender, amount); } /// @inheritdoc IAntePool function cancelPendingWithdraw() external override testNotFailed { UserUnstakeInfo storage unstakeUser = withdrawInfo.userUnstakeInfo[msg.sender]; require(unstakeUser.amount > 0, "ANTE: No pending withdraw balance"); uint256 amount = unstakeUser.amount; unstakeUser.amount = 0; updateDecay(); UserInfo storage user = stakingInfo.userInfo[msg.sender]; if (user.startAmount > 0) { user.startAmount = amount.add(_storedBalance(user, stakingInfo)); } else { user.startAmount = amount; stakingInfo.numUsers = stakingInfo.numUsers.add(1); } stakingInfo.totalAmount = stakingInfo.totalAmount.add(amount); user.startDecayMultiplier = stakingInfo.decayMultiplier; withdrawInfo.totalAmount = withdrawInfo.totalAmount.sub(amount); emit CancelWithdraw(msg.sender, amount); } /// @inheritdoc IAntePool function checkTest() external override testNotFailed { require(challengers.exists(msg.sender), "ANTE: Only challengers can checkTest"); require( block.number.sub(eligibilityInfo.lastStakedBlock[msg.sender]) > CHALLENGER_BLOCK_DELAY, "ANTE: must wait 12 blocks after challenging to call checkTest" ); numTimesVerified = numTimesVerified.add(1); lastVerifiedBlock = block.number; emit TestChecked(msg.sender); if (!_checkTestNoRevert()) { updateDecay(); verifier = msg.sender; failedBlock = block.number; pendingFailure = true; _calculateChallengerEligibility(); _bounty = getVerifierBounty(); uint256 totalStake = stakingInfo.totalAmount.add(withdrawInfo.totalAmount); _remainingStake = totalStake.sub(_bounty); emit FailureOccurred(msg.sender); } } /// @inheritdoc IAntePool function claim() external override { require(pendingFailure, "ANTE: Test has not failed"); UserInfo storage user = challengerInfo.userInfo[msg.sender]; require(user.startAmount > 0, "ANTE: No Challenger Staking balance"); uint256 amount = _calculateChallengerPayout(user, msg.sender); // Zero out the user so they can't claim again. user.startAmount = 0; numPaidOut = numPaidOut.add(1); totalPaidOut = totalPaidOut.add(amount); _safeTransfer(msg.sender, amount); emit ClaimPaid(msg.sender, amount); } /// @inheritdoc IAntePool function updateDecay() public override { (uint256 decayMultiplierThisUpdate, uint256 decayThisUpdate) = _computeDecay(); lastUpdateBlock = block.number; if (decayThisUpdate == 0) return; uint256 totalStaked = stakingInfo.totalAmount; uint256 totalChallengerStaked = challengerInfo.totalAmount; // update totoal accrued decay amounts for challengers // decayMultiplier for challengers = decayMultiplier for challengers * decayMultiplierThisUpdate // totalChallengerStaked = totalChallengerStaked - decayThisUpdate challengerInfo.decayMultiplier = challengerInfo.decayMultiplier.mulDiv(decayMultiplierThisUpdate, ONE); challengerInfo.totalAmount = totalChallengerStaked.sub(decayThisUpdate); // Update the new accrued decay amounts for stakers. // totalStaked_new = totalStaked_old + decayThisUpdate // decayMultipilerThisUpdate = totalStaked_new / totalStaked_old // decayMultiplier_staker = decayMultiplier_staker * decayMultiplierThisUpdate uint256 totalStakedNew = totalStaked.add(decayThisUpdate); stakingInfo.decayMultiplier = stakingInfo.decayMultiplier.mulDiv(totalStakedNew, totalStaked); stakingInfo.totalAmount = totalStakedNew; } /***************************************************** * ================ VIEW FUNCTIONS ================= * *****************************************************/ /// @inheritdoc IAntePool function getTotalChallengerStaked() external view override returns (uint256) { return challengerInfo.totalAmount; } /// @inheritdoc IAntePool function getTotalStaked() external view override returns (uint256) { return stakingInfo.totalAmount; } /// @inheritdoc IAntePool function getTotalPendingWithdraw() external view override returns (uint256) { return withdrawInfo.totalAmount; } /// @inheritdoc IAntePool function getTotalChallengerEligibleBalance() external view override returns (uint256) { return eligibilityInfo.eligibleAmount; } /// @inheritdoc IAntePool function getChallengerPayout(address challenger) external view override returns (uint256) { UserInfo storage user = challengerInfo.userInfo[challenger]; require(user.startAmount > 0, "ANTE: No Challenger Staking balance"); // If called before test failure returns an estimate if (pendingFailure) { return _calculateChallengerPayout(user, challenger); } else { uint256 amount = _storedBalance(user, challengerInfo); uint256 bounty = getVerifierBounty(); uint256 totalStake = stakingInfo.totalAmount.add(withdrawInfo.totalAmount); return amount.add(amount.mulDiv(totalStake.sub(bounty), challengerInfo.totalAmount)); } } /// @inheritdoc IAntePool function getStoredBalance(address _user, bool isChallenger) external view override returns (uint256) { (uint256 decayMultiplierThisUpdate, uint256 decayThisUpdate) = _computeDecay(); UserInfo storage user = isChallenger ? challengerInfo.userInfo[_user] : stakingInfo.userInfo[_user]; if (user.startAmount == 0) return 0; require(user.startDecayMultiplier > 0, "ANTE: Invalid startDecayMultiplier"); uint256 decayMultiplier; if (isChallenger) { decayMultiplier = challengerInfo.decayMultiplier.mul(decayMultiplierThisUpdate).div(1e18); } else { uint256 totalStaked = stakingInfo.totalAmount; uint256 totalStakedNew = totalStaked.add(decayThisUpdate); decayMultiplier = stakingInfo.decayMultiplier.mul(totalStakedNew).div(totalStaked); } return user.startAmount.mulDiv(decayMultiplier, user.startDecayMultiplier); } /// @inheritdoc IAntePool function getPendingWithdrawAmount(address _user) external view override returns (uint256) { return withdrawInfo.userUnstakeInfo[_user].amount; } /// @inheritdoc IAntePool function getPendingWithdrawAllowedTime(address _user) external view override returns (uint256) { UserUnstakeInfo storage user = withdrawInfo.userUnstakeInfo[_user]; require(user.amount > 0, "ANTE: nothing to withdraw"); return user.lastUnstakeTimestamp.add(UNSTAKE_DELAY); } /// @inheritdoc IAntePool function getCheckTestAllowedBlock(address _user) external view override returns (uint256) { return eligibilityInfo.lastStakedBlock[_user].add(CHALLENGER_BLOCK_DELAY); } /// @inheritdoc IAntePool function getUserStartAmount(address _user, bool isChallenger) external view override returns (uint256) { return isChallenger ? challengerInfo.userInfo[_user].startAmount : stakingInfo.userInfo[_user].startAmount; } /// @inheritdoc IAntePool function getVerifierBounty() public view override returns (uint256) { uint256 totalStake = stakingInfo.totalAmount.add(withdrawInfo.totalAmount); return totalStake.mul(VERIFIER_BOUNTY).div(100); } /***************************************************** * =============== INTERNAL HELPERS ================ * *****************************************************/ /// @notice Internal function activating the unstaking action for staker or challengers /// @param amount Amount to be removed in wei /// @param isChallenger True if user is a challenger /// @param side Corresponding staker or challenger pool info /// @param user Info related to the user /// @dev If the user is a challenger the function the amount can be withdrawn /// immediately, if the user is a staker, the amount is moved to the withdraw /// info and then the 24 hour waiting period starts function _unstake( uint256 amount, bool isChallenger, PoolSideInfo storage side, UserInfo storage user ) internal { // Calculate how much the user has available to unstake, including the // effects of any previously accrued decay. // prevAmount = startAmount * decayMultiplier / startDecayMultiplier uint256 prevAmount = _storedBalance(user, side); if (prevAmount == amount) { user.startAmount = 0; user.startDecayMultiplier = 0; side.numUsers = side.numUsers.sub(1); // Remove from set of existing challengers if (isChallenger) challengers.remove(msg.sender); } else { require(amount <= prevAmount, "ANTE: Withdraw request exceeds balance."); user.startAmount = prevAmount.sub(amount); // Reset the startDecayMultiplier for this user, since we've updated // the startAmount to include any already-accrued decay. user.startDecayMultiplier = side.decayMultiplier; } side.totalAmount = side.totalAmount.sub(amount); if (isChallenger) _safeTransfer(msg.sender, amount); else { // Just initiate the withdraw if staker UserUnstakeInfo storage unstakeUser = withdrawInfo.userUnstakeInfo[msg.sender]; unstakeUser.lastUnstakeTimestamp = block.timestamp; unstakeUser.amount = unstakeUser.amount.add(amount); withdrawInfo.totalAmount = withdrawInfo.totalAmount.add(amount); } emit Unstake(msg.sender, amount, isChallenger); } /// @notice Computes the decay differences for staker and challenger pools /// @dev Function shared by getStoredBalance view function and internal /// decay computation /// @return decayMultiplierThisUpdate multiplier factor for this decay change /// @return decayThisUpdate amount of challenger value that's decayed in wei function _computeDecay() internal view returns (uint256 decayMultiplierThisUpdate, uint256 decayThisUpdate) { decayThisUpdate = 0; decayMultiplierThisUpdate = ONE; if (block.number <= lastUpdateBlock) { return (decayMultiplierThisUpdate, decayThisUpdate); } // Stop charging decay if the test already failed. if (pendingFailure) { return (decayMultiplierThisUpdate, decayThisUpdate); } // If we have no stakers or challengers, don't charge any decay. uint256 totalStaked = stakingInfo.totalAmount; uint256 totalChallengerStaked = challengerInfo.totalAmount; if (totalStaked == 0 || totalChallengerStaked == 0) { return (decayMultiplierThisUpdate, decayThisUpdate); } uint256 numBlocks = block.number.sub(lastUpdateBlock); // The rest of the function updates the new accrued decay amounts // decayRateThisUpdate = DECAY_RATE_PER_BLOCK * numBlocks // decayMultiplierThisUpdate = 1 - decayRateThisUpdate // decayThisUpdate = totalChallengerStaked * decayRateThisUpdate uint256 decayRateThisUpdate = DECAY_RATE_PER_BLOCK.mul(numBlocks); // Failsafe to avoid underflow when calculating decayMultiplierThisUpdate if (decayRateThisUpdate >= ONE) { decayMultiplierThisUpdate = 0; decayThisUpdate = totalChallengerStaked; } else { decayMultiplierThisUpdate = ONE.sub(decayRateThisUpdate); decayThisUpdate = totalChallengerStaked.mulDiv(decayRateThisUpdate, ONE); } } /// @notice Calculates total amount of challenger capital eligible for payout. /// @dev Any challenger which stakes within 12 blocks prior to test failure /// will not get a payout but will be able to withdraw their capital /// (minus decay) function _calculateChallengerEligibility() internal { uint256 cutoffBlock = failedBlock.sub(CHALLENGER_BLOCK_DELAY); for (uint256 i = 0; i < challengers.addresses.length; i++) { address challenger = challengers.addresses[i]; if (eligibilityInfo.lastStakedBlock[challenger] < cutoffBlock) { eligibilityInfo.eligibleAmount = eligibilityInfo.eligibleAmount.add( _storedBalance(challengerInfo.userInfo[challenger], challengerInfo) ); } } } /// @notice Checks the connected Ante Test, also returns false if checkTestPasses reverts /// @return passes bool if the Ante Test passed function _checkTestNoRevert() internal returns (bool) { try anteTest.checkTestPasses() returns (bool passes) { return passes; } catch { return false; } } /// @notice Calculates individual challenger payout /// @param user UserInfo for specified challenger /// @param challenger Address of challenger /// @dev This is only called after a test is failed, so it's calculated payouts /// are no longer estimates /// @return Payout amount for challenger in wei function _calculateChallengerPayout(UserInfo storage user, address challenger) internal view returns (uint256) { // Calculate this user's challenging balance. uint256 amount = _storedBalance(user, challengerInfo); // Calculate how much of the staking pool this user gets, and add that // to the user's challenging balance. if (eligibilityInfo.lastStakedBlock[challenger] < failedBlock.sub(CHALLENGER_BLOCK_DELAY)) { amount = amount.add(amount.mulDiv(_remainingStake, eligibilityInfo.eligibleAmount)); } return challenger == verifier ? amount.add(_bounty) : amount; } /// @notice Get the stored balance held by user, including accrued decay /// @param user UserInfo of specified user /// @param side PoolSideInfo of where the user is located, either staker or challenger side /// @dev This includes accrued decay up to `lastUpdateBlock` /// @return Balance of the user in wei function _storedBalance(UserInfo storage user, PoolSideInfo storage side) internal view returns (uint256) { if (user.startAmount == 0) return 0; require(user.startDecayMultiplier > 0, "ANTE: Invalid startDecayMultiplier"); return user.startAmount.mulDiv(side.decayMultiplier, user.startDecayMultiplier); } /// @notice Transfer function for moving funds /// @param to Address to transfer funds to /// @param amount Amount to be transferred in wei /// @dev Safe transfer function, just in case a rounding error causes the /// pool to not have enough ETH function _safeTransfer(address payable to, uint256 amount) internal { to.transfer(_min(amount, address(this).balance)); } /// @notice Returns the minimum of 2 parameters /// @param a Value A /// @param b Value B /// @return Lower of a or b function _min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /// @notice Checks if the test has not failed yet function _testNotFailed() internal { require(!pendingFailure, "ANTE: Test already failed."); } }
// SPDX-License-Identifier: GPL-3.0-only // ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━ // ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━ // ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓ // ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃ // ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫ // ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ pragma solidity ^0.7.0; /// @title The interface for the Ante V0.5 Ante Test /// @notice The Ante V0.5 Ante Test wraps test logic for verifying fundamental invariants of a protocol interface IAnteTest { /// @notice Returns the author of the Ante Test /// @dev This overrides the auto-generated getter for testAuthor as a public var /// @return The address of the test author function testAuthor() external view returns (address); /// @notice Returns the name of the protocol the Ante Test is testing /// @dev This overrides the auto-generated getter for protocolName as a public var /// @return The name of the protocol in string format function protocolName() external view returns (string memory); /// @notice Returns a single address in the testedContracts array /// @dev This overrides the auto-generated getter for testedContracts [] as a public var /// @param i The array index of the address to return /// @return The address of the i-th element in the list of tested contracts function testedContracts(uint256 i) external view returns (address); /// @notice Returns the name of the Ante Test /// @dev This overrides the auto-generated getter for testName as a public var /// @return The name of the Ante Test in string format function testName() external view returns (string memory); /// @notice Function containing test logic to inspect the protocol invariant /// @dev This should usually return True /// @return A single bool indicating if the Ante Test passes/fails function checkTestPasses() external returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only // ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━ // ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━ // ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓ // ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃ // ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫ // ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ pragma solidity ^0.7.0; /// @title The interface for the Ante V0.5 Ante Pool Factory /// @notice The Ante V0.5 Ante Pool Factory programmatically generates an AntePool for a given AnteTest interface IAntePoolFactory { /// @notice Emitted when an AntePool is created from an AnteTest /// @param testAddr The address of the AnteTest used to create the AntePool /// @param testPool The address of the AntePool created by the factory event AntePoolCreated(address indexed testAddr, address testPool); /// @notice Creates an AntePool for an AnteTest and returns the AntePool address /// @param testAddr The address of the AnteTest to create an AntePool for /// @return testPool - The address of the generated AntePool function createPool(address testAddr) external returns (address testPool); /// @notice Returns a single address in the allPools array /// @param i The array index of the address to return /// @return The address of the i-th AntePool created by this factory function allPools(uint256 i) external view returns (address); /// @notice Returns the address of the AntePool corresponding to a given AnteTest /// @param testAddr address of the AnteTest to look up /// @return The address of the corresponding AntePool function poolMap(address testAddr) external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━ // ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━ // ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓ // ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃ // ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫ // ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ pragma solidity ^0.7.0; /// @notice Key sets for addresses with enumeration and delete. Uses mappings for random /// and existence checks and dynamic arrays for enumeration. Key uniqueness is enforced. /// @dev IterableAddressSets are unordered. Delete operations reorder keys. All operations have a /// fixed gas cost at any scale, O(1). /// Code inspired by https://github.com/rob-Hitchens/SetTypes/blob/master/contracts/AddressSet.sol /// and updated to solidity 0.7.x library IterableAddressSetUtils { /// @dev struct stores array of addresses and mapping of addresses to indices to allow O(1) CRUD operations struct IterableAddressSet { mapping(address => uint256) indices; address[] addresses; } /// @notice insert a key. /// @dev duplicate keys are not permitted but fails silently to avoid wasting gas on exist + insert calls /// @param self storage pointer to IterableAddressSet /// @param key value to insert. function insert(IterableAddressSet storage self, address key) internal { if (!exists(self, key)) { self.addresses.push(key); self.indices[key] = self.addresses.length - 1; } } /// @notice remove a key. /// @dev key to remove should exist but fails silently to avoid wasting gas on exist + remove calls /// @param self storage pointer to IterableAddressSet /// @param key value to remove. function remove(IterableAddressSet storage self, address key) internal { if (!exists(self, key)) { return; } uint256 last = self.addresses.length - 1; uint256 indexToReplace = self.indices[key]; if (indexToReplace != last) { address keyToMove = self.addresses[last]; self.indices[keyToMove] = indexToReplace; self.addresses[indexToReplace] = keyToMove; } delete self.indices[key]; self.addresses.pop(); } /// @notice check if a key is in IterableAddressSet /// @param self storage pointer to IterableAddressSet /// @param key value to check. /// @return bool true: is a member, false: not a member. function exists(IterableAddressSet storage self, address key) internal view returns (bool) { if (self.addresses.length == 0) return false; return self.addresses[self.indices[key]] == key; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0; // taken with <3 from https://github.com/Uniswap/uniswap-v3-core/blob/main/contracts/libraries/FullMath.sol // under the MIT license /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an /// intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division /// where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 /// or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = -denominator & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } }
// SPDX-License-Identifier: GPL-3.0-only // ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━ // ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━ // ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓ // ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃ // ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫ // ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ pragma solidity ^0.7.0; import "./IAnteTest.sol"; /// @title The interface for Ante V0.5 Ante Pool /// @notice The Ante Pool handles interactions with connected Ante Test interface IAntePool { /// @notice Emitted when a user adds to the stake or challenge pool /// @param staker The address of user /// @param amount Amount being added in wei /// @param isChallenger Whether or not this is added to the challenger pool event Stake(address indexed staker, uint256 amount, bool indexed isChallenger); /// @notice Emitted when a user removes from the stake or challenge pool /// @param staker The address of user /// @param amount Amount being removed in wei /// @param isChallenger Whether or not this is removed from the challenger pool event Unstake(address indexed staker, uint256 amount, bool indexed isChallenger); /// @notice Emitted when the connected Ante Test's invariant gets verified /// @param checker The address of challenger who called the verification event TestChecked(address indexed checker); /// @notice Emitted when the connected Ante Test has failed test verification /// @param checker The address of challenger who called the verification event FailureOccurred(address indexed checker); /// @notice Emitted when a challenger claims their payout for a failed test /// @param claimer The address of challenger claiming their payout /// @param amount Amount being claimed in wei event ClaimPaid(address indexed claimer, uint256 amount); /// @notice Emitted when a staker has withdrawn their stake after the 24 hour wait period /// @param staker The address of the staker removing their stake /// @param amount Amount withdrawn in wei event WithdrawStake(address indexed staker, uint256 amount); /// @notice Emitted when a staker cancels their withdraw action before the 24 hour wait period /// @param staker The address of the staker cancelling their withdraw /// @param amount Amount cancelled in wei event CancelWithdraw(address indexed staker, uint256 amount); /// @notice Initializes Ante Pool with the connected Ante Test /// @param _anteTest The Ante Test that will be connected to the Ante Pool /// @dev This function requires that the Ante Test address is valid and that /// the invariant validation currently passes function initialize(IAnteTest _anteTest) external; /// @notice Cancels a withdraw action of a staker before the 24 hour wait period expires /// @dev This is called when a staker has initiated a withdraw stake action but /// then decides to cancel that withdraw before the 24 hour wait period is over function cancelPendingWithdraw() external; /// @notice Runs the verification of the invariant of the connected Ante Test /// @dev Can only be called by a challenger who has challenged the Ante Test function checkTest() external; /// @notice Claims the payout of a failed Ante Test /// @dev To prevent double claiming, the challenger balance is checked before /// claiming and that balance is zeroed out once the claim is done function claim() external; /// @notice Adds a users's stake or challenge to the staker or challenger pool /// @param isChallenger Flag for if this is a challenger function stake(bool isChallenger) external payable; /// @notice Removes a user's stake or challenge from the staker or challenger pool /// @param amount Amount being removed in wei /// @param isChallenger Flag for if this is a challenger function unstake(uint256 amount, bool isChallenger) external; /// @notice Removes all of a user's stake or challenge from the respective pool /// @param isChallenger Flag for if this is a challenger function unstakeAll(bool isChallenger) external; /// @notice Updates the decay multipliers and amounts for the total staked and challenged pools /// @dev This function is called in most other functions as well to keep the /// decay amounts and pools accurate function updateDecay() external; /// @notice Initiates the withdraw process for a staker, starting the 24 hour waiting period /// @dev During the 24 hour waiting period, the value is locked to prevent /// users from removing their stake when a challenger is going to verify test function withdrawStake() external; /// @notice Returns the Ante Test connected to this Ante Pool /// @return IAnteTest The Ante Test interface function anteTest() external view returns (IAnteTest); /// @notice Get the info for the challenger pool /// @return numUsers The total number of challengers in the challenger pool /// totalAmount The total value locked in the challenger pool in wei /// decayMultiplier The current multiplier for decay function challengerInfo() external view returns ( uint256 numUsers, uint256 totalAmount, uint256 decayMultiplier ); /// @notice Get the info for the staker pool /// @return numUsers The total number of stakers in the staker pool /// totalAmount The total value locked in the staker pool in wei /// decayMultiplier The current multiplier for decay function stakingInfo() external view returns ( uint256 numUsers, uint256 totalAmount, uint256 decayMultiplier ); /// @notice Get the total value eligible for payout /// @dev This is used so that challengers must have challenged for at least /// 12 blocks to receive payout, this is to mitigate other challengers /// from trying to stick in a challenge right before the verification /// @return eligibleAmount Total value eligible for payout in wei function eligibilityInfo() external view returns (uint256 eligibleAmount); /// @notice Returns the Ante Pool factory address that created this Ante Pool /// @return Address of Ante Pool factory function factory() external view returns (address); /// @notice Returns the block at which the connected Ante Test failed /// @dev This is only set when a verify test action is taken, so the test could /// have logically failed beforehand, but without having a user initiating /// the verify test action /// @return Block number where Ante Test failed function failedBlock() external view returns (uint256); /// @notice Returns the payout amount for a specific challenger /// @param challenger Address of challenger /// @dev If this is called before an Ante Test has failed, then it's return /// value is an estimate /// @return Amount that could be claimed by challenger in wei function getChallengerPayout(address challenger) external view returns (uint256); /// @notice Returns the timestamp for when the staker's 24 hour wait period is over /// @param _user Address of withdrawing staker /// @dev This is timestamp is 24 hours after the time when the staker initaited the /// withdraw process /// @return Timestamp for when the value is no longer locked and can be removed function getPendingWithdrawAllowedTime(address _user) external view returns (uint256); /// @notice Returns the amount a staker is attempting to withdraw /// @param _user Address of withdrawing staker /// @return Amount which is being withdrawn in wei function getPendingWithdrawAmount(address _user) external view returns (uint256); /// @notice Returns the stored balance of a user in their respective pool /// @param _user Address of user /// @param isChallenger Flag if user is a challenger /// @dev This function calculates decay and returns the stored value after the /// decay has been either added (staker) or subtracted (challenger) /// @return Balance that the user has currently in wei function getStoredBalance(address _user, bool isChallenger) external view returns (uint256); /// @notice Returns total value of eligible payout for challengers /// @return Amount eligible for payout in wei function getTotalChallengerEligibleBalance() external view returns (uint256); /// @notice Returns total value locked of all challengers /// @return Total amount challenged in wei function getTotalChallengerStaked() external view returns (uint256); /// @notice Returns total value of all stakers who are withdrawing their stake /// @return Total amount waiting for withdraw in wei function getTotalPendingWithdraw() external view returns (uint256); /// @notice Returns total value locked of all stakers /// @return Total amount staked in wei function getTotalStaked() external view returns (uint256); /// @notice Returns a user's starting amount added in their respective pool /// @param _user Address of user /// @param isChallenger Flag if user is a challenger /// @dev This value is updated as decay is caluclated or additional value /// added to respective side /// @return User's starting amount in wei function getUserStartAmount(address _user, bool isChallenger) external view returns (uint256); /// @notice Returns the verifier bounty amount /// @dev Currently this is 5% of the total staked amount /// @return Bounty amount rewarded to challenger who verifies test in wei function getVerifierBounty() external view returns (uint256); /// @notice Returns the cutoff block when challenger can call verify test /// @dev This is currently 12 blocks after a challenger has challenged the test /// @return Block number of when verify test can be called by challenger function getCheckTestAllowedBlock(address _user) external view returns (uint256); /// @notice Returns the most recent block number where decay was updated /// @dev This is generally updated on most actions that interact with the Ante /// Pool contract /// @return Block number of when contract was last updated function lastUpdateBlock() external view returns (uint256); /// @notice Returns the most recent block number where a challenger verified test /// @dev This is updated whenever the verify test is activated, whether or not /// the Ante Test fails /// @return Block number of last verification attempt function lastVerifiedBlock() external view returns (uint256); /// @notice Returns the number of challengers that have claimed their payout /// @return Number of challengers function numPaidOut() external view returns (uint256); /// @notice Returns the number of times that the Ante Test has been verified /// @return Number of verifications function numTimesVerified() external view returns (uint256); /// @notice Returns if the connected Ante Test has failed /// @return True if the connected Ante Test has failed, False if not function pendingFailure() external view returns (bool); /// @notice Returns the total value of payout to challengers that have been claimed /// @return Value of claimed payouts in wei function totalPaidOut() external view returns (uint256); /// @notice Returns the address of verifier who successfully activated verify test /// @dev This is the user who will receive the verifier bounty /// @return Address of verifier challenger function verifier() external view returns (address); /// @notice Returns the total value of stakers who are withdrawing /// @return totalAmount total amount pending to be withdrawn in wei function withdrawInfo() external view returns (uint256 totalAmount); }
{ "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"testAddr","type":"address"},{"indexed":false,"internalType":"address","name":"testPool","type":"address"}],"name":"AntePoolCreated","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPools","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"testAddr","type":"address"}],"name":"createPool","outputs":[{"internalType":"address","name":"testPool","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolMap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506128b3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806341d1de97146100465780635b6735321461008c5780639049f9d2146100bf575b600080fd5b6100636004803603602081101561005c57600080fd5b50356100f2565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610063600480360360208110156100a257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610129565b610063600480360360208110156100d557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610151565b6001818154811061010257600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60006020819052908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b600073ffffffffffffffffffffffffffffffffffffffff82166101d557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f414e54453a205465737420616464726573732069732030000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260208190526040902054161561026957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f414e54453a20506f6f6c20616c72656164792063726561746564000000000000604482015290519081900360640190fd5b604051829060009061027d60208201610431565b6020820181038252601f19601f820116604052509050600084604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b8152601401915050604051602081830303815290604052805190602001209050808251602084016000f573ffffffffffffffffffffffffffffffffffffffff80871660009081526020819052604080822080548486167fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092556001805480820182559085527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180549091168217905581517fc4d66de8000000000000000000000000000000000000000000000000000000008152938816600485015290519397509263c4d66de892602480820193929182900301818387803b1580156103c357600080fd5b505af11580156103d7573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8881168252915191891693507f9089922f2c4f21a3c7a22f49fcbb52a2ca5e4d35171966522b2fe11af173364b925081900360200190a2505050919050565b61243f8061043f8339019056fe60806040526001805460ff60a01b1916600160a01b1790556008805460ff1916905534801561002d57600080fd5b50600180546001600160a01b03191633179055670de0b6b3a7640000600e819055601255436019556123db806100646000396000f3fe6080604052600436106102a05760003560e01c8063674b78441161016e578063a218141b116100cb578063c45a01551161007f578063e35e5d8411610064578063e35e5d8414610799578063ec7bb87c146107ae578063f39375ad146107c3576102a0565b8063c45a015514610744578063c4d66de814610759576102a0565b8063b6be0090116100b0578063b6be0090146106da578063bed9d8611461071a578063c31678e21461072f576102a0565b8063a218141b1461067d578063a87a8c2c14610692576102a0565b80637fab9e461161012257806392c7a64e1161010757806392c7a64e146105c357806393c00b42146106035780639ebea88c1461064b576102a0565b80637fab9e461461057b578063883d50361461059a576102a0565b8063703ec8c411610153578063703ec8c4146105075780637bb4d0a71461053a5780637fa76e431461054f576102a0565b8063674b7844146104b25780636a7b6506146104c7576102a0565b80632fde80e51161021c5780634e71d92d116101d0578063607c94f0116101b5578063607c94f01461047357806361037ff9146104885780636615bbf01461049d576102a0565b80634e71d92d146104475780635c0dd7761461045e576102a0565b806344e872201161020157806344e872201461040857806349c458831461041d5780634e54498814610432576102a0565b80632fde80e5146103de57806335fd4ce5146103f3576102a0565b80631357e1dc116102735780631e95a512116102585780631e95a512146103355780632043a1a3146103755780632b7ac3f3146103a0576102a0565b80631357e1dc1461030b578063156c2a6414610320576102a0565b806301646b06146102a55780630917e776146102cc5780630b07681c146102e157806312a1a255146102f6575b600080fd5b3480156102b157600080fd5b506102ba6107d8565b60408051918252519081900360200190f35b3480156102d857600080fd5b506102ba6107de565b3480156102ed57600080fd5b506102ba6107e5565b34801561030257600080fd5b506102ba6107eb565b34801561031757600080fd5b506102ba6107f6565b34801561032c57600080fd5b506102ba6107fc565b34801561034157600080fd5b506102ba6004803603602081101561035857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610802565b34801561038157600080fd5b5061038a610895565b6040805160ff9092168252519081900360200190f35b3480156103ac57600080fd5b506103b561089a565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156103ea57600080fd5b506102ba6108b6565b3480156103ff57600080fd5b506102ba6108bc565b34801561041457600080fd5b506102ba6108ee565b34801561042957600080fd5b506102ba6108f7565b34801561043e57600080fd5b506102ba6108fd565b34801561045357600080fd5b5061045c610903565b005b34801561046a57600080fd5b5061045c610a36565b34801561047f57600080fd5b5061045c610b4a565b34801561049457600080fd5b506102ba610d22565b3480156104a957600080fd5b506102ba610d28565b3480156104be57600080fd5b506102ba610d2e565b3480156104d357600080fd5b506102ba600480360360208110156104ea57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610d33565b34801561051357600080fd5b5061051c610d6a565b60408051938452602084019290925282820152519081900360600190f35b34801561054657600080fd5b506103b5610d76565b34801561055b57600080fd5b5061045c6004803603602081101561057257600080fd5b50351515610d92565b61045c6004803603602081101561059157600080fd5b50351515610e38565b3480156105a657600080fd5b506105af610fb8565b604080519115158252519081900360200190f35b3480156105cf57600080fd5b506102ba600480360360208110156105e657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610fd9565b34801561060f57600080fd5b506102ba6004803603604081101561062657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013515156110c6565b34801561065757600080fd5b5061045c6004803603604081101561066e57600080fd5b50803590602001351515611126565b34801561068957600080fd5b506102ba6111ba565b34801561069e57600080fd5b506102ba600480360360408110156106b557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013515156111c0565b3480156106e657600080fd5b506102ba600480360360208110156106fd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166112f1565b34801561072657600080fd5b5061045c61131c565b34801561073b57600080fd5b5061045c61144d565b34801561075057600080fd5b506103b56114c2565b34801561076557600080fd5b5061045c6004803603602081101561077c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114de565b3480156107a557600080fd5b506102ba611731565b3480156107ba57600080fd5b506102ba611738565b3480156107cf57600080fd5b5061051c61173e565b60035481565b600d545b90565b60185481565b662386f26fc1000081565b60075481565b60115490565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601760205260408120600181015461087d576040805162461bcd60e51b815260206004820152601960248201527f414e54453a206e6f7468696e6720746f20776974686472617700000000000000604482015290519081900360640190fd5b805461088c906201518061174a565b9150505b919050565b600c81565b60055473ffffffffffffffffffffffffffffffffffffffff1681565b60045481565b601854600d5460009182916108d09161174a565b90506108e860646108e28360056117a4565b906117fd565b91505090565b64174876e80081565b60065481565b60145490565b60015474010000000000000000000000000000000000000000900460ff16610972576040805162461bcd60e51b815260206004820152601960248201527f414e54453a205465737420686173206e6f74206661696c656400000000000000604482015290519081900360640190fd5b336000908152600f6020526040902080546109be5760405162461bcd60e51b81526004018080602001828103825260238152602001806122f86023913960400191505060405180910390fd5b60006109ca8233611864565b600083556006549091506109df90600161174a565b6006556007546109ef908261174a565b6007556109fc338261190d565b60408051828152905133917ff42cf8c29487b42c009006cba2a2a0ca0388229f3183e6e957e0a0b163585cb4919081900360200190a25050565b610a3e61195e565b3360009081526017602052604090206001810154610a8d5760405162461bcd60e51b81526004018080602001828103825260218152602001806121d36021913960400191505060405180910390fd5b6001810180546000909155610aa061144d565b336000908152600b60205260409020805415610ad257610acb610ac482600b6119ce565b839061174a565b8155610ae7565b818155600c54610ae390600161174a565b600c555b600d54610af4908361174a565b600d55600e546001820155601854610b0c9083611a39565b60185560408051838152905133917f62437abf8b924b1ad4fbca02f5402eb6fe6bf4ba9b844f3c1378a7507e3799a0919081900360200190a2505050565b610b5261195e565b610b5d601533611a96565b610b985760405162461bcd60e51b81526004018080602001828103825260248152602001806121af6024913960400191505060405180910390fd5b33600090815260136020526040902054600c90610bb6904390611a39565b11610bf25760405162461bcd60e51b815260040180806020018281038252603d815260200180612342603d913960400191505060405180910390fd5b600254610c0090600161174a565b6002554360045560405133907f19be9da849e19de3d0b3e9d11c9b0542b8e91a3f26d3188b8984ee8bac17fcac90600090a2610c3a611b0b565b610d2057610c4661144d565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905543600355600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055610cbb611bae565b610cc36108bc565b600955601854600d54600091610cd9919061174a565b9050610cf060095482611a3990919063ffffffff16565b600a5560405133907f9818c5a155ab582a34fec045ea885625c3d2bcb231cf25d5501f54d000ee891190600090a2505b565b60025481565b60185490565b600581565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260136020526040812054610d6490600c61174a565b92915050565b600c54600d54600e5483565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b610d9a61195e565b610da261144d565b600081610db057600b610db3565b600f5b336000908152602082905260408120919250610dcf82846119ce565b905060008111610e26576040805162461bcd60e51b815260206004820152601860248201527f414e54453a204e6f7468696e6720746f20756e7374616b650000000000000000604482015290519081900360640190fd5b610e3281858585611c6c565b50505050565b610e4061195e565b3480610e93576040805162461bcd60e51b815260206004820152601760248201527f414e54453a2043616e6e6f74207374616b65207a65726f000000000000000000604482015290519081900360640190fd5b610e9b61144d565b60008215610f0e57662386f26fc10000821015610ee95760405162461bcd60e51b815260040180806020018281038252602e815260200180612255602e913960400191505060405180910390fd5b50600f610ef7601533611daf565b336000908152601360205260409020439055610f12565b50600b5b336000908152602082905260409020805415610f4357610f3c610f3582846119ce565b849061174a565b8155610f5b565b828155600182810154610f559161174a565b60018301555b6002820154610f6a908461174a565b6002830155600382015460018201556040805184815290518515159133917f20580cc2838cc75cd2cfb9e285a0d4c24078360f4273611af79fcdff9a6a806f9181900360200190a350505050565b60015474010000000000000000000000000000000000000000900460ff1681565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f60205260408120805461103b5760405162461bcd60e51b81526004018080602001828103825260238152602001806122f86023913960400191505060405180910390fd5b60015474010000000000000000000000000000000000000000900460ff1615611070576110688184611864565b915050610890565b600061107d82600f6119ce565b905060006110896108bc565b601854600d5491925060009161109e9161174a565b90506110bb610f356110b08385611a39565b601154869190611e4d565b945050505050610890565b6000816110f85773ffffffffffffffffffffffffffffffffffffffff83166000908152600b602052604090205461111f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600f60205260409020545b9392505050565b61112e61195e565b60008211611183576040805162461bcd60e51b815260206004820152601760248201527f414e54453a2043616e6e6f7420756e7374616b6520302e000000000000000000604482015290519081900360640190fd5b61118b61144d565b60008161119957600b61119c565b600f5b336000908152602082905260409020909150610e3284848484611c6c565b60195481565b60008060006111cd611f1a565b915091506000846112025773ffffffffffffffffffffffffffffffffffffffff86166000908152600b60205260409020611228565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600f602052604090205b805490915061123d5760009350505050610d64565b60008160010154116112805760405162461bcd60e51b81526004018080602001828103825260228152602001806122336022913960400191505060405180910390fd5b600085156112aa576012546112a390670de0b6b3a7640000906108e290876117a4565b90506112d4565b600d5460006112b9828661174a565b600e549091506112cf9083906108e290846117a4565b925050505b600182015482546112e6918390611e4d565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526017602052604090206001015490565b61132461195e565b33600090815260176020526040902080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeae804201116113945760405162461bcd60e51b815260040180806020018281038252602a815260200180612283602a913960400191505060405180910390fd5b60008160010154116113ed576040805162461bcd60e51b815260206004820152601960248201527f414e54453a204e6f7468696e6720746f20776974686472617700000000000000604482015290519081900360640190fd5b60018101546018546113ff9082611a39565b60185560006001830155611413338261190d565b60408051828152905133917f141ef67c4a6d3ec2adfb2f66d33c2b11de5b4f34344757554d430570b18a92ec919081900360200190a25050565b600080611458611f1a565b4360195590925090508061146d575050610d20565b600d546011546012546114899085670de0b6b3a7640000611e4d565b6012556114968184611a39565b60115560006114a5838561174a565b600e549091506114b6908285611e4d565b600e55600d5550505050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60085460ff1615611536576040805162461bcd60e51b815260206004820152601e60248201527f414e54453a20506f6f6c20616c726561647920696e697469616c697a65640000604482015290519081900360640190fd5b60015473ffffffffffffffffffffffffffffffffffffffff16331461158c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806122ce602a913960400191505060405180910390fd5b6115ab8173ffffffffffffffffffffffffffffffffffffffff16611ff4565b6115e65760405162461bcd60e51b815260040180806020018281038252602781526020018061237f6027913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561162e57600080fd5b505af1158015611642573d6000803e3d6000fd5b505050506040513d602081101561165857600080fd5b50516116955760405162461bcd60e51b815260040180806020018281038252603f8152602001806121f4603f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6201518081565b60145481565b60105460115460125483565b60008282018381101561111f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000826117b357506000610d64565b828202828482816117c057fe5b041461111f5760405162461bcd60e51b81526004018080602001828103825260218152602001806122ad6021913960400191505060405180910390fd5b6000808211611853576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161185c57fe5b049392505050565b60008061187284600f6119ce565b60035490915061188390600c611a39565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604090205410156118cf57600a546014546118cc916118c591849190611e4d565b829061174a565b90505b60055473ffffffffffffffffffffffffffffffffffffffff8481169116146118f75780611905565b60095461190590829061174a565b949350505050565b8173ffffffffffffffffffffffffffffffffffffffff166108fc6119318347611ffa565b6040518115909202916000818181858888f19350505050158015611959573d6000803e3d6000fd5b505050565b60015474010000000000000000000000000000000000000000900460ff1615610d20576040805162461bcd60e51b815260206004820152601a60248201527f414e54453a205465737420616c7265616479206661696c65642e000000000000604482015290519081900360640190fd5b81546000906119df57506000610d64565b6000836001015411611a225760405162461bcd60e51b81526004018080602001828103825260228152602001806122336022913960400191505060405180910390fd5b60038201546001840154845461111f929091611e4d565b600082821115611a90576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001820154600090611aaa57506000610d64565b73ffffffffffffffffffffffffffffffffffffffff82166000818152602085905260409020546001850180549091908110611ae157fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16149392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b7657600080fd5b505af1925050508015611b9b57506040513d6020811015611b9657600080fd5b505160015b611ba7575060006107e2565b90506107e2565b600354600090611bbf90600c611a39565b905060005b601654811015611c6857600060156001018281548110611be057fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083526013909152604090912054909150831115611c5f5773ffffffffffffffffffffffffffffffffffffffff81166000908152600f60208190526040909120611c5b91611c5291906119ce565b6014549061174a565b6014555b50600101611bc4565b5050565b6000611c7882846119ce565b905084811415611cb857600080835560018084019190915583810154611c9d91611a39565b60018401558315611cb357611cb3601533612010565b611d0e565b80851115611cf75760405162461bcd60e51b815260040180806020018281038252602781526020018061231b6027913960400191505060405180910390fd5b611d018186611a39565b8255600383015460018301555b6002830154611d1d9086611a39565b60028401558315611d3757611d32338661190d565b611d6f565b3360009081526017602052604090204281556001810154611d58908761174a565b6001820155601854611d6a908761174a565b601855505b6040805186815290518515159133917f2dad9020fc3cab73927d1f0192936d8dcbceac42333d75509d99c2c941339ccf9181900360200190a35050505050565b611db98282611a96565b611c68576001828101805491820181556000818152602080822090930180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff959095169485179055905492815292905260409091207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019055565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870986860292508281109083900303905080611ea15760008411611e9657600080fd5b50829004905061111f565b808411611ead57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b601954670de0b6b3a7640000906000904311611f3557611ff0565b60015474010000000000000000000000000000000000000000900460ff1615611f5d57611ff0565b600d54601154811580611f6e575080155b15611f7a575050611ff0565b6000611f9160195443611a3990919063ffffffff16565b90506000611fa464174876e800836117a4565b9050670de0b6b3a76400008110611fc15760009550829450611feb565b611fd3670de0b6b3a764000082611a39565b9550611fe88382670de0b6b3a7640000611e4d565b94505b505050505b9091565b3b151590565b6000818310612009578161111f565b5090919050565b61201a8282611a96565b61202357611c68565b600182015473ffffffffffffffffffffffffffffffffffffffff82166000908152602084905260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019080821461211d57600084600101838154811061208b57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083529087905260409091208390556001860180549192508291849081106120d357fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b73ffffffffffffffffffffffffffffffffffffffff83166000908152602085905260408120556001840180548061215057fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555050505056fe414e54453a204f6e6c79206368616c6c656e676572732063616e20636865636b54657374414e54453a204e6f2070656e64696e672077697468647261772062616c616e6365414e54453a20416e74655465737420646f6573206e6f7420696d706c656d656e7420636865636b54657374506173736573206f722074657374206661696c73414e54453a20496e76616c696420737461727444656361794d756c7469706c696572414e54453a204368616c6c656e676572206d757374207374616b65206d6f7265207468616e20302e303120455448414e54453a206d757374207761697420323420686f75727320746f207769746864726177207374616b65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77414e54453a206f6e6c7920666163746f72792063616e20696e697469616c697a6520416e7465506f6f6c414e54453a204e6f204368616c6c656e676572205374616b696e672062616c616e6365414e54453a205769746864726177207265717565737420657863656564732062616c616e63652e414e54453a206d757374207761697420313220626c6f636b73206166746572206368616c6c656e67696e6720746f2063616c6c20636865636b54657374414e54453a20416e746554657374206d757374206265206120736d61727420636f6e7472616374a26469706673582212208a68b95ae628a7624f9f5dd2dc1e8ff5dc8e22bab4d2491bc71f57fd4df21b4164736f6c63430007060033a2646970667358221220d7ca7ec2141d8ac5cf9d6f31f8ac62228d4ec950f8547aef94bab89d4e4b6d6f64736f6c63430007060033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100415760003560e01c806341d1de97146100465780635b6735321461008c5780639049f9d2146100bf575b600080fd5b6100636004803603602081101561005c57600080fd5b50356100f2565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610063600480360360208110156100a257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610129565b610063600480360360208110156100d557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610151565b6001818154811061010257600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60006020819052908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b600073ffffffffffffffffffffffffffffffffffffffff82166101d557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f414e54453a205465737420616464726573732069732030000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260208190526040902054161561026957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f414e54453a20506f6f6c20616c72656164792063726561746564000000000000604482015290519081900360640190fd5b604051829060009061027d60208201610431565b6020820181038252601f19601f820116604052509050600084604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b8152601401915050604051602081830303815290604052805190602001209050808251602084016000f573ffffffffffffffffffffffffffffffffffffffff80871660009081526020819052604080822080548486167fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092556001805480820182559085527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180549091168217905581517fc4d66de8000000000000000000000000000000000000000000000000000000008152938816600485015290519397509263c4d66de892602480820193929182900301818387803b1580156103c357600080fd5b505af11580156103d7573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8881168252915191891693507f9089922f2c4f21a3c7a22f49fcbb52a2ca5e4d35171966522b2fe11af173364b925081900360200190a2505050919050565b61243f8061043f8339019056fe60806040526001805460ff60a01b1916600160a01b1790556008805460ff1916905534801561002d57600080fd5b50600180546001600160a01b03191633179055670de0b6b3a7640000600e819055601255436019556123db806100646000396000f3fe6080604052600436106102a05760003560e01c8063674b78441161016e578063a218141b116100cb578063c45a01551161007f578063e35e5d8411610064578063e35e5d8414610799578063ec7bb87c146107ae578063f39375ad146107c3576102a0565b8063c45a015514610744578063c4d66de814610759576102a0565b8063b6be0090116100b0578063b6be0090146106da578063bed9d8611461071a578063c31678e21461072f576102a0565b8063a218141b1461067d578063a87a8c2c14610692576102a0565b80637fab9e461161012257806392c7a64e1161010757806392c7a64e146105c357806393c00b42146106035780639ebea88c1461064b576102a0565b80637fab9e461461057b578063883d50361461059a576102a0565b8063703ec8c411610153578063703ec8c4146105075780637bb4d0a71461053a5780637fa76e431461054f576102a0565b8063674b7844146104b25780636a7b6506146104c7576102a0565b80632fde80e51161021c5780634e71d92d116101d0578063607c94f0116101b5578063607c94f01461047357806361037ff9146104885780636615bbf01461049d576102a0565b80634e71d92d146104475780635c0dd7761461045e576102a0565b806344e872201161020157806344e872201461040857806349c458831461041d5780634e54498814610432576102a0565b80632fde80e5146103de57806335fd4ce5146103f3576102a0565b80631357e1dc116102735780631e95a512116102585780631e95a512146103355780632043a1a3146103755780632b7ac3f3146103a0576102a0565b80631357e1dc1461030b578063156c2a6414610320576102a0565b806301646b06146102a55780630917e776146102cc5780630b07681c146102e157806312a1a255146102f6575b600080fd5b3480156102b157600080fd5b506102ba6107d8565b60408051918252519081900360200190f35b3480156102d857600080fd5b506102ba6107de565b3480156102ed57600080fd5b506102ba6107e5565b34801561030257600080fd5b506102ba6107eb565b34801561031757600080fd5b506102ba6107f6565b34801561032c57600080fd5b506102ba6107fc565b34801561034157600080fd5b506102ba6004803603602081101561035857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610802565b34801561038157600080fd5b5061038a610895565b6040805160ff9092168252519081900360200190f35b3480156103ac57600080fd5b506103b561089a565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156103ea57600080fd5b506102ba6108b6565b3480156103ff57600080fd5b506102ba6108bc565b34801561041457600080fd5b506102ba6108ee565b34801561042957600080fd5b506102ba6108f7565b34801561043e57600080fd5b506102ba6108fd565b34801561045357600080fd5b5061045c610903565b005b34801561046a57600080fd5b5061045c610a36565b34801561047f57600080fd5b5061045c610b4a565b34801561049457600080fd5b506102ba610d22565b3480156104a957600080fd5b506102ba610d28565b3480156104be57600080fd5b506102ba610d2e565b3480156104d357600080fd5b506102ba600480360360208110156104ea57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610d33565b34801561051357600080fd5b5061051c610d6a565b60408051938452602084019290925282820152519081900360600190f35b34801561054657600080fd5b506103b5610d76565b34801561055b57600080fd5b5061045c6004803603602081101561057257600080fd5b50351515610d92565b61045c6004803603602081101561059157600080fd5b50351515610e38565b3480156105a657600080fd5b506105af610fb8565b604080519115158252519081900360200190f35b3480156105cf57600080fd5b506102ba600480360360208110156105e657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610fd9565b34801561060f57600080fd5b506102ba6004803603604081101561062657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013515156110c6565b34801561065757600080fd5b5061045c6004803603604081101561066e57600080fd5b50803590602001351515611126565b34801561068957600080fd5b506102ba6111ba565b34801561069e57600080fd5b506102ba600480360360408110156106b557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013515156111c0565b3480156106e657600080fd5b506102ba600480360360208110156106fd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166112f1565b34801561072657600080fd5b5061045c61131c565b34801561073b57600080fd5b5061045c61144d565b34801561075057600080fd5b506103b56114c2565b34801561076557600080fd5b5061045c6004803603602081101561077c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114de565b3480156107a557600080fd5b506102ba611731565b3480156107ba57600080fd5b506102ba611738565b3480156107cf57600080fd5b5061051c61173e565b60035481565b600d545b90565b60185481565b662386f26fc1000081565b60075481565b60115490565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601760205260408120600181015461087d576040805162461bcd60e51b815260206004820152601960248201527f414e54453a206e6f7468696e6720746f20776974686472617700000000000000604482015290519081900360640190fd5b805461088c906201518061174a565b9150505b919050565b600c81565b60055473ffffffffffffffffffffffffffffffffffffffff1681565b60045481565b601854600d5460009182916108d09161174a565b90506108e860646108e28360056117a4565b906117fd565b91505090565b64174876e80081565b60065481565b60145490565b60015474010000000000000000000000000000000000000000900460ff16610972576040805162461bcd60e51b815260206004820152601960248201527f414e54453a205465737420686173206e6f74206661696c656400000000000000604482015290519081900360640190fd5b336000908152600f6020526040902080546109be5760405162461bcd60e51b81526004018080602001828103825260238152602001806122f86023913960400191505060405180910390fd5b60006109ca8233611864565b600083556006549091506109df90600161174a565b6006556007546109ef908261174a565b6007556109fc338261190d565b60408051828152905133917ff42cf8c29487b42c009006cba2a2a0ca0388229f3183e6e957e0a0b163585cb4919081900360200190a25050565b610a3e61195e565b3360009081526017602052604090206001810154610a8d5760405162461bcd60e51b81526004018080602001828103825260218152602001806121d36021913960400191505060405180910390fd5b6001810180546000909155610aa061144d565b336000908152600b60205260409020805415610ad257610acb610ac482600b6119ce565b839061174a565b8155610ae7565b818155600c54610ae390600161174a565b600c555b600d54610af4908361174a565b600d55600e546001820155601854610b0c9083611a39565b60185560408051838152905133917f62437abf8b924b1ad4fbca02f5402eb6fe6bf4ba9b844f3c1378a7507e3799a0919081900360200190a2505050565b610b5261195e565b610b5d601533611a96565b610b985760405162461bcd60e51b81526004018080602001828103825260248152602001806121af6024913960400191505060405180910390fd5b33600090815260136020526040902054600c90610bb6904390611a39565b11610bf25760405162461bcd60e51b815260040180806020018281038252603d815260200180612342603d913960400191505060405180910390fd5b600254610c0090600161174a565b6002554360045560405133907f19be9da849e19de3d0b3e9d11c9b0542b8e91a3f26d3188b8984ee8bac17fcac90600090a2610c3a611b0b565b610d2057610c4661144d565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905543600355600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055610cbb611bae565b610cc36108bc565b600955601854600d54600091610cd9919061174a565b9050610cf060095482611a3990919063ffffffff16565b600a5560405133907f9818c5a155ab582a34fec045ea885625c3d2bcb231cf25d5501f54d000ee891190600090a2505b565b60025481565b60185490565b600581565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260136020526040812054610d6490600c61174a565b92915050565b600c54600d54600e5483565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b610d9a61195e565b610da261144d565b600081610db057600b610db3565b600f5b336000908152602082905260408120919250610dcf82846119ce565b905060008111610e26576040805162461bcd60e51b815260206004820152601860248201527f414e54453a204e6f7468696e6720746f20756e7374616b650000000000000000604482015290519081900360640190fd5b610e3281858585611c6c565b50505050565b610e4061195e565b3480610e93576040805162461bcd60e51b815260206004820152601760248201527f414e54453a2043616e6e6f74207374616b65207a65726f000000000000000000604482015290519081900360640190fd5b610e9b61144d565b60008215610f0e57662386f26fc10000821015610ee95760405162461bcd60e51b815260040180806020018281038252602e815260200180612255602e913960400191505060405180910390fd5b50600f610ef7601533611daf565b336000908152601360205260409020439055610f12565b50600b5b336000908152602082905260409020805415610f4357610f3c610f3582846119ce565b849061174a565b8155610f5b565b828155600182810154610f559161174a565b60018301555b6002820154610f6a908461174a565b6002830155600382015460018201556040805184815290518515159133917f20580cc2838cc75cd2cfb9e285a0d4c24078360f4273611af79fcdff9a6a806f9181900360200190a350505050565b60015474010000000000000000000000000000000000000000900460ff1681565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f60205260408120805461103b5760405162461bcd60e51b81526004018080602001828103825260238152602001806122f86023913960400191505060405180910390fd5b60015474010000000000000000000000000000000000000000900460ff1615611070576110688184611864565b915050610890565b600061107d82600f6119ce565b905060006110896108bc565b601854600d5491925060009161109e9161174a565b90506110bb610f356110b08385611a39565b601154869190611e4d565b945050505050610890565b6000816110f85773ffffffffffffffffffffffffffffffffffffffff83166000908152600b602052604090205461111f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600f60205260409020545b9392505050565b61112e61195e565b60008211611183576040805162461bcd60e51b815260206004820152601760248201527f414e54453a2043616e6e6f7420756e7374616b6520302e000000000000000000604482015290519081900360640190fd5b61118b61144d565b60008161119957600b61119c565b600f5b336000908152602082905260409020909150610e3284848484611c6c565b60195481565b60008060006111cd611f1a565b915091506000846112025773ffffffffffffffffffffffffffffffffffffffff86166000908152600b60205260409020611228565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600f602052604090205b805490915061123d5760009350505050610d64565b60008160010154116112805760405162461bcd60e51b81526004018080602001828103825260228152602001806122336022913960400191505060405180910390fd5b600085156112aa576012546112a390670de0b6b3a7640000906108e290876117a4565b90506112d4565b600d5460006112b9828661174a565b600e549091506112cf9083906108e290846117a4565b925050505b600182015482546112e6918390611e4d565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526017602052604090206001015490565b61132461195e565b33600090815260176020526040902080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeae804201116113945760405162461bcd60e51b815260040180806020018281038252602a815260200180612283602a913960400191505060405180910390fd5b60008160010154116113ed576040805162461bcd60e51b815260206004820152601960248201527f414e54453a204e6f7468696e6720746f20776974686472617700000000000000604482015290519081900360640190fd5b60018101546018546113ff9082611a39565b60185560006001830155611413338261190d565b60408051828152905133917f141ef67c4a6d3ec2adfb2f66d33c2b11de5b4f34344757554d430570b18a92ec919081900360200190a25050565b600080611458611f1a565b4360195590925090508061146d575050610d20565b600d546011546012546114899085670de0b6b3a7640000611e4d565b6012556114968184611a39565b60115560006114a5838561174a565b600e549091506114b6908285611e4d565b600e55600d5550505050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60085460ff1615611536576040805162461bcd60e51b815260206004820152601e60248201527f414e54453a20506f6f6c20616c726561647920696e697469616c697a65640000604482015290519081900360640190fd5b60015473ffffffffffffffffffffffffffffffffffffffff16331461158c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806122ce602a913960400191505060405180910390fd5b6115ab8173ffffffffffffffffffffffffffffffffffffffff16611ff4565b6115e65760405162461bcd60e51b815260040180806020018281038252602781526020018061237f6027913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561162e57600080fd5b505af1158015611642573d6000803e3d6000fd5b505050506040513d602081101561165857600080fd5b50516116955760405162461bcd60e51b815260040180806020018281038252603f8152602001806121f4603f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6201518081565b60145481565b60105460115460125483565b60008282018381101561111f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000826117b357506000610d64565b828202828482816117c057fe5b041461111f5760405162461bcd60e51b81526004018080602001828103825260218152602001806122ad6021913960400191505060405180910390fd5b6000808211611853576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161185c57fe5b049392505050565b60008061187284600f6119ce565b60035490915061188390600c611a39565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604090205410156118cf57600a546014546118cc916118c591849190611e4d565b829061174a565b90505b60055473ffffffffffffffffffffffffffffffffffffffff8481169116146118f75780611905565b60095461190590829061174a565b949350505050565b8173ffffffffffffffffffffffffffffffffffffffff166108fc6119318347611ffa565b6040518115909202916000818181858888f19350505050158015611959573d6000803e3d6000fd5b505050565b60015474010000000000000000000000000000000000000000900460ff1615610d20576040805162461bcd60e51b815260206004820152601a60248201527f414e54453a205465737420616c7265616479206661696c65642e000000000000604482015290519081900360640190fd5b81546000906119df57506000610d64565b6000836001015411611a225760405162461bcd60e51b81526004018080602001828103825260228152602001806122336022913960400191505060405180910390fd5b60038201546001840154845461111f929091611e4d565b600082821115611a90576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001820154600090611aaa57506000610d64565b73ffffffffffffffffffffffffffffffffffffffff82166000818152602085905260409020546001850180549091908110611ae157fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16149392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b7657600080fd5b505af1925050508015611b9b57506040513d6020811015611b9657600080fd5b505160015b611ba7575060006107e2565b90506107e2565b600354600090611bbf90600c611a39565b905060005b601654811015611c6857600060156001018281548110611be057fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083526013909152604090912054909150831115611c5f5773ffffffffffffffffffffffffffffffffffffffff81166000908152600f60208190526040909120611c5b91611c5291906119ce565b6014549061174a565b6014555b50600101611bc4565b5050565b6000611c7882846119ce565b905084811415611cb857600080835560018084019190915583810154611c9d91611a39565b60018401558315611cb357611cb3601533612010565b611d0e565b80851115611cf75760405162461bcd60e51b815260040180806020018281038252602781526020018061231b6027913960400191505060405180910390fd5b611d018186611a39565b8255600383015460018301555b6002830154611d1d9086611a39565b60028401558315611d3757611d32338661190d565b611d6f565b3360009081526017602052604090204281556001810154611d58908761174a565b6001820155601854611d6a908761174a565b601855505b6040805186815290518515159133917f2dad9020fc3cab73927d1f0192936d8dcbceac42333d75509d99c2c941339ccf9181900360200190a35050505050565b611db98282611a96565b611c68576001828101805491820181556000818152602080822090930180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff959095169485179055905492815292905260409091207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019055565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870986860292508281109083900303905080611ea15760008411611e9657600080fd5b50829004905061111f565b808411611ead57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b601954670de0b6b3a7640000906000904311611f3557611ff0565b60015474010000000000000000000000000000000000000000900460ff1615611f5d57611ff0565b600d54601154811580611f6e575080155b15611f7a575050611ff0565b6000611f9160195443611a3990919063ffffffff16565b90506000611fa464174876e800836117a4565b9050670de0b6b3a76400008110611fc15760009550829450611feb565b611fd3670de0b6b3a764000082611a39565b9550611fe88382670de0b6b3a7640000611e4d565b94505b505050505b9091565b3b151590565b6000818310612009578161111f565b5090919050565b61201a8282611a96565b61202357611c68565b600182015473ffffffffffffffffffffffffffffffffffffffff82166000908152602084905260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019080821461211d57600084600101838154811061208b57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083529087905260409091208390556001860180549192508291849081106120d357fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b73ffffffffffffffffffffffffffffffffffffffff83166000908152602085905260408120556001840180548061215057fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555050505056fe414e54453a204f6e6c79206368616c6c656e676572732063616e20636865636b54657374414e54453a204e6f2070656e64696e672077697468647261772062616c616e6365414e54453a20416e74655465737420646f6573206e6f7420696d706c656d656e7420636865636b54657374506173736573206f722074657374206661696c73414e54453a20496e76616c696420737461727444656361794d756c7469706c696572414e54453a204368616c6c656e676572206d757374207374616b65206d6f7265207468616e20302e303120455448414e54453a206d757374207761697420323420686f75727320746f207769746864726177207374616b65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77414e54453a206f6e6c7920666163746f72792063616e20696e697469616c697a6520416e7465506f6f6c414e54453a204e6f204368616c6c656e676572205374616b696e672062616c616e6365414e54453a205769746864726177207265717565737420657863656564732062616c616e63652e414e54453a206d757374207761697420313220626c6f636b73206166746572206368616c6c656e67696e6720746f2063616c6c20636865636b54657374414e54453a20416e746554657374206d757374206265206120736d61727420636f6e7472616374a26469706673582212208a68b95ae628a7624f9f5dd2dc1e8ff5dc8e22bab4d2491bc71f57fd4df21b4164736f6c63430007060033a2646970667358221220d7ca7ec2141d8ac5cf9d6f31f8ac62228d4ec950f8547aef94bab89d4e4b6d6f64736f6c63430007060033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.