ETH Price: $2,648.43 (-0.43%)

Contract

0xa03492A9A663F04c51684A3c172FC9c4D7E02eDc
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create Pool165957152023-02-10 3:37:23729 days ago1676000243IN
0xa03492A9...4D7E02eDc
0 ETH0.05255424.95612349
Create Pool162959562022-12-30 7:00:23771 days ago1672383623IN
0xa03492A9...4D7E02eDc
0 ETH0.0352875215.98583342
Create Pool161513602022-12-10 2:36:35791 days ago1670639795IN
0xa03492A9...4D7E02eDc
0 ETH0.0334176515.90362867
Create Pool161393762022-12-08 10:24:23793 days ago1670495063IN
0xa03492A9...4D7E02eDc
0 ETH0.0317790815.07475132
Create Pool161247362022-12-06 9:04:23795 days ago1670317463IN
0xa03492A9...4D7E02eDc
0 ETH0.0283958213.60756641
Create Pool161145242022-12-04 22:48:23796 days ago1670194103IN
0xa03492A9...4D7E02eDc
0 ETH0.0309917314.65085208
Create Pool161099452022-12-04 7:26:11797 days ago1670138771IN
0xa03492A9...4D7E02eDc
0 ETH0.0260125811.66210684
Create Pool161063622022-12-03 19:26:35798 days ago1670095595IN
0xa03492A9...4D7E02eDc
0 ETH0.0265773312.58249465
Create Pool160997862022-12-02 21:23:59798 days ago1670016239IN
0xa03492A9...4D7E02eDc
0 ETH0.035772915.11963425
Create Pool160947382022-12-02 4:29:11799 days ago1669955351IN
0xa03492A9...4D7E02eDc
0 ETH0.0278501613.32972323
Create Pool160812442022-11-30 7:14:23801 days ago1669792463IN
0xa03492A9...4D7E02eDc
0 ETH0.0257145812.0677764
Create Pool160811552022-11-30 6:56:23801 days ago1669791383IN
0xa03492A9...4D7E02eDc
0 ETH0.0249752711.94918986
Create Pool160716462022-11-28 23:02:59802 days ago1669676579IN
0xa03492A9...4D7E02eDc
0 ETH0.0251227411.97788568
Create Pool160651342022-11-28 1:16:11803 days ago1669598171IN
0xa03492A9...4D7E02eDc
0 ETH0.024336311.45225968
Create Pool160232402022-11-22 4:43:59809 days ago1669092239IN
0xa03492A9...4D7E02eDc
0 ETH0.0246341911.76220358
Create Pool159207032022-11-07 21:01:59823 days ago1667854919IN
0xa03492A9...4D7E02eDc
0 ETH0.0476059821.60693968
Create Pool158997592022-11-04 22:52:23826 days ago1667602343IN
0xa03492A9...4D7E02eDc
0 ETH0.0306817313.64861712
Create Pool158997402022-11-04 22:48:35826 days ago1667602115IN
0xa03492A9...4D7E02eDc
0 ETH0.0305440314.61350914
Create Pool158996972022-11-04 22:39:59826 days ago1667601599IN
0xa03492A9...4D7E02eDc
0 ETH0.0300983214.20180375
Create Pool158996582022-11-04 22:32:11826 days ago1667601131IN
0xa03492A9...4D7E02eDc
0 ETH0.0270592712.74939749
Create Pool158996112022-11-04 22:22:47826 days ago1667600567IN
0xa03492A9...4D7E02eDc
0 ETH0.0292744613.90165995
Create Pool158278352022-10-25 21:41:35836 days ago1666734095IN
0xa03492A9...4D7E02eDc
0 ETH0.0378066118.09136048
Create Pool157412242022-10-13 19:17:23849 days ago1665688643IN
0xa03492A9...4D7E02eDc
0 ETH0.060643529.00921512
Create Pool154181602022-08-26 23:04:23896 days ago1661555063IN
0xa03492A9...4D7E02eDc
0 ETH0.016977847.95590304
Create Pool153735882022-08-19 21:10:14903 days ago1660943414IN
0xa03492A9...4D7E02eDc
0 ETH0.0390505418.71439548
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
165957152023-02-10 3:37:23729 days ago1676000243
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
162959562022-12-30 7:00:23771 days ago1672383623
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
161513602022-12-10 2:36:35791 days ago1670639795
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
161393762022-12-08 10:24:23793 days ago1670495063
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
161247362022-12-06 9:04:23795 days ago1670317463
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
161145242022-12-04 22:48:23796 days ago1670194103
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
161099452022-12-04 7:26:11797 days ago1670138771
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
161063622022-12-03 19:26:35798 days ago1670095595
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
160997862022-12-02 21:23:59798 days ago1670016239
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
160947382022-12-02 4:29:11799 days ago1669955351
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
160812442022-11-30 7:14:23801 days ago1669792463
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
160811552022-11-30 6:56:23801 days ago1669791383
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
160716462022-11-28 23:02:59802 days ago1669676579
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
160651342022-11-28 1:16:11803 days ago1669598171
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
160232402022-11-22 4:43:59809 days ago1669092239
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
159207032022-11-07 21:01:59823 days ago1667854919
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
158997592022-11-04 22:52:23826 days ago1667602343
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
158997402022-11-04 22:48:35826 days ago1667602115
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
158996972022-11-04 22:39:59826 days ago1667601599
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
158996582022-11-04 22:32:11826 days ago1667601131
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
158996112022-11-04 22:22:47826 days ago1667600567
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
158278352022-10-25 21:41:35836 days ago1666734095
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
157412242022-10-13 19:17:23849 days ago1665688643
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
154181602022-08-26 23:04:23896 days ago1661555063
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
153735882022-08-19 21:10:14903 days ago1660943414
0xa03492A9...4D7E02eDc
 Contract Creation0 ETH
View All Internal Transactions
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
File 1 of 9 : AntePoolFactory.sol
// 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);
    }
}

File 2 of 9 : AntePool.sol
// 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.");
    }
}

File 3 of 9 : IAnteTest.sol
// 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);
}

File 4 of 9 : IAntePoolFactory.sol
// 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);
}

File 5 of 9 : SafeMath.sol
// 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;
    }
}

File 6 of 9 : Address.sol
// 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);
            }
        }
    }
}

File 7 of 9 : IterableSet.sol
// 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;
    }
}

File 8 of 9 : FullMath.sol
// 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;
    }
}

File 9 of 9 : IAntePool.sol
// 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);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"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"}]

608060405234801561001057600080fd5b506128b3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806341d1de97146100465780635b6735321461008c5780639049f9d2146100bf575b600080fd5b6100636004803603602081101561005c57600080fd5b50356100f2565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610063600480360360208110156100a257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610129565b610063600480360360208110156100d557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610151565b6001818154811061010257600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60006020819052908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b600073ffffffffffffffffffffffffffffffffffffffff82166101d557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f414e54453a205465737420616464726573732069732030000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260208190526040902054161561026957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f414e54453a20506f6f6c20616c72656164792063726561746564000000000000604482015290519081900360640190fd5b604051829060009061027d60208201610431565b6020820181038252601f19601f820116604052509050600084604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b8152601401915050604051602081830303815290604052805190602001209050808251602084016000f573ffffffffffffffffffffffffffffffffffffffff80871660009081526020819052604080822080548486167fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092556001805480820182559085527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180549091168217905581517fc4d66de8000000000000000000000000000000000000000000000000000000008152938816600485015290519397509263c4d66de892602480820193929182900301818387803b1580156103c357600080fd5b505af11580156103d7573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8881168252915191891693507f9089922f2c4f21a3c7a22f49fcbb52a2ca5e4d35171966522b2fe11af173364b925081900360200190a2505050919050565b61243f8061043f8339019056fe60806040526001805460ff60a01b1916600160a01b1790556008805460ff1916905534801561002d57600080fd5b50600180546001600160a01b03191633179055670de0b6b3a7640000600e819055601255436019556123db806100646000396000f3fe6080604052600436106102a05760003560e01c8063674b78441161016e578063a218141b116100cb578063c45a01551161007f578063e35e5d8411610064578063e35e5d8414610799578063ec7bb87c146107ae578063f39375ad146107c3576102a0565b8063c45a015514610744578063c4d66de814610759576102a0565b8063b6be0090116100b0578063b6be0090146106da578063bed9d8611461071a578063c31678e21461072f576102a0565b8063a218141b1461067d578063a87a8c2c14610692576102a0565b80637fab9e461161012257806392c7a64e1161010757806392c7a64e146105c357806393c00b42146106035780639ebea88c1461064b576102a0565b80637fab9e461461057b578063883d50361461059a576102a0565b8063703ec8c411610153578063703ec8c4146105075780637bb4d0a71461053a5780637fa76e431461054f576102a0565b8063674b7844146104b25780636a7b6506146104c7576102a0565b80632fde80e51161021c5780634e71d92d116101d0578063607c94f0116101b5578063607c94f01461047357806361037ff9146104885780636615bbf01461049d576102a0565b80634e71d92d146104475780635c0dd7761461045e576102a0565b806344e872201161020157806344e872201461040857806349c458831461041d5780634e54498814610432576102a0565b80632fde80e5146103de57806335fd4ce5146103f3576102a0565b80631357e1dc116102735780631e95a512116102585780631e95a512146103355780632043a1a3146103755780632b7ac3f3146103a0576102a0565b80631357e1dc1461030b578063156c2a6414610320576102a0565b806301646b06146102a55780630917e776146102cc5780630b07681c146102e157806312a1a255146102f6575b600080fd5b3480156102b157600080fd5b506102ba6107d8565b60408051918252519081900360200190f35b3480156102d857600080fd5b506102ba6107de565b3480156102ed57600080fd5b506102ba6107e5565b34801561030257600080fd5b506102ba6107eb565b34801561031757600080fd5b506102ba6107f6565b34801561032c57600080fd5b506102ba6107fc565b34801561034157600080fd5b506102ba6004803603602081101561035857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610802565b34801561038157600080fd5b5061038a610895565b6040805160ff9092168252519081900360200190f35b3480156103ac57600080fd5b506103b561089a565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156103ea57600080fd5b506102ba6108b6565b3480156103ff57600080fd5b506102ba6108bc565b34801561041457600080fd5b506102ba6108ee565b34801561042957600080fd5b506102ba6108f7565b34801561043e57600080fd5b506102ba6108fd565b34801561045357600080fd5b5061045c610903565b005b34801561046a57600080fd5b5061045c610a36565b34801561047f57600080fd5b5061045c610b4a565b34801561049457600080fd5b506102ba610d22565b3480156104a957600080fd5b506102ba610d28565b3480156104be57600080fd5b506102ba610d2e565b3480156104d357600080fd5b506102ba600480360360208110156104ea57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610d33565b34801561051357600080fd5b5061051c610d6a565b60408051938452602084019290925282820152519081900360600190f35b34801561054657600080fd5b506103b5610d76565b34801561055b57600080fd5b5061045c6004803603602081101561057257600080fd5b50351515610d92565b61045c6004803603602081101561059157600080fd5b50351515610e38565b3480156105a657600080fd5b506105af610fb8565b604080519115158252519081900360200190f35b3480156105cf57600080fd5b506102ba600480360360208110156105e657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610fd9565b34801561060f57600080fd5b506102ba6004803603604081101561062657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013515156110c6565b34801561065757600080fd5b5061045c6004803603604081101561066e57600080fd5b50803590602001351515611126565b34801561068957600080fd5b506102ba6111ba565b34801561069e57600080fd5b506102ba600480360360408110156106b557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013515156111c0565b3480156106e657600080fd5b506102ba600480360360208110156106fd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166112f1565b34801561072657600080fd5b5061045c61131c565b34801561073b57600080fd5b5061045c61144d565b34801561075057600080fd5b506103b56114c2565b34801561076557600080fd5b5061045c6004803603602081101561077c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114de565b3480156107a557600080fd5b506102ba611731565b3480156107ba57600080fd5b506102ba611738565b3480156107cf57600080fd5b5061051c61173e565b60035481565b600d545b90565b60185481565b662386f26fc1000081565b60075481565b60115490565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601760205260408120600181015461087d576040805162461bcd60e51b815260206004820152601960248201527f414e54453a206e6f7468696e6720746f20776974686472617700000000000000604482015290519081900360640190fd5b805461088c906201518061174a565b9150505b919050565b600c81565b60055473ffffffffffffffffffffffffffffffffffffffff1681565b60045481565b601854600d5460009182916108d09161174a565b90506108e860646108e28360056117a4565b906117fd565b91505090565b64174876e80081565b60065481565b60145490565b60015474010000000000000000000000000000000000000000900460ff16610972576040805162461bcd60e51b815260206004820152601960248201527f414e54453a205465737420686173206e6f74206661696c656400000000000000604482015290519081900360640190fd5b336000908152600f6020526040902080546109be5760405162461bcd60e51b81526004018080602001828103825260238152602001806122f86023913960400191505060405180910390fd5b60006109ca8233611864565b600083556006549091506109df90600161174a565b6006556007546109ef908261174a565b6007556109fc338261190d565b60408051828152905133917ff42cf8c29487b42c009006cba2a2a0ca0388229f3183e6e957e0a0b163585cb4919081900360200190a25050565b610a3e61195e565b3360009081526017602052604090206001810154610a8d5760405162461bcd60e51b81526004018080602001828103825260218152602001806121d36021913960400191505060405180910390fd5b6001810180546000909155610aa061144d565b336000908152600b60205260409020805415610ad257610acb610ac482600b6119ce565b839061174a565b8155610ae7565b818155600c54610ae390600161174a565b600c555b600d54610af4908361174a565b600d55600e546001820155601854610b0c9083611a39565b60185560408051838152905133917f62437abf8b924b1ad4fbca02f5402eb6fe6bf4ba9b844f3c1378a7507e3799a0919081900360200190a2505050565b610b5261195e565b610b5d601533611a96565b610b985760405162461bcd60e51b81526004018080602001828103825260248152602001806121af6024913960400191505060405180910390fd5b33600090815260136020526040902054600c90610bb6904390611a39565b11610bf25760405162461bcd60e51b815260040180806020018281038252603d815260200180612342603d913960400191505060405180910390fd5b600254610c0090600161174a565b6002554360045560405133907f19be9da849e19de3d0b3e9d11c9b0542b8e91a3f26d3188b8984ee8bac17fcac90600090a2610c3a611b0b565b610d2057610c4661144d565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905543600355600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055610cbb611bae565b610cc36108bc565b600955601854600d54600091610cd9919061174a565b9050610cf060095482611a3990919063ffffffff16565b600a5560405133907f9818c5a155ab582a34fec045ea885625c3d2bcb231cf25d5501f54d000ee891190600090a2505b565b60025481565b60185490565b600581565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260136020526040812054610d6490600c61174a565b92915050565b600c54600d54600e5483565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b610d9a61195e565b610da261144d565b600081610db057600b610db3565b600f5b336000908152602082905260408120919250610dcf82846119ce565b905060008111610e26576040805162461bcd60e51b815260206004820152601860248201527f414e54453a204e6f7468696e6720746f20756e7374616b650000000000000000604482015290519081900360640190fd5b610e3281858585611c6c565b50505050565b610e4061195e565b3480610e93576040805162461bcd60e51b815260206004820152601760248201527f414e54453a2043616e6e6f74207374616b65207a65726f000000000000000000604482015290519081900360640190fd5b610e9b61144d565b60008215610f0e57662386f26fc10000821015610ee95760405162461bcd60e51b815260040180806020018281038252602e815260200180612255602e913960400191505060405180910390fd5b50600f610ef7601533611daf565b336000908152601360205260409020439055610f12565b50600b5b336000908152602082905260409020805415610f4357610f3c610f3582846119ce565b849061174a565b8155610f5b565b828155600182810154610f559161174a565b60018301555b6002820154610f6a908461174a565b6002830155600382015460018201556040805184815290518515159133917f20580cc2838cc75cd2cfb9e285a0d4c24078360f4273611af79fcdff9a6a806f9181900360200190a350505050565b60015474010000000000000000000000000000000000000000900460ff1681565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f60205260408120805461103b5760405162461bcd60e51b81526004018080602001828103825260238152602001806122f86023913960400191505060405180910390fd5b60015474010000000000000000000000000000000000000000900460ff1615611070576110688184611864565b915050610890565b600061107d82600f6119ce565b905060006110896108bc565b601854600d5491925060009161109e9161174a565b90506110bb610f356110b08385611a39565b601154869190611e4d565b945050505050610890565b6000816110f85773ffffffffffffffffffffffffffffffffffffffff83166000908152600b602052604090205461111f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600f60205260409020545b9392505050565b61112e61195e565b60008211611183576040805162461bcd60e51b815260206004820152601760248201527f414e54453a2043616e6e6f7420756e7374616b6520302e000000000000000000604482015290519081900360640190fd5b61118b61144d565b60008161119957600b61119c565b600f5b336000908152602082905260409020909150610e3284848484611c6c565b60195481565b60008060006111cd611f1a565b915091506000846112025773ffffffffffffffffffffffffffffffffffffffff86166000908152600b60205260409020611228565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600f602052604090205b805490915061123d5760009350505050610d64565b60008160010154116112805760405162461bcd60e51b81526004018080602001828103825260228152602001806122336022913960400191505060405180910390fd5b600085156112aa576012546112a390670de0b6b3a7640000906108e290876117a4565b90506112d4565b600d5460006112b9828661174a565b600e549091506112cf9083906108e290846117a4565b925050505b600182015482546112e6918390611e4d565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526017602052604090206001015490565b61132461195e565b33600090815260176020526040902080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeae804201116113945760405162461bcd60e51b815260040180806020018281038252602a815260200180612283602a913960400191505060405180910390fd5b60008160010154116113ed576040805162461bcd60e51b815260206004820152601960248201527f414e54453a204e6f7468696e6720746f20776974686472617700000000000000604482015290519081900360640190fd5b60018101546018546113ff9082611a39565b60185560006001830155611413338261190d565b60408051828152905133917f141ef67c4a6d3ec2adfb2f66d33c2b11de5b4f34344757554d430570b18a92ec919081900360200190a25050565b600080611458611f1a565b4360195590925090508061146d575050610d20565b600d546011546012546114899085670de0b6b3a7640000611e4d565b6012556114968184611a39565b60115560006114a5838561174a565b600e549091506114b6908285611e4d565b600e55600d5550505050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60085460ff1615611536576040805162461bcd60e51b815260206004820152601e60248201527f414e54453a20506f6f6c20616c726561647920696e697469616c697a65640000604482015290519081900360640190fd5b60015473ffffffffffffffffffffffffffffffffffffffff16331461158c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806122ce602a913960400191505060405180910390fd5b6115ab8173ffffffffffffffffffffffffffffffffffffffff16611ff4565b6115e65760405162461bcd60e51b815260040180806020018281038252602781526020018061237f6027913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561162e57600080fd5b505af1158015611642573d6000803e3d6000fd5b505050506040513d602081101561165857600080fd5b50516116955760405162461bcd60e51b815260040180806020018281038252603f8152602001806121f4603f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6201518081565b60145481565b60105460115460125483565b60008282018381101561111f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000826117b357506000610d64565b828202828482816117c057fe5b041461111f5760405162461bcd60e51b81526004018080602001828103825260218152602001806122ad6021913960400191505060405180910390fd5b6000808211611853576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161185c57fe5b049392505050565b60008061187284600f6119ce565b60035490915061188390600c611a39565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604090205410156118cf57600a546014546118cc916118c591849190611e4d565b829061174a565b90505b60055473ffffffffffffffffffffffffffffffffffffffff8481169116146118f75780611905565b60095461190590829061174a565b949350505050565b8173ffffffffffffffffffffffffffffffffffffffff166108fc6119318347611ffa565b6040518115909202916000818181858888f19350505050158015611959573d6000803e3d6000fd5b505050565b60015474010000000000000000000000000000000000000000900460ff1615610d20576040805162461bcd60e51b815260206004820152601a60248201527f414e54453a205465737420616c7265616479206661696c65642e000000000000604482015290519081900360640190fd5b81546000906119df57506000610d64565b6000836001015411611a225760405162461bcd60e51b81526004018080602001828103825260228152602001806122336022913960400191505060405180910390fd5b60038201546001840154845461111f929091611e4d565b600082821115611a90576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001820154600090611aaa57506000610d64565b73ffffffffffffffffffffffffffffffffffffffff82166000818152602085905260409020546001850180549091908110611ae157fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16149392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b7657600080fd5b505af1925050508015611b9b57506040513d6020811015611b9657600080fd5b505160015b611ba7575060006107e2565b90506107e2565b600354600090611bbf90600c611a39565b905060005b601654811015611c6857600060156001018281548110611be057fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083526013909152604090912054909150831115611c5f5773ffffffffffffffffffffffffffffffffffffffff81166000908152600f60208190526040909120611c5b91611c5291906119ce565b6014549061174a565b6014555b50600101611bc4565b5050565b6000611c7882846119ce565b905084811415611cb857600080835560018084019190915583810154611c9d91611a39565b60018401558315611cb357611cb3601533612010565b611d0e565b80851115611cf75760405162461bcd60e51b815260040180806020018281038252602781526020018061231b6027913960400191505060405180910390fd5b611d018186611a39565b8255600383015460018301555b6002830154611d1d9086611a39565b60028401558315611d3757611d32338661190d565b611d6f565b3360009081526017602052604090204281556001810154611d58908761174a565b6001820155601854611d6a908761174a565b601855505b6040805186815290518515159133917f2dad9020fc3cab73927d1f0192936d8dcbceac42333d75509d99c2c941339ccf9181900360200190a35050505050565b611db98282611a96565b611c68576001828101805491820181556000818152602080822090930180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff959095169485179055905492815292905260409091207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019055565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870986860292508281109083900303905080611ea15760008411611e9657600080fd5b50829004905061111f565b808411611ead57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b601954670de0b6b3a7640000906000904311611f3557611ff0565b60015474010000000000000000000000000000000000000000900460ff1615611f5d57611ff0565b600d54601154811580611f6e575080155b15611f7a575050611ff0565b6000611f9160195443611a3990919063ffffffff16565b90506000611fa464174876e800836117a4565b9050670de0b6b3a76400008110611fc15760009550829450611feb565b611fd3670de0b6b3a764000082611a39565b9550611fe88382670de0b6b3a7640000611e4d565b94505b505050505b9091565b3b151590565b6000818310612009578161111f565b5090919050565b61201a8282611a96565b61202357611c68565b600182015473ffffffffffffffffffffffffffffffffffffffff82166000908152602084905260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019080821461211d57600084600101838154811061208b57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083529087905260409091208390556001860180549192508291849081106120d357fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b73ffffffffffffffffffffffffffffffffffffffff83166000908152602085905260408120556001840180548061215057fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555050505056fe414e54453a204f6e6c79206368616c6c656e676572732063616e20636865636b54657374414e54453a204e6f2070656e64696e672077697468647261772062616c616e6365414e54453a20416e74655465737420646f6573206e6f7420696d706c656d656e7420636865636b54657374506173736573206f722074657374206661696c73414e54453a20496e76616c696420737461727444656361794d756c7469706c696572414e54453a204368616c6c656e676572206d757374207374616b65206d6f7265207468616e20302e303120455448414e54453a206d757374207761697420323420686f75727320746f207769746864726177207374616b65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77414e54453a206f6e6c7920666163746f72792063616e20696e697469616c697a6520416e7465506f6f6c414e54453a204e6f204368616c6c656e676572205374616b696e672062616c616e6365414e54453a205769746864726177207265717565737420657863656564732062616c616e63652e414e54453a206d757374207761697420313220626c6f636b73206166746572206368616c6c656e67696e6720746f2063616c6c20636865636b54657374414e54453a20416e746554657374206d757374206265206120736d61727420636f6e7472616374a26469706673582212208a68b95ae628a7624f9f5dd2dc1e8ff5dc8e22bab4d2491bc71f57fd4df21b4164736f6c63430007060033a2646970667358221220d7ca7ec2141d8ac5cf9d6f31f8ac62228d4ec950f8547aef94bab89d4e4b6d6f64736f6c63430007060033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100415760003560e01c806341d1de97146100465780635b6735321461008c5780639049f9d2146100bf575b600080fd5b6100636004803603602081101561005c57600080fd5b50356100f2565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610063600480360360208110156100a257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610129565b610063600480360360208110156100d557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610151565b6001818154811061010257600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60006020819052908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b600073ffffffffffffffffffffffffffffffffffffffff82166101d557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f414e54453a205465737420616464726573732069732030000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260208190526040902054161561026957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f414e54453a20506f6f6c20616c72656164792063726561746564000000000000604482015290519081900360640190fd5b604051829060009061027d60208201610431565b6020820181038252601f19601f820116604052509050600084604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b8152601401915050604051602081830303815290604052805190602001209050808251602084016000f573ffffffffffffffffffffffffffffffffffffffff80871660009081526020819052604080822080548486167fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092556001805480820182559085527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180549091168217905581517fc4d66de8000000000000000000000000000000000000000000000000000000008152938816600485015290519397509263c4d66de892602480820193929182900301818387803b1580156103c357600080fd5b505af11580156103d7573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8881168252915191891693507f9089922f2c4f21a3c7a22f49fcbb52a2ca5e4d35171966522b2fe11af173364b925081900360200190a2505050919050565b61243f8061043f8339019056fe60806040526001805460ff60a01b1916600160a01b1790556008805460ff1916905534801561002d57600080fd5b50600180546001600160a01b03191633179055670de0b6b3a7640000600e819055601255436019556123db806100646000396000f3fe6080604052600436106102a05760003560e01c8063674b78441161016e578063a218141b116100cb578063c45a01551161007f578063e35e5d8411610064578063e35e5d8414610799578063ec7bb87c146107ae578063f39375ad146107c3576102a0565b8063c45a015514610744578063c4d66de814610759576102a0565b8063b6be0090116100b0578063b6be0090146106da578063bed9d8611461071a578063c31678e21461072f576102a0565b8063a218141b1461067d578063a87a8c2c14610692576102a0565b80637fab9e461161012257806392c7a64e1161010757806392c7a64e146105c357806393c00b42146106035780639ebea88c1461064b576102a0565b80637fab9e461461057b578063883d50361461059a576102a0565b8063703ec8c411610153578063703ec8c4146105075780637bb4d0a71461053a5780637fa76e431461054f576102a0565b8063674b7844146104b25780636a7b6506146104c7576102a0565b80632fde80e51161021c5780634e71d92d116101d0578063607c94f0116101b5578063607c94f01461047357806361037ff9146104885780636615bbf01461049d576102a0565b80634e71d92d146104475780635c0dd7761461045e576102a0565b806344e872201161020157806344e872201461040857806349c458831461041d5780634e54498814610432576102a0565b80632fde80e5146103de57806335fd4ce5146103f3576102a0565b80631357e1dc116102735780631e95a512116102585780631e95a512146103355780632043a1a3146103755780632b7ac3f3146103a0576102a0565b80631357e1dc1461030b578063156c2a6414610320576102a0565b806301646b06146102a55780630917e776146102cc5780630b07681c146102e157806312a1a255146102f6575b600080fd5b3480156102b157600080fd5b506102ba6107d8565b60408051918252519081900360200190f35b3480156102d857600080fd5b506102ba6107de565b3480156102ed57600080fd5b506102ba6107e5565b34801561030257600080fd5b506102ba6107eb565b34801561031757600080fd5b506102ba6107f6565b34801561032c57600080fd5b506102ba6107fc565b34801561034157600080fd5b506102ba6004803603602081101561035857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610802565b34801561038157600080fd5b5061038a610895565b6040805160ff9092168252519081900360200190f35b3480156103ac57600080fd5b506103b561089a565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156103ea57600080fd5b506102ba6108b6565b3480156103ff57600080fd5b506102ba6108bc565b34801561041457600080fd5b506102ba6108ee565b34801561042957600080fd5b506102ba6108f7565b34801561043e57600080fd5b506102ba6108fd565b34801561045357600080fd5b5061045c610903565b005b34801561046a57600080fd5b5061045c610a36565b34801561047f57600080fd5b5061045c610b4a565b34801561049457600080fd5b506102ba610d22565b3480156104a957600080fd5b506102ba610d28565b3480156104be57600080fd5b506102ba610d2e565b3480156104d357600080fd5b506102ba600480360360208110156104ea57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610d33565b34801561051357600080fd5b5061051c610d6a565b60408051938452602084019290925282820152519081900360600190f35b34801561054657600080fd5b506103b5610d76565b34801561055b57600080fd5b5061045c6004803603602081101561057257600080fd5b50351515610d92565b61045c6004803603602081101561059157600080fd5b50351515610e38565b3480156105a657600080fd5b506105af610fb8565b604080519115158252519081900360200190f35b3480156105cf57600080fd5b506102ba600480360360208110156105e657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610fd9565b34801561060f57600080fd5b506102ba6004803603604081101561062657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013515156110c6565b34801561065757600080fd5b5061045c6004803603604081101561066e57600080fd5b50803590602001351515611126565b34801561068957600080fd5b506102ba6111ba565b34801561069e57600080fd5b506102ba600480360360408110156106b557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013515156111c0565b3480156106e657600080fd5b506102ba600480360360208110156106fd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166112f1565b34801561072657600080fd5b5061045c61131c565b34801561073b57600080fd5b5061045c61144d565b34801561075057600080fd5b506103b56114c2565b34801561076557600080fd5b5061045c6004803603602081101561077c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114de565b3480156107a557600080fd5b506102ba611731565b3480156107ba57600080fd5b506102ba611738565b3480156107cf57600080fd5b5061051c61173e565b60035481565b600d545b90565b60185481565b662386f26fc1000081565b60075481565b60115490565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601760205260408120600181015461087d576040805162461bcd60e51b815260206004820152601960248201527f414e54453a206e6f7468696e6720746f20776974686472617700000000000000604482015290519081900360640190fd5b805461088c906201518061174a565b9150505b919050565b600c81565b60055473ffffffffffffffffffffffffffffffffffffffff1681565b60045481565b601854600d5460009182916108d09161174a565b90506108e860646108e28360056117a4565b906117fd565b91505090565b64174876e80081565b60065481565b60145490565b60015474010000000000000000000000000000000000000000900460ff16610972576040805162461bcd60e51b815260206004820152601960248201527f414e54453a205465737420686173206e6f74206661696c656400000000000000604482015290519081900360640190fd5b336000908152600f6020526040902080546109be5760405162461bcd60e51b81526004018080602001828103825260238152602001806122f86023913960400191505060405180910390fd5b60006109ca8233611864565b600083556006549091506109df90600161174a565b6006556007546109ef908261174a565b6007556109fc338261190d565b60408051828152905133917ff42cf8c29487b42c009006cba2a2a0ca0388229f3183e6e957e0a0b163585cb4919081900360200190a25050565b610a3e61195e565b3360009081526017602052604090206001810154610a8d5760405162461bcd60e51b81526004018080602001828103825260218152602001806121d36021913960400191505060405180910390fd5b6001810180546000909155610aa061144d565b336000908152600b60205260409020805415610ad257610acb610ac482600b6119ce565b839061174a565b8155610ae7565b818155600c54610ae390600161174a565b600c555b600d54610af4908361174a565b600d55600e546001820155601854610b0c9083611a39565b60185560408051838152905133917f62437abf8b924b1ad4fbca02f5402eb6fe6bf4ba9b844f3c1378a7507e3799a0919081900360200190a2505050565b610b5261195e565b610b5d601533611a96565b610b985760405162461bcd60e51b81526004018080602001828103825260248152602001806121af6024913960400191505060405180910390fd5b33600090815260136020526040902054600c90610bb6904390611a39565b11610bf25760405162461bcd60e51b815260040180806020018281038252603d815260200180612342603d913960400191505060405180910390fd5b600254610c0090600161174a565b6002554360045560405133907f19be9da849e19de3d0b3e9d11c9b0542b8e91a3f26d3188b8984ee8bac17fcac90600090a2610c3a611b0b565b610d2057610c4661144d565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905543600355600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055610cbb611bae565b610cc36108bc565b600955601854600d54600091610cd9919061174a565b9050610cf060095482611a3990919063ffffffff16565b600a5560405133907f9818c5a155ab582a34fec045ea885625c3d2bcb231cf25d5501f54d000ee891190600090a2505b565b60025481565b60185490565b600581565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260136020526040812054610d6490600c61174a565b92915050565b600c54600d54600e5483565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b610d9a61195e565b610da261144d565b600081610db057600b610db3565b600f5b336000908152602082905260408120919250610dcf82846119ce565b905060008111610e26576040805162461bcd60e51b815260206004820152601860248201527f414e54453a204e6f7468696e6720746f20756e7374616b650000000000000000604482015290519081900360640190fd5b610e3281858585611c6c565b50505050565b610e4061195e565b3480610e93576040805162461bcd60e51b815260206004820152601760248201527f414e54453a2043616e6e6f74207374616b65207a65726f000000000000000000604482015290519081900360640190fd5b610e9b61144d565b60008215610f0e57662386f26fc10000821015610ee95760405162461bcd60e51b815260040180806020018281038252602e815260200180612255602e913960400191505060405180910390fd5b50600f610ef7601533611daf565b336000908152601360205260409020439055610f12565b50600b5b336000908152602082905260409020805415610f4357610f3c610f3582846119ce565b849061174a565b8155610f5b565b828155600182810154610f559161174a565b60018301555b6002820154610f6a908461174a565b6002830155600382015460018201556040805184815290518515159133917f20580cc2838cc75cd2cfb9e285a0d4c24078360f4273611af79fcdff9a6a806f9181900360200190a350505050565b60015474010000000000000000000000000000000000000000900460ff1681565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600f60205260408120805461103b5760405162461bcd60e51b81526004018080602001828103825260238152602001806122f86023913960400191505060405180910390fd5b60015474010000000000000000000000000000000000000000900460ff1615611070576110688184611864565b915050610890565b600061107d82600f6119ce565b905060006110896108bc565b601854600d5491925060009161109e9161174a565b90506110bb610f356110b08385611a39565b601154869190611e4d565b945050505050610890565b6000816110f85773ffffffffffffffffffffffffffffffffffffffff83166000908152600b602052604090205461111f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600f60205260409020545b9392505050565b61112e61195e565b60008211611183576040805162461bcd60e51b815260206004820152601760248201527f414e54453a2043616e6e6f7420756e7374616b6520302e000000000000000000604482015290519081900360640190fd5b61118b61144d565b60008161119957600b61119c565b600f5b336000908152602082905260409020909150610e3284848484611c6c565b60195481565b60008060006111cd611f1a565b915091506000846112025773ffffffffffffffffffffffffffffffffffffffff86166000908152600b60205260409020611228565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600f602052604090205b805490915061123d5760009350505050610d64565b60008160010154116112805760405162461bcd60e51b81526004018080602001828103825260228152602001806122336022913960400191505060405180910390fd5b600085156112aa576012546112a390670de0b6b3a7640000906108e290876117a4565b90506112d4565b600d5460006112b9828661174a565b600e549091506112cf9083906108e290846117a4565b925050505b600182015482546112e6918390611e4d565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526017602052604090206001015490565b61132461195e565b33600090815260176020526040902080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeae804201116113945760405162461bcd60e51b815260040180806020018281038252602a815260200180612283602a913960400191505060405180910390fd5b60008160010154116113ed576040805162461bcd60e51b815260206004820152601960248201527f414e54453a204e6f7468696e6720746f20776974686472617700000000000000604482015290519081900360640190fd5b60018101546018546113ff9082611a39565b60185560006001830155611413338261190d565b60408051828152905133917f141ef67c4a6d3ec2adfb2f66d33c2b11de5b4f34344757554d430570b18a92ec919081900360200190a25050565b600080611458611f1a565b4360195590925090508061146d575050610d20565b600d546011546012546114899085670de0b6b3a7640000611e4d565b6012556114968184611a39565b60115560006114a5838561174a565b600e549091506114b6908285611e4d565b600e55600d5550505050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60085460ff1615611536576040805162461bcd60e51b815260206004820152601e60248201527f414e54453a20506f6f6c20616c726561647920696e697469616c697a65640000604482015290519081900360640190fd5b60015473ffffffffffffffffffffffffffffffffffffffff16331461158c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806122ce602a913960400191505060405180910390fd5b6115ab8173ffffffffffffffffffffffffffffffffffffffff16611ff4565b6115e65760405162461bcd60e51b815260040180806020018281038252602781526020018061237f6027913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561162e57600080fd5b505af1158015611642573d6000803e3d6000fd5b505050506040513d602081101561165857600080fd5b50516116955760405162461bcd60e51b815260040180806020018281038252603f8152602001806121f4603f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6201518081565b60145481565b60105460115460125483565b60008282018381101561111f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000826117b357506000610d64565b828202828482816117c057fe5b041461111f5760405162461bcd60e51b81526004018080602001828103825260218152602001806122ad6021913960400191505060405180910390fd5b6000808211611853576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161185c57fe5b049392505050565b60008061187284600f6119ce565b60035490915061188390600c611a39565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604090205410156118cf57600a546014546118cc916118c591849190611e4d565b829061174a565b90505b60055473ffffffffffffffffffffffffffffffffffffffff8481169116146118f75780611905565b60095461190590829061174a565b949350505050565b8173ffffffffffffffffffffffffffffffffffffffff166108fc6119318347611ffa565b6040518115909202916000818181858888f19350505050158015611959573d6000803e3d6000fd5b505050565b60015474010000000000000000000000000000000000000000900460ff1615610d20576040805162461bcd60e51b815260206004820152601a60248201527f414e54453a205465737420616c7265616479206661696c65642e000000000000604482015290519081900360640190fd5b81546000906119df57506000610d64565b6000836001015411611a225760405162461bcd60e51b81526004018080602001828103825260228152602001806122336022913960400191505060405180910390fd5b60038201546001840154845461111f929091611e4d565b600082821115611a90576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001820154600090611aaa57506000610d64565b73ffffffffffffffffffffffffffffffffffffffff82166000818152602085905260409020546001850180549091908110611ae157fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16149392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b7657600080fd5b505af1925050508015611b9b57506040513d6020811015611b9657600080fd5b505160015b611ba7575060006107e2565b90506107e2565b600354600090611bbf90600c611a39565b905060005b601654811015611c6857600060156001018281548110611be057fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083526013909152604090912054909150831115611c5f5773ffffffffffffffffffffffffffffffffffffffff81166000908152600f60208190526040909120611c5b91611c5291906119ce565b6014549061174a565b6014555b50600101611bc4565b5050565b6000611c7882846119ce565b905084811415611cb857600080835560018084019190915583810154611c9d91611a39565b60018401558315611cb357611cb3601533612010565b611d0e565b80851115611cf75760405162461bcd60e51b815260040180806020018281038252602781526020018061231b6027913960400191505060405180910390fd5b611d018186611a39565b8255600383015460018301555b6002830154611d1d9086611a39565b60028401558315611d3757611d32338661190d565b611d6f565b3360009081526017602052604090204281556001810154611d58908761174a565b6001820155601854611d6a908761174a565b601855505b6040805186815290518515159133917f2dad9020fc3cab73927d1f0192936d8dcbceac42333d75509d99c2c941339ccf9181900360200190a35050505050565b611db98282611a96565b611c68576001828101805491820181556000818152602080822090930180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff959095169485179055905492815292905260409091207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019055565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870986860292508281109083900303905080611ea15760008411611e9657600080fd5b50829004905061111f565b808411611ead57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b601954670de0b6b3a7640000906000904311611f3557611ff0565b60015474010000000000000000000000000000000000000000900460ff1615611f5d57611ff0565b600d54601154811580611f6e575080155b15611f7a575050611ff0565b6000611f9160195443611a3990919063ffffffff16565b90506000611fa464174876e800836117a4565b9050670de0b6b3a76400008110611fc15760009550829450611feb565b611fd3670de0b6b3a764000082611a39565b9550611fe88382670de0b6b3a7640000611e4d565b94505b505050505b9091565b3b151590565b6000818310612009578161111f565b5090919050565b61201a8282611a96565b61202357611c68565b600182015473ffffffffffffffffffffffffffffffffffffffff82166000908152602084905260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019080821461211d57600084600101838154811061208b57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083529087905260409091208390556001860180549192508291849081106120d357fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b73ffffffffffffffffffffffffffffffffffffffff83166000908152602085905260408120556001840180548061215057fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555050505056fe414e54453a204f6e6c79206368616c6c656e676572732063616e20636865636b54657374414e54453a204e6f2070656e64696e672077697468647261772062616c616e6365414e54453a20416e74655465737420646f6573206e6f7420696d706c656d656e7420636865636b54657374506173736573206f722074657374206661696c73414e54453a20496e76616c696420737461727444656361794d756c7469706c696572414e54453a204368616c6c656e676572206d757374207374616b65206d6f7265207468616e20302e303120455448414e54453a206d757374207761697420323420686f75727320746f207769746864726177207374616b65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77414e54453a206f6e6c7920666163746f72792063616e20696e697469616c697a6520416e7465506f6f6c414e54453a204e6f204368616c6c656e676572205374616b696e672062616c616e6365414e54453a205769746864726177207265717565737420657863656564732062616c616e63652e414e54453a206d757374207761697420313220626c6f636b73206166746572206368616c6c656e67696e6720746f2063616c6c20636865636b54657374414e54453a20416e746554657374206d757374206265206120736d61727420636f6e7472616374a26469706673582212208a68b95ae628a7624f9f5dd2dc1e8ff5dc8e22bab4d2491bc71f57fd4df21b4164736f6c63430007060033a2646970667358221220d7ca7ec2141d8ac5cf9d6f31f8ac62228d4ec950f8547aef94bab89d4e4b6d6f64736f6c63430007060033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.