ETH Price: $3,418.79 (-1.76%)

Contract

0x1A53b3500216D547186C833c35F39a82053B7223

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Sponsored

Transaction Hash
Method
Block
From
To
Create Pool725316312023-03-22 16:53:40483 days ago1679504020IN
0x1A53b350...2053B7223
0 ETH0.000129110.1
Create Pool725315622023-03-22 16:53:23483 days ago1679504003IN
0x1A53b350...2053B7223
0 ETH0.000129110.1
Create Pool725314292023-03-22 16:52:49483 days ago1679503969IN
0x1A53b350...2053B7223
0 ETH0.000129110.1
Create Pool725254312023-03-22 16:28:14483 days ago1679502494IN
0x1A53b350...2053B7223
0 ETH0.000127370.1
Create Pool725253002023-03-22 16:27:41483 days ago1679502461IN
0x1A53b350...2053B7223
0 ETH0.000127590.1
Create Pool725228702023-03-22 16:17:35483 days ago1679501855IN
0x1A53b350...2053B7223
0 ETH0.000133080.1
Create Pool725226392023-03-22 16:16:37483 days ago1679501797IN
0x1A53b350...2053B7223
0 ETH0.000137830.1
Create Pool725167542023-03-22 15:52:33483 days ago1679500353IN
0x1A53b350...2053B7223
0 ETH0.000138820.1
Create Pool725044432023-03-22 15:01:56483 days ago1679497316IN
0x1A53b350...2053B7223
0 ETH0.000123370.1
Create Pool724977192023-03-22 14:34:25483 days ago1679495665IN
0x1A53b350...2053B7223
0 ETH0.000120370.1
0x60806040724350652023-03-22 10:17:05483 days ago1679480225IN
 Create: AntePoolFactory
0 ETH0.000678590.1

Latest 10 internal transactions

Parent Transaction Hash Block From To
725316312023-03-22 16:53:40483 days ago1679504020
0x1A53b350...2053B7223
 Contract Creation0 ETH
725315622023-03-22 16:53:23483 days ago1679504003
0x1A53b350...2053B7223
 Contract Creation0 ETH
725314292023-03-22 16:52:49483 days ago1679503969
0x1A53b350...2053B7223
 Contract Creation0 ETH
725254312023-03-22 16:28:14483 days ago1679502494
0x1A53b350...2053B7223
 Contract Creation0 ETH
725253002023-03-22 16:27:41483 days ago1679502461
0x1A53b350...2053B7223
 Contract Creation0 ETH
725228702023-03-22 16:17:35483 days ago1679501855
0x1A53b350...2053B7223
 Contract Creation0 ETH
725226392023-03-22 16:16:37483 days ago1679501797
0x1A53b350...2053B7223
 Contract Creation0 ETH
725167542023-03-22 15:52:33483 days ago1679500353
0x1A53b350...2053B7223
 Contract Creation0 ETH
725044432023-03-22 15:01:56483 days ago1679497316
0x1A53b350...2053B7223
 Contract Creation0 ETH
724977192023-03-22 14:34:25483 days ago1679495665
0x1A53b350...2053B7223
 Contract Creation0 ETH

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AntePoolFactory

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion
File 1 of 11 : AntePoolFactory.sol
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// β”—β”› ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity ^0.8.0;

import "./AntePool.sol";
import "./interfaces/IAnteTest.sol";
import "./interfaces/IAntePool.sol";
import "./interfaces/IAntePoolFactory.sol";
import "./interfaces/IAntePoolFactoryController.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

/// @title Ante V0.6 Ante Pool Factory smart contract
/// @notice Contract that creates an AntePool wrapper for an AnteTest
contract AntePoolFactory is IAntePoolFactory, ReentrancyGuard {
    struct TestStateInfo {
        bool hasFailed;
        address verifier;
        uint256 failedBlock;
        uint256 failedTimestamp;
    }

    mapping(address => TestStateInfo) private stateByTest;

    // Stores all the pools associated with a test
    mapping(address => address[]) public poolsByTest;
    /// @inheritdoc IAntePoolFactory
    mapping(bytes32 => address) public override poolByConfig;
    /// @inheritdoc IAntePoolFactory
    address[] public override allPools;

    /// @dev The maximum number of pools allowed to be created for an Ante Test
    uint256 public constant MAX_POOLS_PER_TEST = 10;

    /// @inheritdoc IAntePoolFactory
    IAntePoolFactoryController public override controller;

    /// @param _controller The address of the Ante Factory Controller
    constructor(address _controller) {
        controller = IAntePoolFactoryController(_controller);
    }

    /// @inheritdoc IAntePoolFactory
    function createPool(
        address testAddr,
        address tokenAddr,
        uint256 payoutRatio,
        uint256 decayRate,
        uint256 authorRewardRate
    ) 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(!stateByTest[testAddr].hasFailed, "ANTE: Test has previously failed");
        require(controller.isTokenAllowed(tokenAddr), "ANTE: Token not allowed");
        require(poolsByTest[testAddr].length < MAX_POOLS_PER_TEST, "ANTE: Max pools per test reached");

        uint256 tokenMinimum = controller.getTokenMinimum(tokenAddr);
        bytes32 configHash = keccak256(
            abi.encodePacked(testAddr, tokenAddr, tokenMinimum, payoutRatio, decayRate, authorRewardRate)
        );
        address poolAddr = poolByConfig[configHash];
        require(poolAddr == address(0), "ANTE: Pool with the same config already exists");

        IAnteTest anteTest = IAnteTest(testAddr);

        testPool = address(new AntePool{salt: configHash}(controller.antePoolLogicAddr()));

        require(testPool != address(0), "ANTE: Pool creation failed");

        poolsByTest[testAddr].push(testPool);
        poolByConfig[configHash] = testPool;
        allPools.push(testPool);

        IAntePool(testPool).initialize(
            anteTest,
            IERC20(tokenAddr),
            tokenMinimum,
            decayRate,
            payoutRatio,
            authorRewardRate
        );

        emit AntePoolCreated(
            testAddr,
            tokenAddr,
            tokenMinimum,
            payoutRatio,
            decayRate,
            authorRewardRate,
            testPool,
            msg.sender
        );
    }

    /// @inheritdoc IAntePoolFactory
    function hasTestFailed(address testAddr) external view override returns (bool) {
        return stateByTest[testAddr].hasFailed;
    }

    /// @inheritdoc IAntePoolFactory
    function checkTestWithState(
        bytes memory _testState,
        address verifier,
        bytes32 poolConfig
    ) public override nonReentrant {
        address poolAddr = poolByConfig[poolConfig];
        require(poolAddr == msg.sender, "ANTE: Must be called by a pool");

        IAntePool pool = IAntePool(msg.sender);
        (, , uint256 claimableShares, ) = pool.getChallengerInfo(verifier);
        require(claimableShares > 0, "ANTE: Only confirmed challengers can checkTest");
        require(
            pool.getCheckTestAllowedBlock(verifier) < block.number,
            "ANTE: must wait 255 blocks after challenging to call checkTest"
        );
        IAnteTest anteTest = pool.anteTest();
        bool hasFailed = stateByTest[address(anteTest)].hasFailed;
        require(!hasFailed, "ANTE: Test already failed.");

        pool.updateVerifiedState(verifier);
        if (!_checkTestNoRevert(anteTest, _testState)) {
            _setFailureStateForTest(address(anteTest), verifier);
        }
    }

    /// @inheritdoc IAntePoolFactory
    function getPoolsByTest(address testAddr) external view override returns (address[] memory) {
        return poolsByTest[testAddr];
    }

    /// @inheritdoc IAntePoolFactory
    function getNumPoolsByTest(address testAddr) external view override returns (uint256) {
        return poolsByTest[testAddr].length;
    }

    /// @inheritdoc IAntePoolFactory
    function numPools() external view override returns (uint256) {
        return allPools.length;
    }

    /*****************************************************
     * =============== INTERNAL HELPERS ================ *
     *****************************************************/

    /// @notice Checks the connected Ante Test, also returns true if
    /// setStateAndCheckTestPasses or checkTestPasses reverts
    /// @return passes bool if the Ante Test passed
    function _checkTestNoRevert(IAnteTest anteTest, bytes memory _testState) internal returns (bool) {
        // This condition replicates the logic from AnteTest(v0.6).setStateAndCheckTestPasses
        // It is used for backward compatibility with v0.5 tests
        if (_testState.length > 0) {
            try anteTest.setStateAndCheckTestPasses(_testState) returns (bool passes) {
                return passes;
            } catch {
                return true;
            }
        }

        try anteTest.checkTestPasses() returns (bool passes) {
            return passes;
        } catch {
            return true;
        }
    }

    function _setFailureStateForTest(address testAddr, address verifier) internal {
        TestStateInfo storage testState = stateByTest[testAddr];
        testState.hasFailed = true;
        testState.failedBlock = block.number;
        testState.failedTimestamp = block.timestamp;
        testState.verifier = verifier;

        address[] memory pools = poolsByTest[testAddr];
        uint256 numPoolsByTest = pools.length;
        for (uint256 i = 0; i < numPoolsByTest; i++) {
            try IAntePool(pools[i]).updateFailureState(verifier) {} catch {
                emit PoolFailureReverted();
            }
        }
    }
}

File 2 of 11 : Proxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)

pragma solidity ^0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}

File 3 of 11 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 4 of 11 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 5 of 11 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 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");

        (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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 6 of 11 : AntePool.sol
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// β”—β”› ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/proxy/Proxy.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./libraries/StorageSlot.sol";

/// @title Ante V0.6 Ante Pool Proxy smart contract
contract AntePool is Proxy {
    /// @dev Storage slot with the address of the current implementation.
    /// This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1
    bytes32 internal constant _IMPLEMENTATION_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);

    /// @param _antePoolLogicAddr The address where the implementation contract is deployed
    constructor(address _antePoolLogicAddr) {
        require(Address.isContract(_antePoolLogicAddr), "ANTE: implementation is not a contract");
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = _antePoolLogicAddr;
    }

    /// @inheritdoc Proxy
    function _implementation() internal view override returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }
}

File 7 of 11 : IAntePool.sol
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// β”—β”› ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "./IAnteTest.sol";

/// @title The interface for Ante V0.6 Ante Pool
/// @notice The Ante Pool handles interactions with connected Ante Test
interface IAntePool {
    /// @notice Emitted when a user adds to the stake pool
    /// @param staker The address of user
    /// @param amount Amount being added in wei
    /// @param commitTime The minimum staking time commitment
    event Stake(address indexed staker, uint256 amount, uint256 commitTime);

    /// @notice Emitted when a user extends his stake commitment
    /// @param staker The address of user
    /// @param additionalTime The additional commitment time
    /// @param commitTime The new minimum staking time commitment
    event ExtendStake(address indexed staker, uint256 additionalTime, uint256 commitTime);

    /// @notice Emitted when a user adds to the challenge pool
    /// @param challenger The address of user
    /// @param amount Amount being added in wei
    event RegisterChallenge(address indexed challenger, uint256 amount);

    /// @notice Emitted when a challenging user confirms their challenge
    /// @param challenger The address of user
    /// @param confirmedShares The amount of shares that were confirmed in wei
    event ConfirmChallenge(address indexed challenger, uint256 confirmedShares);

    /// @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 the test author claims their reward for a test
    /// @param author The address of auther claiming their reward
    /// @param amount Amount being claimed in wei
    event RewardPaid(address indexed author, 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 emited when decay paid to stakers is updated
    /// @param decayThisUpdate total decay accrued to stakers this update
    /// @param challengerMultiplier new challenger decay multiplier
    /// @param stakerMultiplier new staker decay multiplier
    event DecayUpdated(uint256 decayThisUpdate, uint256 challengerMultiplier, uint256 stakerMultiplier);

    /// @notice emited when decay starts to accumulate
    event DecayStarted();

    /// @notice emited when decay stops being accumulated
    event DecayPaused();

    /// @notice Initializes Ante Pool with the connected Ante Test
    /// @param _anteTest The Ante Test that will be connected to the Ante Pool
    /// @param _token The ERC20 token used for transacting with the Ante Pool
    /// @param _decayRate The annualized challenger decay rate expressed as precentage (x%) of total challenge
    /// @param _payoutRatio The minimum totalStake:totalChallenge ratio allowed for the Ante Pool
    /// @param _testAuthorRewardRate The test author reward rate expressed as a percentage (x%) of the decay
    /// @dev This function requires that the Ante Test address is valid and that
    /// the invariant validation currently passes
    function initialize(
        IAnteTest _anteTest,
        IERC20 _token,
        uint256 _tokenMinimum,
        uint256 _decayRate,
        uint256 _payoutRatio,
        uint256 _testAuthorRewardRate
    ) external;

    /// @notice Cancels a withdraw action of a staker
    /// @dev This is called when a staker has initiated a withdraw stake action but
    /// then decides to cancel that withdraw
    function cancelPendingWithdraw() external;

    /// @notice Runs the verification of the invariant of the connected Ante Test
    /// without updating the state
    /// @dev Can only be called by a challenger who has challenged the Ante Test
    function checkTest() external;

    /// @notice Runs the verification of the invariant of the connected Ante Test
    /// @param _testState The encoded data required to set the test state
    /// @dev Can only be called by a challenger who has challenged the Ante Test
    function checkTestWithState(bytes memory _testState) 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 Claims the reward for an Ante Test
    /// @dev To prevent double claiming, the author reward is checked before
    /// claiming and that balance is zeroed out once the claim is done
    function claimReward() external;

    /// @notice Adds a users's stake to the staker pool
    /// @param amount Amount to stake
    /// @param commitTime Time in seconds before the stake can be unstaked again
    function stake(uint256 amount, uint256 commitTime) external;

    /// @notice Extend a staker commitment time by additional time
    /// @param additionalTime Time in seconds to add to the current commitment lock
    function extendStakeLock(uint256 additionalTime) external;

    /// @notice Registers a user's challenge to the challenger pool
    /// @dev confirmChallenge() must be called after MIN_CHALLENGER_DELAY to confirm
    /// the challenge.
    /// @param amount The amount to challenge, denominated in the ERC20 Token of the AntePool
    function registerChallenge(uint256 amount) external;

    /// @notice Confirms a challenger's previously registered challenge
    /// @dev Must be called after at least MIN_CHALLENGER_DELAY seconds to confirm
    /// the challenge.
    function confirmChallenge() external;

    /// @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 Updates the verified state of this pool when a verification is triggered
    /// @param _verifier The address of who called the test verification
    /// @dev This function is called from the AntePoolFactory to set the pool's verification state.
    function updateVerifiedState(address _verifier) external;

    /// @notice Updates the failure state of this pool after the associated ante test has failed
    /// @param _verifier The address of who called the test verification
    /// @dev This function is called from the AntePoolFactory to propagate the failure state to
    /// all linked ante pools as soon as a checkTest() call has failed on a single AntePool
    function updateFailureState(address _verifier) 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 Returns the annualized challenger decay rate expressed as a precentage (x%) of challenger pool
    /// @return The decay rate of the challenger side
    function decayRate() external view returns (uint256);

    /// @notice Returns the minimum totalStake:totalChallenge ratio allowed for the Ante Pool
    /// @return The challenger payout ratio
    function challengerPayoutRatio() external view returns (uint256);

    /// @notice Returns the test author reward rate on this Ante Pool, expressed as a percentage (x%) of the decay
    /// @return The test author reward rate
    function testAuthorRewardRate() external view returns (uint256);

    /// @notice Returns the available rewards to be claimed by the test author
    /// @return The amount of tokens available to be claimed
    function getTestAuthorReward() external view returns (uint256);

    /// @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 timestamp 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 Seconds since epoch when Ante Test failed
    function failedTimestamp() external view returns (uint256);

    /// @notice Returns info for a specific challenger
    /// @param challenger Address of challenger
    function getChallengerInfo(
        address challenger
    )
        external
        view
        returns (
            uint256 startAmount,
            uint256 lastStakedTimestamp,
            uint256 claimableShares,
            uint256 claimableSharesStartMultiplier
        );

    /// @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 timestamp for when the staker's time commitment expires
    /// @param _user Address of staker
    /// @dev This timestamp is the commitTime after the time the staker initially staked
    /// @return Timestamp for when the stake is no longer locked and can be unstaked
    function getUnstakeAllowedTime(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 a user's starting decay multiplier
    /// @param _user Address of user
    /// @param isChallenger Flag if user is a challenger
    /// @dev This value is updated as decay is calculated or additional value
    /// added to respective side
    /// @return User's starting decay multiplier
    function getUserStartDecayMultiplier(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 timestamp where decay was updated
    /// @dev This is generally updated on most actions that interact with the Ante
    /// Pool contract
    /// @return Number of seconds since epoch of when contract was last updated
    function lastUpdateTimestamp() external view returns (uint256);

    /// @notice Returns the minimum allowed challenger stake
    /// @dev Minimum challenger stake is token based and is configured in AntePoolFactoryController
    /// @return The minimum amount that a challenger can stake
    function minChallengerStake() external view returns (uint256);

    /// @notice Returns the minimum allowed support stake
    /// @dev Minimum support stake is derived from the challengerPayoutRatio and minChallengerStake
    /// @return The minimum amount that a supporter can stake
    function minSupporterStake() 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 most recent timestamp when a challenger verified test
    /// @dev This is updated whenever the verify test is activated, whether or not
    /// the Ante Test fails
    /// @return Seconds since epoch of last verification attempt
    function lastVerifiedTimestamp() 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 ERC20 token used for transacting with the pool
    /// @return IERC20 interface of the token
    function token() external view returns (IERC20);

    /// @notice Returns if the decay accumulation is active
    /// @return True if decay accumulation is active
    function isDecaying() external view returns (bool);

    /// @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);
}

File 8 of 11 : IAntePoolFactory.sol
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// β”—β”› ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity ^0.8.0;

import "../interfaces/IAntePoolFactoryController.sol";

/// @title The interface for the Ante V0.6 Ante Pool Factory
/// @notice The Ante V0.6 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 tokenAddr The address of the ERC20 Token used to stake
    /// @param tokenMinimum The minimum allowed stake amount
    /// @param payoutRatio The payout ratio of the pool
    /// @param decayRate The decay rate of the pool
    /// @param authorRewardRate The test writer reward rate
    /// @param testPool The address of the AntePool created by the factory
    /// @param poolCreator address which created the pool (msg.sender on createPool)
    event AntePoolCreated(
        address indexed testAddr,
        address tokenAddr,
        uint256 tokenMinimum,
        uint256 payoutRatio,
        uint256 decayRate,
        uint256 authorRewardRate,
        address testPool,
        address poolCreator
    );

    /// @notice Emitted when pushing the fail state to a pool reverts.
    event PoolFailureReverted();

    /// @notice Creates an AntePool for an AnteTest and returns the AntePool address
    /// @param testAddr The address of the AnteTest to create an AntePool for
    /// @param tokenAddr The address of the ERC20 Token used to stake
    /// @param payoutRatio The payout ratio of the pool
    /// @param decayRate The decay rate of the pool
    /// @param authorRewardRate The test writer reward rate
    /// @return testPool - The address of the generated AntePool
    function createPool(
        address testAddr,
        address tokenAddr,
        uint256 payoutRatio,
        uint256 decayRate,
        uint256 authorRewardRate
    ) external returns (address testPool);

    /// @notice Returns the historic failure state of a given ante test
    /// @param testAddr Address of the test to check
    function hasTestFailed(address testAddr) external view returns (bool);

    /// @notice Runs the verification of the invariant of the connected Ante Test, called by a pool
    /// @param _testState The encoded data required to set the test state
    /// @param verifier The address of who called the test verification
    /// @param poolConfig config hash of the AntePool calling the method. Used for gas effective authorization
    function checkTestWithState(bytes memory _testState, address verifier, bytes32 poolConfig) external;

    /// @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 addresses of the corresponding AntePools
    function getPoolsByTest(address testAddr) external view returns (address[] memory);

    /// @notice Returns the number of AntePools corresponding to a given AnteTest
    /// @param testAddr address of the AnteTest to look up
    /// @return The number of pools for a specified AnteTest
    function getNumPoolsByTest(address testAddr) external view returns (uint256);

    /// @notice Returns the address of the AntePool corresponding to a given config hash
    /// @param configHash config hash of the AntePool to look up
    /// @return The address of the corresponding AntePool
    function poolByConfig(bytes32 configHash) external view returns (address);

    /// @notice Returns the number of pools created by this factory
    /// @return Number of pools created.
    function numPools() external view returns (uint256);

    /// @notice Returns the Factory Controller used for whitelisting tokens
    /// @return IAntePoolFactoryController The Ante Factory Controller interface
    function controller() external view returns (IAntePoolFactoryController);
}

File 9 of 11 : IAntePoolFactoryController.sol
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// β”—β”› ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity ^0.8.0;

/// @title Ante V0.6 Ante Pool Factory Controller smart contract
/// @notice Contract that handles the whitelisted ERC20 tokens
interface IAntePoolFactoryController {
    /// @notice Emitted when a new token is added to whitelist.
    /// @param tokenAddr The ERC20 token address that was added
    /// @param min The minimum allowed stake amount expressed in the token's decimals
    event TokenAdded(address indexed tokenAddr, uint256 min);

    /// @notice Emitted when a token is removed from whitelist.
    /// @param tokenAddr The ERC20 token address that was added
    event TokenRemoved(address indexed tokenAddr);

    /// @notice Emitted when a token minimum stake is updated.
    /// @param tokenAddr The ERC20 token address that was added
    /// @param min The minimum allowed stake amount expressed in the token's decimals
    event TokenMinimumUpdated(address indexed tokenAddr, uint256 min);

    /// @notice Emitted when the ante pool implementation contract address is updated.
    /// @param oldImplAddress The address of the old implementation contract
    /// @param implAddress The address of the new implementation contract
    event AntePoolImplementationUpdated(address oldImplAddress, address implAddress);

    /// @notice Adds the provided token to the whitelist
    /// @param _tokenAddr The ERC20 token address to be added
    /// @param _min The minimum allowed stake amount expressed in the token's decimals
    function addToken(address _tokenAddr, uint256 _min) external;

    /// @notice Adds multiple tokens to the whitelist only if they do not already exist
    /// It reverts only if no token was added
    /// @param _tokenAddresses An array of ERC20 token addresses
    /// @param _mins An array of minimum allowed stake amount expressed in the token's decimals
    function addTokens(address[] memory _tokenAddresses, uint256[] memory _mins) external;

    /// @notice Removes the provided token address from the whitelist
    /// @param _tokenAddr The ERC20 token address to be removed
    function removeToken(address _tokenAddr) external;

    /// @notice Sets the address of AntePool implementation contract
    /// This is used by the factory when creating a new pool
    /// @param _antePoolLogicAddr The address of the new implementation contract
    function setPoolLogicAddr(address _antePoolLogicAddr) external;

    /// @notice Check if the provided token address exists in the whitelist
    /// @param _tokenAddr The ERC20 token address to be checked
    /// @return true if the provided token is in the whitelist
    function isTokenAllowed(address _tokenAddr) external view returns (bool);

    /// @notice Set the minimum allowed stake amount for a token in the whitelist
    /// @param _tokenAddr The ERC20 token address to be modified
    /// @param _min The minimum allowed stake amount expressed in the token's decimals
    function setTokenMinimum(address _tokenAddr, uint256 _min) external;

    /// @notice Get the minimum allowed stake amount for a token in the whitelist
    /// @param _tokenAddr The ERC20 token address to be checked
    /// @return The minimum stake amount, expressed in the token's decimals
    function getTokenMinimum(address _tokenAddr) external view returns (uint256);

    /// @notice Retrieves an array of all whitelisted tokens
    /// @return A list of ERC20 tokens that are allowed to be used by the factory.
    function getAllowedTokens() external view returns (address[] memory);

    /// @notice Returns the address of AntePool implementation contract
    /// @return Address of the AntePool implementation contract
    function antePoolLogicAddr() external view returns (address);
}

File 10 of 11 : IAnteTest.sol
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// β”—β”› ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity ^0.8.0;

/// @title The interface for the Ante V0.6 Ante Test
/// @notice The Ante V0.6 Ante Test wraps test logic for verifying fundamental invariants of a protocol
interface IAnteTest {
    /// @notice Emitted when the test author is changed
    /// @param previousAuthor The address of the previous author
    /// @param newAuthor The address of the new author
    event TestAuthorChanged(address indexed previousAuthor, address indexed newAuthor);

    /// @notice Function containing the logic to set the AnteTest state and call checkTestPasses
    /// @param _state The encoded data required to set the test state
    /// @return A single bool indicating if the Ante Test passes/fails
    function setStateAndCheckTestPasses(bytes memory _state) external returns (bool);

    /// @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);

    /// @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 Sets the author of the Ante Test
    /// @dev This can only be called by the current author, which is the deployer initially
    /// @param _testAuthor The address of the test author
    function setTestAuthor(address _testAuthor) external;

    /// @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 Returns a string of comma delimited types used for setting the AnteTest state
    /// @return The types of the state variables
    function getStateTypes() external pure returns (string memory);

    /// @notice Returns a string of comma delimited names used for setting the AnteTest state
    /// @return The names of the state variables
    function getStateNames() external pure returns (string memory);
}

File 11 of 11 : StorageSlot.sol
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// β”—β”› ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Inspired by https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/StorageSlot.sol

pragma solidity ^0.8.0;

library StorageSlot {
    struct AddressSlot {
        address value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_controller","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"testAddr","type":"address"},{"indexed":false,"internalType":"address","name":"tokenAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenMinimum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payoutRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"decayRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"authorRewardRate","type":"uint256"},{"indexed":false,"internalType":"address","name":"testPool","type":"address"},{"indexed":false,"internalType":"address","name":"poolCreator","type":"address"}],"name":"AntePoolCreated","type":"event"},{"anonymous":false,"inputs":[],"name":"PoolFailureReverted","type":"event"},{"inputs":[],"name":"MAX_POOLS_PER_TEST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPools","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_testState","type":"bytes"},{"internalType":"address","name":"verifier","type":"address"},{"internalType":"bytes32","name":"poolConfig","type":"bytes32"}],"name":"checkTestWithState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IAntePoolFactoryController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"testAddr","type":"address"},{"internalType":"address","name":"tokenAddr","type":"address"},{"internalType":"uint256","name":"payoutRatio","type":"uint256"},{"internalType":"uint256","name":"decayRate","type":"uint256"},{"internalType":"uint256","name":"authorRewardRate","type":"uint256"}],"name":"createPool","outputs":[{"internalType":"address","name":"testPool","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"testAddr","type":"address"}],"name":"getNumPoolsByTest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"testAddr","type":"address"}],"name":"getPoolsByTest","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"testAddr","type":"address"}],"name":"hasTestFailed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numPools","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"poolByConfig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolsByTest","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50604051611b30380380611b3083398101604081905261002f91610059565b6001600055600580546001600160a01b0319166001600160a01b0392909216919091179055610089565b60006020828403121561006b57600080fd5b81516001600160a01b038116811461008257600080fd5b9392505050565b611a98806100986000396000f3fe60806040523480156200001157600080fd5b5060043610620000d95760003560e01c806385ac165a116200008b57806392e48ed1116200006257806392e48ed1146200024a578063eeb9ab0d1462000253578063f77c4791146200026c57600080fd5b806385ac165a14620001cf578063910bc43414620001e6578063915b3c77146200023357600080fd5b806323ceee0911620000c057806323ceee09146200016757806335c62bc214620001af57806341d1de9714620001b857600080fd5b806305e7960a14620000de5780631ecb337f1462000141575b600080fd5b62000117620000ef366004620013b3565b60036020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001586200015236600462001405565b6200028d565b6040516200013891906200142c565b620001a06200017836600462001405565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b60405190815260200162000138565b600454620001a0565b62000117620001c9366004620013b3565b6200031f565b62000117620001e036600462001488565b62000357565b62000222620001f736600462001405565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b604051901515815260200162000138565b6200011762000244366004620014de565b62000b12565b620001a0600a81565b6200026a620002643660046200153c565b62000b58565b005b600554620001179073ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156200031357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620002e7575b50505050509050919050565b600481815481106200033057600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b600073ffffffffffffffffffffffffffffffffffffffff8616620003dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f414e54453a20546573742061646472657373206973203000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff861660009081526001602052604090205460ff16156200046e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f414e54453a2054657374206861732070726576696f75736c79206661696c65646044820152606401620003d3565b6005546040517ff9eaee0d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301529091169063f9eaee0d90602401602060405180830381865afa158015620004df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000505919062001631565b6200056d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f414e54453a20546f6b656e206e6f7420616c6c6f7765640000000000000000006044820152606401620003d3565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260026020526040902054600a11620005fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f414e54453a204d617820706f6f6c7320706572207465737420726561636865646044820152606401620003d3565b6005546040517f93bc7d1200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260009216906393bc7d1290602401602060405180830381865afa15801562000670573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000696919062001655565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608a811b8216602084015289901b16603482015260488101829052606881018790526088810186905260a8810185905290915060009060c801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600390935291205490915073ffffffffffffffffffffffffffffffffffffffff168015620007e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f414e54453a20506f6f6c2077697468207468652073616d6520636f6e6669672060448201527f616c7265616479206578697374730000000000000000000000000000000000006064820152608401620003d3565b600554604080517ff2d8aa9900000000000000000000000000000000000000000000000000000000815290518b92859273ffffffffffffffffffffffffffffffffffffffff9091169163f2d8aa99916004808201926020929091908290030181865afa15801562000855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200087b91906200166f565b6040516200088990620013a5565b73ffffffffffffffffffffffffffffffffffffffff90911681526020018190604051809103906000f5905080158015620008c7573d6000803e3d6000fd5b50945073ffffffffffffffffffffffffffffffffffffffff851662000949576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f414e54453a20506f6f6c206372656174696f6e206661696c65640000000000006044820152606401620003d3565b73ffffffffffffffffffffffffffffffffffffffff808b1660009081526002602090815260408083208054600181810183559185528385200180548b87167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811790925589865260039094528285208054851682179055600480549283018155948590527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b90910180549093168117909255517f86489ba900000000000000000000000000000000000000000000000000000000815284841692810192909252918b1660248201526044810186905260648101899052608481018a905260a481018890526386489ba99060c401600060405180830381600087803b15801562000a7457600080fd5b505af115801562000a89573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8d81168252602082018990529181018c9052606081018b9052608081018a905288821660a08201523360c0820152908d1692507fb43245c2ad6a25515dae8505f54738e2543a4dcdd83771da7a8f882bb6fd15a0915060e00160405180910390a25050505095945050505050565b6002602052816000526040600020818154811062000b2f57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b62000b6262001003565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1633811462000bf2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f414e54453a204d7573742062652063616c6c6564206279206120706f6f6c00006044820152606401620003d3565b6040517f18350f2200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152339060009082906318350f2290602401608060405180830381865afa15801562000c62573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c8891906200168f565b50925050506000811162000d1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f414e54453a204f6e6c7920636f6e6669726d6564206368616c6c656e6765727360448201527f2063616e20636865636b546573740000000000000000000000000000000000006064820152608401620003d3565b6040517f6a7b650600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152439190841690636a7b650690602401602060405180830381865afa15801562000d8f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000db5919062001655565b1062000e44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f414e54453a206d75737420776169742032353520626c6f636b7320616674657260448201527f206368616c6c656e67696e6720746f2063616c6c20636865636b5465737400006064820152608401620003d3565b60008273ffffffffffffffffffffffffffffffffffffffff16637bb4d0a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000e92573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000eb891906200166f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205490915060ff16801562000f4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f414e54453a205465737420616c7265616479206661696c65642e0000000000006044820152606401620003d3565b6040517f8dd9dc0400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152851690638dd9dc0490602401600060405180830381600087803b15801562000fb857600080fd5b505af115801562000fcd573d6000803e3d6000fd5b5050505062000fdd828962001078565b62000fee5762000fee8288620011d6565b505050505062000ffe6001600055565b505050565b60026000540362001071576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401620003d3565b6002600055565b80516000901562001149576040517f07c0dffe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906307c0dffe90620010d7908590600401620016c6565b6020604051808303816000875af192505050801562001133575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252620011309181019062001631565b60015b6200114157506001620011d0565b9050620011d0565b8273ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b81526004016020604051808303816000875af192505050801562001133575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252620011309181019062001631565b92915050565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526001602081815260408084208054438286015542600280840191909155968816610100027fffffffffffffffffffffff00000000000000000000000000000000000000000090911617909317835593815283832080548551818402810184019096528086529294929091830182828015620012a557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831162001279575b505083519394506000925050505b818110156200139d57828181518110620012d157620012d162001734565b60209081029190910101516040517fe528c94a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301529091169063e528c94a90602401600060405180830381600087803b1580156200134757600080fd5b505af192505050801562001359575060015b62001388576040517f288c43acf4ce89fe7c0c09300defaff6775ae6329e91c02f7f1714968e348ca490600090a15b80620013948162001763565b915050620012b3565b505050505050565b61029f80620017c483390190565b600060208284031215620013c657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114620013f057600080fd5b50565b80356200140081620013cd565b919050565b6000602082840312156200141857600080fd5b81356200142581620013cd565b9392505050565b6020808252825182820181905260009190848201906040850190845b818110156200147c57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010162001448565b50909695505050505050565b600080600080600060a08688031215620014a157600080fd5b8535620014ae81620013cd565b94506020860135620014c081620013cd565b94979496505050506040830135926060810135926080909101359150565b60008060408385031215620014f257600080fd5b8235620014ff81620013cd565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156200155257600080fd5b833567ffffffffffffffff808211156200156b57600080fd5b818601915086601f8301126200158057600080fd5b8135818111156200159557620015956200150d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715620015de57620015de6200150d565b81604052828152896020848701011115620015f857600080fd5b8260208601602083013760006020848301015280975050505050506200162160208501620013f3565b9150604084013590509250925092565b6000602082840312156200164457600080fd5b815180151581146200142557600080fd5b6000602082840312156200166857600080fd5b5051919050565b6000602082840312156200168257600080fd5b81516200142581620013cd565b60008060008060808587031215620016a657600080fd5b505082516020840151604085015160609095015191969095509092509050565b600060208083528351808285015260005b81811015620016f557858101830151858201604001528201620016d7565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620017bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fe608060405234801561001057600080fd5b5060405161029f38038061029f83398101604081905261002f91610118565b6100428161010660201b6100211760201c565b6100a15760405162461bcd60e51b815260206004820152602660248201527f414e54453a20696d706c656d656e746174696f6e206973206e6f74206120636f6044820152651b9d1c9858dd60d21b606482015260840160405180910390fd5b806100e26100d060017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd610148565b60001b61011560201b61003d1760201c565b80546001600160a01b0319166001600160a01b03929092169190911790555061016f565b6001600160a01b03163b151590565b90565b60006020828403121561012a57600080fd5b81516001600160a01b038116811461014157600080fd5b9392505050565b8181038181111561016957634e487b7160e01b600052601160045260246000fd5b92915050565b6101218061017e6000396000f3fe608060405236601057600e6013565b005b600e5b601f601b6040565b6089565b565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b6000606d603d60017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd60ac565b5473ffffffffffffffffffffffffffffffffffffffff16919050565b3660008037600080366000845af43d6000803e80801560a7573d6000f35b3d6000fd5b8181038181111560e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea2646970667358221220fffe7dd56380a5ce4638672ddef2f12a0a86466f94de0c90fa6ddda72fa743ee64736f6c63430008100033a2646970667358221220b9c3ec15f641721fa12d17927d27865bf235afcac259513b916214577f9101cd64736f6c6343000810003300000000000000000000000044d195661277f25597fe6b6d9f910d5bbe9821b3

Deployed Bytecode

0x60806040523480156200001157600080fd5b5060043610620000d95760003560e01c806385ac165a116200008b57806392e48ed1116200006257806392e48ed1146200024a578063eeb9ab0d1462000253578063f77c4791146200026c57600080fd5b806385ac165a14620001cf578063910bc43414620001e6578063915b3c77146200023357600080fd5b806323ceee0911620000c057806323ceee09146200016757806335c62bc214620001af57806341d1de9714620001b857600080fd5b806305e7960a14620000de5780631ecb337f1462000141575b600080fd5b62000117620000ef366004620013b3565b60036020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001586200015236600462001405565b6200028d565b6040516200013891906200142c565b620001a06200017836600462001405565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b60405190815260200162000138565b600454620001a0565b62000117620001c9366004620013b3565b6200031f565b62000117620001e036600462001488565b62000357565b62000222620001f736600462001405565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b604051901515815260200162000138565b6200011762000244366004620014de565b62000b12565b620001a0600a81565b6200026a620002643660046200153c565b62000b58565b005b600554620001179073ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156200031357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620002e7575b50505050509050919050565b600481815481106200033057600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b600073ffffffffffffffffffffffffffffffffffffffff8616620003dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f414e54453a20546573742061646472657373206973203000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff861660009081526001602052604090205460ff16156200046e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f414e54453a2054657374206861732070726576696f75736c79206661696c65646044820152606401620003d3565b6005546040517ff9eaee0d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301529091169063f9eaee0d90602401602060405180830381865afa158015620004df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000505919062001631565b6200056d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f414e54453a20546f6b656e206e6f7420616c6c6f7765640000000000000000006044820152606401620003d3565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260026020526040902054600a11620005fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f414e54453a204d617820706f6f6c7320706572207465737420726561636865646044820152606401620003d3565b6005546040517f93bc7d1200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260009216906393bc7d1290602401602060405180830381865afa15801562000670573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000696919062001655565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608a811b8216602084015289901b16603482015260488101829052606881018790526088810186905260a8810185905290915060009060c801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600390935291205490915073ffffffffffffffffffffffffffffffffffffffff168015620007e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f414e54453a20506f6f6c2077697468207468652073616d6520636f6e6669672060448201527f616c7265616479206578697374730000000000000000000000000000000000006064820152608401620003d3565b600554604080517ff2d8aa9900000000000000000000000000000000000000000000000000000000815290518b92859273ffffffffffffffffffffffffffffffffffffffff9091169163f2d8aa99916004808201926020929091908290030181865afa15801562000855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200087b91906200166f565b6040516200088990620013a5565b73ffffffffffffffffffffffffffffffffffffffff90911681526020018190604051809103906000f5905080158015620008c7573d6000803e3d6000fd5b50945073ffffffffffffffffffffffffffffffffffffffff851662000949576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f414e54453a20506f6f6c206372656174696f6e206661696c65640000000000006044820152606401620003d3565b73ffffffffffffffffffffffffffffffffffffffff808b1660009081526002602090815260408083208054600181810183559185528385200180548b87167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811790925589865260039094528285208054851682179055600480549283018155948590527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b90910180549093168117909255517f86489ba900000000000000000000000000000000000000000000000000000000815284841692810192909252918b1660248201526044810186905260648101899052608481018a905260a481018890526386489ba99060c401600060405180830381600087803b15801562000a7457600080fd5b505af115801562000a89573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8d81168252602082018990529181018c9052606081018b9052608081018a905288821660a08201523360c0820152908d1692507fb43245c2ad6a25515dae8505f54738e2543a4dcdd83771da7a8f882bb6fd15a0915060e00160405180910390a25050505095945050505050565b6002602052816000526040600020818154811062000b2f57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b62000b6262001003565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1633811462000bf2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f414e54453a204d7573742062652063616c6c6564206279206120706f6f6c00006044820152606401620003d3565b6040517f18350f2200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152339060009082906318350f2290602401608060405180830381865afa15801562000c62573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c8891906200168f565b50925050506000811162000d1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f414e54453a204f6e6c7920636f6e6669726d6564206368616c6c656e6765727360448201527f2063616e20636865636b546573740000000000000000000000000000000000006064820152608401620003d3565b6040517f6a7b650600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152439190841690636a7b650690602401602060405180830381865afa15801562000d8f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000db5919062001655565b1062000e44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f414e54453a206d75737420776169742032353520626c6f636b7320616674657260448201527f206368616c6c656e67696e6720746f2063616c6c20636865636b5465737400006064820152608401620003d3565b60008273ffffffffffffffffffffffffffffffffffffffff16637bb4d0a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000e92573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000eb891906200166f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205490915060ff16801562000f4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f414e54453a205465737420616c7265616479206661696c65642e0000000000006044820152606401620003d3565b6040517f8dd9dc0400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152851690638dd9dc0490602401600060405180830381600087803b15801562000fb857600080fd5b505af115801562000fcd573d6000803e3d6000fd5b5050505062000fdd828962001078565b62000fee5762000fee8288620011d6565b505050505062000ffe6001600055565b505050565b60026000540362001071576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401620003d3565b6002600055565b80516000901562001149576040517f07c0dffe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906307c0dffe90620010d7908590600401620016c6565b6020604051808303816000875af192505050801562001133575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252620011309181019062001631565b60015b6200114157506001620011d0565b9050620011d0565b8273ffffffffffffffffffffffffffffffffffffffff1663e0b4fb926040518163ffffffff1660e01b81526004016020604051808303816000875af192505050801562001133575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252620011309181019062001631565b92915050565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526001602081815260408084208054438286015542600280840191909155968816610100027fffffffffffffffffffffff00000000000000000000000000000000000000000090911617909317835593815283832080548551818402810184019096528086529294929091830182828015620012a557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831162001279575b505083519394506000925050505b818110156200139d57828181518110620012d157620012d162001734565b60209081029190910101516040517fe528c94a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301529091169063e528c94a90602401600060405180830381600087803b1580156200134757600080fd5b505af192505050801562001359575060015b62001388576040517f288c43acf4ce89fe7c0c09300defaff6775ae6329e91c02f7f1714968e348ca490600090a15b80620013948162001763565b915050620012b3565b505050505050565b61029f80620017c483390190565b600060208284031215620013c657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114620013f057600080fd5b50565b80356200140081620013cd565b919050565b6000602082840312156200141857600080fd5b81356200142581620013cd565b9392505050565b6020808252825182820181905260009190848201906040850190845b818110156200147c57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010162001448565b50909695505050505050565b600080600080600060a08688031215620014a157600080fd5b8535620014ae81620013cd565b94506020860135620014c081620013cd565b94979496505050506040830135926060810135926080909101359150565b60008060408385031215620014f257600080fd5b8235620014ff81620013cd565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156200155257600080fd5b833567ffffffffffffffff808211156200156b57600080fd5b818601915086601f8301126200158057600080fd5b8135818111156200159557620015956200150d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715620015de57620015de6200150d565b81604052828152896020848701011115620015f857600080fd5b8260208601602083013760006020848301015280975050505050506200162160208501620013f3565b9150604084013590509250925092565b6000602082840312156200164457600080fd5b815180151581146200142557600080fd5b6000602082840312156200166857600080fd5b5051919050565b6000602082840312156200168257600080fd5b81516200142581620013cd565b60008060008060808587031215620016a657600080fd5b505082516020840151604085015160609095015191969095509092509050565b600060208083528351808285015260005b81811015620016f557858101830151858201604001528201620016d7565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620017bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fe608060405234801561001057600080fd5b5060405161029f38038061029f83398101604081905261002f91610118565b6100428161010660201b6100211760201c565b6100a15760405162461bcd60e51b815260206004820152602660248201527f414e54453a20696d706c656d656e746174696f6e206973206e6f74206120636f6044820152651b9d1c9858dd60d21b606482015260840160405180910390fd5b806100e26100d060017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd610148565b60001b61011560201b61003d1760201c565b80546001600160a01b0319166001600160a01b03929092169190911790555061016f565b6001600160a01b03163b151590565b90565b60006020828403121561012a57600080fd5b81516001600160a01b038116811461014157600080fd5b9392505050565b8181038181111561016957634e487b7160e01b600052601160045260246000fd5b92915050565b6101218061017e6000396000f3fe608060405236601057600e6013565b005b600e5b601f601b6040565b6089565b565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b6000606d603d60017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd60ac565b5473ffffffffffffffffffffffffffffffffffffffff16919050565b3660008037600080366000845af43d6000803e80801560a7573d6000f35b3d6000fd5b8181038181111560e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea2646970667358221220fffe7dd56380a5ce4638672ddef2f12a0a86466f94de0c90fa6ddda72fa743ee64736f6c63430008100033a2646970667358221220b9c3ec15f641721fa12d17927d27865bf235afcac259513b916214577f9101cd64736f6c63430008100033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000044d195661277f25597fe6b6d9f910d5bbe9821b3

-----Decoded View---------------
Arg [0] : _controller (address): 0x44d195661277f25597fE6b6d9f910D5bbe9821b3

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000044d195661277f25597fe6b6d9f910d5bbe9821b3


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
[ 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.