Contract 0x1430f4cb9d123f1542d908a29d6987ba05a858e3 2

Txn Hash Method
Block
From
To
Value [Txn Fee]
0xf2c5d997b7698cbed1dfef1a37b362759d1198d3526037664303e96b015fc673Set AUTO76478352021-12-01 1:54:46300 days 6 hrs ago0x3f09e942b0089b8af73ccb9603da8064b6c4b637 IN  0x1430f4cb9d123f1542d908a29d6987ba05a858e30 AVAX0.00117016255126.495246259
0x556619733774d1f62b3163b43ed693e16a45a99c342e6cfd4f43d05fa6a529af0x60a0604076476572021-12-01 1:48:48300 days 6 hrs ago0x3f09e942b0089b8af73ccb9603da8064b6c4b637 IN  Create: StakeManager0 AVAX0.036889625
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StakeManager

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 9 : StakeManager.sol
pragma solidity 0.8.6;


import "IERC777.sol";
import "ReentrancyGuard.sol";
import "IERC777Recipient.sol";
import "IERC1820Registry.sol";
import "IStakeManager.sol";
import "IOracle.sol";
import "Shared.sol";


contract StakeManager is IStakeManager, Shared, ReentrancyGuard, IERC777Recipient {

    uint public constant STAN_STAKE = 10000 * _E_18;
    uint public constant BLOCKS_IN_EPOCH = 100;
    bytes private constant _stakingIndicator = "staking";

    IOracle private immutable _oracle;
    // AUTO ERC777
    IERC777 private _AUTO;
    bool private _AUTOSet = false;
    IERC1820Registry constant private _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
    bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH = keccak256('ERC777TokensRecipient');
    uint private _totalStaked = 0;
    // Needed so that receiving AUTO is rejected unless it's indicated
    // that's it's used for staking and therefore not an accident (protect users)
    Executor private _executor;
    mapping(address => uint) private _stakerToStakedAmount;
    address[] private _stakes;


    // Pasted for convenience here, defined in IStakeManager
    // struct Executor{
    //     address addr;
    //     uint96 forEpoch;
    // }


    event Staked(address staker, uint amount);
    event Unstaked(address staker, uint amount);


    constructor(IOracle oracle) {
        _oracle = oracle;
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), TOKENS_RECIPIENT_INTERFACE_HASH, address(this));
    }


    function setAUTO(IERC777 AUTO) external {
        require(!_AUTOSet, "SM: AUTO already set");
        _AUTOSet = true;
        _AUTO = AUTO;
    }


    //////////////////////////////////////////////////////////////
    //                                                          //
    //                          Getters                         //
    //                                                          //
    //////////////////////////////////////////////////////////////

    function getOracle() external view override returns (IOracle) {
        return _oracle;
    }

    function getAUTOAddr() external view override returns (address) {
        return address(_AUTO);
    }

    function getTotalStaked() external view override returns (uint) {
        return _totalStaked;
    }

    function getStake(address staker) external view override returns (uint) {
        return _stakerToStakedAmount[staker];
    }

    function getStakes() external view override returns (address[] memory) {
        return _stakes;
    }

    function getStakesLength() external view override returns (uint) {
        return _stakes.length;
    }

    function getStakesSlice(uint startIdx, uint endIdx) external view override returns (address[] memory) {
        address[] memory slice = new address[](endIdx - startIdx);
        uint sliceIdx = 0;
        for (uint stakeIdx = startIdx; stakeIdx < endIdx; stakeIdx++) {
            slice[sliceIdx] = _stakes[stakeIdx];
            sliceIdx++;
        }

        return slice;
    }

    function getCurEpoch() public view override returns (uint96) {
        return uint96((block.number / BLOCKS_IN_EPOCH) * BLOCKS_IN_EPOCH);
    }

    function getExecutor() external view override returns (Executor memory) {
        return _executor;
    }

    function isCurExec(address addr) external view override returns (bool) {
        // So that the storage is only loaded once
        Executor memory ex = _executor;
        if (ex.forEpoch == getCurEpoch()) {
            if (ex.addr == addr) {
                return true;
            } else {
                return false;
            }
        }
        // If there're no stakes, allow anyone to be the executor so that a random
        // person can bootstrap the network and nobody needs to be sent any coins
        if (_stakes.length == 0) { return true; }

        return false;
    }

    function getUpdatedExecRes() public view override returns (uint96 epoch, uint randNum, uint idxOfExecutor, address exec) {
        epoch = getCurEpoch();
        // So that the storage is only loaded once
        address[] memory stakes = _stakes;
        // If the executor is out of date and the system already has stake,
        // choose a new executor. This will do nothing if the system is starting
        // and allow someone to stake without needing there to already be existing stakes
        if (_executor.forEpoch != epoch && stakes.length > 0) {
            // -1 because blockhash(seed) in Oracle will return 0x00 if the
            // seed == this block's height
            randNum = _oracle.getRandNum(epoch - 1);
            idxOfExecutor = randNum % stakes.length;
            exec = stakes[idxOfExecutor];
        }
    }


    //////////////////////////////////////////////////////////////
    //                                                          //
    //                          Staking                         //
    //                                                          //
    //////////////////////////////////////////////////////////////

    function updateExecutor() external override nonReentrant noFish returns (uint, uint, uint, address) {
        return _updateExecutor();
    }

    function isUpdatedExec(address addr) external override nonReentrant noFish returns (bool) {
        // So that the storage is only loaded once
        Executor memory ex = _executor;
        if (ex.forEpoch == getCurEpoch()) {
            if (ex.addr == addr) {
                return true;
            } else {
                return false;
            }
        } else {
            (, , , address exec) = _updateExecutor();
            if (exec == addr) { return true; }
        }
        if (_stakes.length == 0) { return true; }

        return false;
    }

    // The 1st stake/unstake of an epoch shouldn't change the executor, otherwise
    // a staker could precalculate the effect of how much they stake in order to
    // game the staker selection algo
    function stake(uint numStakes) external nzUint(numStakes) nonReentrant updateExec noFish override {
        uint amount = numStakes * STAN_STAKE;
        _stakerToStakedAmount[msg.sender] += amount;
        // So that the storage is only loaded once
        IERC777 AUTO = _AUTO;

        // Deposit the coins
        uint balBefore = AUTO.balanceOf(address(this));
        AUTO.operatorSend(msg.sender, address(this), amount, "", _stakingIndicator);
        // This check is a bit unnecessary, but better to be paranoid than r3kt
        require(AUTO.balanceOf(address(this)) - balBefore == amount, "SM: transfer bal check failed");

        for (uint i; i < numStakes; i++) {
            _stakes.push(msg.sender);
        }

        _totalStaked += amount;
        emit Staked(msg.sender, amount);
    }

    function unstake(uint[] calldata idxs) external nzUintArr(idxs) nonReentrant updateExec noFish override {
        uint amount = idxs.length * STAN_STAKE;
        require(amount <= _stakerToStakedAmount[msg.sender], "SM: not enough stake, peasant");

        for (uint i = 0; i < idxs.length; i++) {
            require(_stakes[idxs[i]] == msg.sender, "SM: idx is not you");
            require(idxs[i] < _stakes.length, "SM: idx out of bounds");
            // Update stakes by moving the last element to the
            // element we're wanting to delete (so it doesn't leave gaps, which is
            // necessary for the _updateExecutor algo)
            _stakes[idxs[i]] = _stakes[_stakes.length-1];
            _stakes.pop();
        }
        
        _stakerToStakedAmount[msg.sender] -= amount;
        _AUTO.send(msg.sender, amount, _stakingIndicator);
        _totalStaked -= amount;
        emit Unstaked(msg.sender, amount);
    }

    function _updateExecutor() private returns (uint96 epoch, uint randNum, uint idxOfExecutor, address exec) {
        (epoch, randNum, idxOfExecutor, exec) = getUpdatedExecRes();
        if (exec != _ADDR_0) {
            _executor = Executor(exec, epoch);
        }
    }

    modifier updateExec() {
        // Need to update executor at the start of stake/unstake as opposed to the
        // end of the fcns because otherwise, for the 1st stake/unstake tx in an
        // epoch, someone could influence the outcome of the executor by precalculating
        // the outcome based on how much they stake and unfairly making themselves the executor
        _updateExecutor();
        _;
    }

    // Ensure the contract is fully collateralised every time
    modifier noFish() {
        _;
        // >= because someone could send some tokens to this contract and disable it if it was ==
        require(_AUTO.balanceOf(address(this)) >= _totalStaked, "SM: something fishy here");
    }

    function tokensReceived(
        address _operator,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data,
        bytes calldata _operatorData
    ) external override {
        require(msg.sender == address(_AUTO), "SM: non-AUTO token");
        require(keccak256(_operatorData) == keccak256(_stakingIndicator), "SM: sending by mistake");
    }

}

File 2 of 9 : IERC777.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC777Token standard as defined in the EIP.
 *
 * This contract uses the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
 * token holders and recipients react to token movements by using setting implementers
 * for the associated interfaces in said registry. See {IERC1820Registry} and
 * {ERC1820Implementer}.
 */
interface IERC777 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the smallest part of the token that is not divisible. This
     * means all token operations (creation, movement and destruction) must have
     * amounts that are a multiple of this number.
     *
     * For most token contracts, this value will equal 1.
     */
    function granularity() external view returns (uint256);

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

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

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * If send or receive hooks are registered for the caller and `recipient`,
     * the corresponding functions will be called with `data` and empty
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function send(
        address recipient,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the
     * total supply.
     *
     * If a send hook is registered for the caller, the corresponding function
     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     */
    function burn(uint256 amount, bytes calldata data) external;

    /**
     * @dev Returns true if an account is an operator of `tokenHolder`.
     * Operators can send and burn tokens on behalf of their owners. All
     * accounts are their own operator.
     *
     * See {operatorSend} and {operatorBurn}.
     */
    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);

    /**
     * @dev Make an account an operator of the caller.
     *
     * See {isOperatorFor}.
     *
     * Emits an {AuthorizedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function authorizeOperator(address operator) external;

    /**
     * @dev Revoke an account's operator status for the caller.
     *
     * See {isOperatorFor} and {defaultOperators}.
     *
     * Emits a {RevokedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function revokeOperator(address operator) external;

    /**
     * @dev Returns the list of default operators. These accounts are operators
     * for all token holders, even if {authorizeOperator} was never called on
     * them.
     *
     * This list is immutable, but individual holders may revoke these via
     * {revokeOperator}, in which case {isOperatorFor} will return false.
     */
    function defaultOperators() external view returns (address[] memory);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
     * be an operator of `sender`.
     *
     * If send or receive hooks are registered for `sender` and `recipient`,
     * the corresponding functions will be called with `data` and
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - `sender` cannot be the zero address.
     * - `sender` must have at least `amount` tokens.
     * - the caller must be an operator for `sender`.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the total supply.
     * The caller must be an operator of `account`.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `data` and `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     * - the caller must be an operator for `account`.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    event Sent(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );

    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);

    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);

    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);

    event RevokedOperator(address indexed operator, address indexed tokenHolder);
}

File 3 of 9 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

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 make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

File 4 of 9 : IERC777Recipient.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
 *
 * Accounts can be notified of {IERC777} tokens being sent to them by having a
 * contract implement this interface (contract holders can be their own
 * implementer) and registering it on the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
 *
 * See {IERC1820Registry} and {ERC1820Implementer}.
 */
interface IERC777Recipient {
    /**
     * @dev Called by an {IERC777} token contract whenever tokens are being
     * moved or created into a registered account (`to`). The type of operation
     * is conveyed by `from` being the zero address or not.
     *
     * This call occurs _after_ the token contract's state is updated, so
     * {IERC777-balanceOf}, etc., can be used to query the post-operation state.
     *
     * This function may revert to prevent the operation from being executed.
     */
    function tokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}

File 5 of 9 : IERC1820Registry.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the global ERC1820 Registry, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
 * implementers for interfaces in this registry, as well as query support.
 *
 * Implementers may be shared by multiple accounts, and can also implement more
 * than a single interface for each account. Contracts can implement interfaces
 * for themselves, but externally-owned accounts (EOA) must delegate this to a
 * contract.
 *
 * {IERC165} interfaces can also be queried via the registry.
 *
 * For an in-depth explanation and source code analysis, see the EIP text.
 */
interface IERC1820Registry {
    /**
     * @dev Sets `newManager` as the manager for `account`. A manager of an
     * account is able to set interface implementers for it.
     *
     * By default, each account is its own manager. Passing a value of `0x0` in
     * `newManager` will reset the manager to this initial state.
     *
     * Emits a {ManagerChanged} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     */
    function setManager(address account, address newManager) external;

    /**
     * @dev Returns the manager for `account`.
     *
     * See {setManager}.
     */
    function getManager(address account) external view returns (address);

    /**
     * @dev Sets the `implementer` contract as ``account``'s implementer for
     * `interfaceHash`.
     *
     * `account` being the zero address is an alias for the caller's address.
     * The zero address can also be used in `implementer` to remove an old one.
     *
     * See {interfaceHash} to learn how these are created.
     *
     * Emits an {InterfaceImplementerSet} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
     * end in 28 zeroes).
     * - `implementer` must implement {IERC1820Implementer} and return true when
     * queried for support, unless `implementer` is the caller. See
     * {IERC1820Implementer-canImplementInterfaceForAddress}.
     */
    function setInterfaceImplementer(
        address account,
        bytes32 _interfaceHash,
        address implementer
    ) external;

    /**
     * @dev Returns the implementer of `interfaceHash` for `account`. If no such
     * implementer is registered, returns the zero address.
     *
     * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
     * zeroes), `account` will be queried for support of it.
     *
     * `account` being the zero address is an alias for the caller's address.
     */
    function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);

    /**
     * @dev Returns the interface hash for an `interfaceName`, as defined in the
     * corresponding
     * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
     */
    function interfaceHash(string calldata interfaceName) external pure returns (bytes32);

    /**
     * @notice Updates the cache with whether the contract implements an ERC165 interface or not.
     * @param account Address of the contract for which to update the cache.
     * @param interfaceId ERC165 interface for which to update the cache.
     */
    function updateERC165Cache(address account, bytes4 interfaceId) external;

    /**
     * @notice Checks whether a contract implements an ERC165 interface or not.
     * If the result is not cached a direct lookup on the contract address is performed.
     * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
     * {updateERC165Cache} with the contract address.
     * @param account Address of the contract to check.
     * @param interfaceId ERC165 interface to check.
     * @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);

    /**
     * @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
     * @param account Address of the contract to check.
     * @param interfaceId ERC165 interface to check.
     * @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);

    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);

    event ManagerChanged(address indexed account, address indexed newManager);
}

File 6 of 9 : IStakeManager.sol
pragma solidity 0.8.6;


import "IOracle.sol";


/**
* @title    StakeManager
* @notice   A lightweight Proof of Stake contract that allows
*           staking of AUTO tokens. Instead of a miner winning
*           the ability to produce a block, the algorithm selects
*           a staker for a period of 100 blocks to be the executor.
*           the executor has the exclusive right to execute requests
*           in the Registry contract. The Registry checks with StakeManager
*           who is allowed to execute requests at any given time
* @author   Quantaf1re (James Key)
*/
interface IStakeManager {

    struct Executor{
        address addr;
        uint96 forEpoch;
    }


    //////////////////////////////////////////////////////////////
    //                                                          //
    //                          Getters                         //
    //                                                          //
    //////////////////////////////////////////////////////////////
    
    function getOracle() external view returns (IOracle);

    function getAUTOAddr() external view returns (address);

    function getTotalStaked() external view returns (uint);

    function getStake(address staker) external view returns (uint);

    /**
     * @notice  Returns the array of stakes. Every element in the array represents
     *          `STAN_STAKE` amount of AUTO tokens staked for that address. Addresses
     *          can be in the array arbitrarily many times
     */
    function getStakes() external view returns (address[] memory);

    /**
     * @notice  The length of `_stakes`, i.e. the total staked when multiplied by `STAN_STAKE`
     */
    function getStakesLength() external view returns (uint);

    /**
     * @notice  The same as getStakes except it returns only part of the array - the
     *          array might grow so large that retrieving it costs more gas than the
     *          block gas limit and therefore brick the contract. E.g. for an array of
     *          x = [4, 5, 6, 7], x[1, 2] returns [5], the same as lists in Python
     * @param startIdx  [uint] The starting index from which to start getting the slice (inclusive)
     * @param endIdx    [uint] The ending index from which to start getting the slice (exclusive)
     */
    function getStakesSlice(uint startIdx, uint endIdx) external view returns (address[] memory);

    /**
     * @notice  Returns the current epoch. Goes in increments of 100. E.g. the epoch
     *          for 420 is 400, and 42069 is 42000
     */
    function getCurEpoch() external view returns (uint96);

    /**
     * @notice  Returns the currently stored Executor - which might be old,
     *          i.e. for a previous epoch
     */
    function getExecutor() external view returns (Executor memory);

    /**
     * @notice  Returns whether `addr` is the current executor for this epoch. If the executor
     *          is outdated (i.e. for a previous epoch), it'll return false regardless of `addr`
     * @param addr  [address] The address to check
     * @return  [bool] Whether or not `addr` is the current executor for this epoch
     */
    function isCurExec(address addr) external view returns (bool);

    /**
     * @notice  Returns what the result of updating the executor would be, but doesn't actually
     *          make any changes
     * @return epoch    Returns the relevant variables for determining the new executor if the executor
     *          can be updated currently. It can only be updated currently if the stored executor
     *          is for a previous epoch, and there is some stake in the system. If the executor
     *          can't be updated currently, then everything execpt `epoch` will return 0
     */
    function getUpdatedExecRes() external view returns (uint96 epoch, uint randNum, uint idxOfExecutor, address exec);

    //////////////////////////////////////////////////////////////
    //                                                          //
    //                          Staking                         //
    //                                                          //
    //////////////////////////////////////////////////////////////

    /**
     * @notice  Updates the executor. Calls `getUpdatedExecRes` to know. Makes the changes
     *          only if the executor can be updated
     * @return  Returns the relevant variables for determining the new executor if the executor
     *          can be updated currently
     */
    function updateExecutor() external returns (uint, uint, uint, address);

    /**
     * @notice  Checks if the stored executor is for the current epoch - if it is,
     *          then it returns whether `addr` is the current exec or not. If the epoch
     *          is old, then it updates the executor, then returns whether `addr` is the
     *          current executor or not. If there's no stake in the system, returns true
     * @param addr  [address] The address to check
     * @return  [bool] Returns whether or not `addr` is the current, updated executor
     */
    function isUpdatedExec(address addr) external returns (bool);

    /**
     * @notice  Stake a set amount of AUTO tokens. A set amount of tokens needs to be used
     *          so that a random number can be used to look up a specific index in the array.
     *          We want the staker to be chosen proportional to their stake, which requires
     *          knowing their stake in relation to everyone else. If you could stake any
     *          amount of AUTO tokens, then the contract would have to store that amount
     *          along with the staker and, crucially, would require iteration over the
     *          whole array. E.g. if the random number in this PoS system was 0.2, then
     *          you could calculate the amount of proportional stake that translates to.
     *          If the total stakes was 10^6, then whichever staker in the array at token
     *          position 200,000 would be the winner, but that requires going through every
     *          piece of staking info in the first part of the array in order to calculate
     *          the running cumulative and know who happens to have the slot where the
     *          cumulative stake is 200,000. This has problems when the staking array is
     *          so large that it costs more than the block gas limit to iterate over, which
     *          would brick the contract, but also just generally costs alot of gas. Having
     *          a set amount of AUTO tokens means you already know everything about every
     *          element in the array therefore don't need to iterate over it.
     *          Calling this will add the caller to the array. Calling this will first try
     *          and set the executor so that the caller can't precalculate and affect the outcome
     *          by deciding the size of `numStakes`
     * @param numStakes  [uint] The number of `STAN_STAKE` to stake and therefore how many
     *          slots in the array to add the user to
     */
    function stake(uint numStakes) external;

    /**
     * @notice  Unstake AUTO tokens. Calling this will first try and set the executor so that
     *          the caller can't precalculate and affect the outcome by deciding the size of
     *          `numStakes`
     * @dev     Instead of just deleting the array slot, this takes the last element, copies
     *          it to the slot being unstaked, and pops off the original copy of the replacement
     *          from the end of the array, so that there are no gaps left, such that 0x00...00
     *          can never be chosen as an executor
     * @param idxs  [uint[]] The indices of the user's slots, in order of which they'll be
     *              removed, which is not necessariy the current indices. E.g. if the `_staking`
     *              array is [a, b, c, b], and `idxs` = [1, 3], then i=1 will first get
     *              replaced by i=3 and look like [a, b, c], then it would try and replace i=3
     *              by the end of the array...but i=3 no longer exists, so it'll revert. In this
     *              case, `idxs` would need to be [1, 1], which would result in [a, c]. It's
     *              recommended to choose idxs in descending order so that you don't have to
     *              take account of this behaviour - that way you can just use indexes
     *              as they are already without alterations
     */
    function unstake(uint[] calldata idxs) external;
}

File 7 of 9 : IOracle.sol
pragma solidity 0.8.6;


import "IPriceOracle.sol";


interface IOracle {
    // Needs to output the same number for the whole epoch
    function getRandNum(uint salt) external view returns (uint);

    function getPriceOracle() external view returns (IPriceOracle);

    function getAUTOPerETH() external view returns (uint);

    function getGasPriceFast() external view returns (uint);

    function setPriceOracle(IPriceOracle newPriceOracle) external;

    function defaultPayIsAUTO() external view returns (bool);

    function setDefaultPayIsAUTO(bool newDefaultPayIsAUTO) external;
}

File 8 of 9 : IPriceOracle.sol
pragma solidity 0.8.6;


interface IPriceOracle {

    function getAUTOPerETH() external view returns (uint);

    function getGasPriceFast() external view returns (uint);
}

File 9 of 9 : Shared.sol
pragma solidity 0.8.6;


/**
* @title    Shared contract
* @notice   Holds constants and modifiers that are used in multiple contracts
* @dev      It would be nice if this could be a library, but modifiers can't be exported :(
* @author   Quantaf1re (James Key)
*/
abstract contract Shared {
    address constant internal _ADDR_0 = address(0);
    bytes32 constant internal _NULL = "";
    uint constant internal _E_18 = 10**18;


    /// @dev    Checks that a uint isn't nonzero/empty
    modifier nzUint(uint u) {
        require(u != 0, "Shared: uint input is empty");
        _;
    }

    /// @dev    Checks that an address isn't nonzero/empty
    modifier nzAddr(address a) {
        require(a != _ADDR_0, "Shared: address input is empty");
        _;
    }

    /// @dev    Checks that a bytes array isn't nonzero/empty
    modifier nzBytes(bytes calldata b) {
        require(b.length > 1, "Shared: bytes input is empty");
        _;
    }

    /// @dev    Checks that a bytes array isn't nonzero/empty
    modifier nzBytes32(bytes32 b) {
        require(b != _NULL, "Shared: bytes32 input is empty");
        _;
    }

    /// @dev    Checks that a uint array isn't nonzero/empty
    modifier nzUintArr(uint[] calldata arr) {
        require(arr.length > 0, "Shared: uint arr input is empty");
        _;
    }
}

Settings
{
  "evmVersion": "istanbul",
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract ABI

[{"inputs":[{"internalType":"contract IOracle","name":"oracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"BLOCKS_IN_EPOCH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAUTOAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurEpoch","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExecutor","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint96","name":"forEpoch","type":"uint96"}],"internalType":"struct IStakeManager.Executor","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakes","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIdx","type":"uint256"},{"internalType":"uint256","name":"endIdx","type":"uint256"}],"name":"getStakesSlice","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUpdatedExecRes","outputs":[{"internalType":"uint96","name":"epoch","type":"uint96"},{"internalType":"uint256","name":"randNum","type":"uint256"},{"internalType":"uint256","name":"idxOfExecutor","type":"uint256"},{"internalType":"address","name":"exec","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isCurExec","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isUpdatedExec","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC777","name":"AUTO","type":"address"}],"name":"setAUTO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numStakes","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes","name":"_operatorData","type":"bytes"}],"name":"tokensReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"idxs","type":"uint256[]"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateExecutor","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"}]

60a06040526001805460ff60a01b19169055600060025534801561002257600080fd5b506040516119e53803806119e5833981016040819052610041916100ef565b6001600055606081901b6001600160601b0319166080526040516329965a1d60e01b815230600482018190527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b60248301526044820152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90606401600060405180830381600087803b1580156100d157600080fd5b505af11580156100e5573d6000803e3d6000fd5b505050505061011f565b60006020828403121561010157600080fd5b81516001600160a01b038116811461011857600080fd5b9392505050565b60805160601c6118a16101446000396000818161025501526111fb01526118a16000f3fe608060405234801561001057600080fd5b50600436106101205760003560e01c8063833b1fce116100ad578063d34f304b11610071578063d34f304b146102de578063df4b4776146102ef578063e449f341146102f7578063ec8ea74f1461030a578063f862a7b31461034557600080fd5b8063833b1fce14610253578063885964a41461028d578063a694fc3a146102b0578063aba21dfd146102c3578063ac4a8703146102cb57600080fd5b80634bade67e116100f45780634bade67e146101795780635fce0b2a146101815780636c1032af146101b25780637776f8f91461020a5780637a7664601461022a57600080fd5b806223de29146101255780630917e7761461013a5780633fd51c471461015157806344c0e04c14610159575b600080fd5b610138610133366004611421565b610358565b005b6002545b6040519081526020015b60405180910390f35b61013e610452565b61016c610167366004611579565b610469565b6040516101489190611671565b60055461013e565b61018961054c565b604080519485526020850193909352918301526001600160a01b03166060820152608001610148565b6040805180820182526000808252602091820152815180830183526003546001600160a01b0381168083526001600160601b03600160a01b909204821692840192835284519081529151169181019190915201610148565b610212610641565b6040516001600160601b039091168152602001610148565b61013e6102383660046113fd565b6001600160a01b031660009081526004602052604090205490565b7f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b039091168152602001610148565b6102a061029b3660046113fd565b61065e565b6040519015158152602001610148565b6101386102be366004611547565b6106f4565b61013e606481565b6102a06102d93660046113fd565b610aed565b6001546001600160a01b0316610275565b61016c610c8e565b6101386103053660046114d2565b610cf0565b610312611156565b604080516001600160601b0390951685526020850193909352918301526001600160a01b03166060820152608001610148565b6101386103533660046113fd565b6112d7565b6001546001600160a01b031633146103ac5760405162461bcd60e51b815260206004820152601260248201527129a69d103737b716a0aaaa27903a37b5b2b760711b60448201526064015b60405180910390fd5b60408051808201825260078152667374616b696e6760c81b602090910152517f8f6d06a17e13511155ffa96004c22afae6a03438b8fed74cb1cf441168df3f12906103fa90849084906115e8565b6040518091039020146104485760405162461bcd60e51b8152602060048201526016602482015275534d3a2073656e64696e67206279206d697374616b6560501b60448201526064016103a3565b5050505050505050565b610466670de0b6b3a7640000612710611758565b81565b606060006104778484611777565b67ffffffffffffffff81111561048f5761048f61183d565b6040519080825280602002602001820160405280156104b8578160200160208202803683370190505b5090506000845b8481101561054257600581815481106104da576104da611827565b9060005260206000200160009054906101000a90046001600160a01b031683838151811061050a5761050a611827565b6001600160a01b03909216602092830291909101909101528161052c816117b6565b925050808061053a906117b6565b9150506104bf565b5090949350505050565b600080600080600260005414156105755760405162461bcd60e51b81526004016103a3906116f5565b6002600055610582611351565b6002546001546040516370a0823160e01b81523060048201526001600160601b0390961699509397509195509350916001600160a01b03909116906370a082319060240160206040518083038186803b1580156105de57600080fd5b505afa1580156105f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106169190611560565b10156106345760405162461bcd60e51b81526004016103a3906116be565b6001600055929391929091565b6000606461064f8143611744565b6106599190611758565b905090565b604080518082019091526003546001600160a01b0381168252600160a01b90046001600160601b03166020820152600090610697610641565b6001600160601b031681602001516001600160601b031614156106e457826001600160a01b031681600001516001600160a01b031614156106db5750600192915050565b50600092915050565b6005546106db5750600192915050565b80806107425760405162461bcd60e51b815260206004820152601b60248201527f5368617265643a2075696e7420696e70757420697320656d707479000000000060448201526064016103a3565b600260005414156107655760405162461bcd60e51b81526004016103a3906116f5565b6002600055610772611351565b505050506000670de0b6b3a764000061271061078e9190611758565b6107989084611758565b336000908152600460205260408120805492935083929091906107bc90849061172c565b90915550506001546040516370a0823160e01b81523060048201526001600160a01b039091169060009082906370a082319060240160206040518083038186803b15801561080957600080fd5b505afa15801561081d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108419190611560565b60408051808201825260078152667374616b696e6760c81b602082015290516362ad1b8360e01b81529192506001600160a01b038416916362ad1b839161089191339130918991906004016115f8565b600060405180830381600087803b1580156108ab57600080fd5b505af11580156108bf573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201528592508391506001600160a01b038516906370a082319060240160206040518083038186803b15801561090657600080fd5b505afa15801561091a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093e9190611560565b6109489190611777565b146109955760405162461bcd60e51b815260206004820152601d60248201527f534d3a207472616e736665722062616c20636865636b206661696c656400000060448201526064016103a3565b60005b858110156109f457600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191633179055806109ec816117b6565b915050610998565b508260026000828254610a07919061172c565b909155505060408051338152602081018590527f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a150506002546001546040516370a0823160e01b81523060048201529192506001600160a01b0316906370a082319060240160206040518083038186803b158015610a8e57600080fd5b505afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190611560565b1015610ae45760405162461bcd60e51b81526004016103a3906116be565b50506001600055565b600060026000541415610b125760405162461bcd60e51b81526004016103a3906116f5565b6002600055604080518082019091526003546001600160a01b0381168252600160a01b90046001600160601b03166020820152610b4d610641565b6001600160601b031681602001516001600160601b03161415610b9c57826001600160a01b031681600001516001600160a01b03161415610b92576001915050610be8565b6000915050610be8565b6000610ba6611351565b9350505050836001600160a01b0316816001600160a01b03161415610bd057600192505050610be8565b50600554610be2576001915050610be8565b60009150505b6002546001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610c2e57600080fd5b505afa158015610c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c669190611560565b1015610c845760405162461bcd60e51b81526004016103a3906116be565b6001600055919050565b60606005805480602002602001604051908101604052809291908181526020018280548015610ce657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cc8575b5050505050905090565b818180610d3f5760405162461bcd60e51b815260206004820152601f60248201527f5368617265643a2075696e742061727220696e70757420697320656d7074790060448201526064016103a3565b60026000541415610d625760405162461bcd60e51b81526004016103a3906116f5565b6002600055610d6f611351565b505050506000670de0b6b3a7640000612710610d8b9190611758565b610d959085611758565b33600090815260046020526040902054909150811115610df75760405162461bcd60e51b815260206004820152601d60248201527f534d3a206e6f7420656e6f756768207374616b652c2070656173616e7400000060448201526064016103a3565b60005b84811015610fb957336005878784818110610e1757610e17611827565b9050602002013581548110610e2e57610e2e611827565b6000918252602090912001546001600160a01b031614610e855760405162461bcd60e51b8152602060048201526012602482015271534d3a20696478206973206e6f7420796f7560701b60448201526064016103a3565b600554868683818110610e9a57610e9a611827565b9050602002013510610ee65760405162461bcd60e51b8152602060048201526015602482015274534d3a20696478206f7574206f6620626f756e647360581b60448201526064016103a3565b60058054610ef690600190611777565b81548110610f0657610f06611827565b6000918252602090912001546001600160a01b03166005878784818110610f2f57610f2f611827565b9050602002013581548110610f4657610f46611827565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506005805480610f8557610f85611811565b600082815260209020810160001990810180546001600160a01b031916905501905580610fb1816117b6565b915050610dfa565b503360009081526004602052604081208054839290610fd9908490611777565b909155505060015460408051808201825260078152667374616b696e6760c81b60208201529051634decdde360e11b81526001600160a01b0390921691639bd9bbc69161102c9133918691600401611641565b600060405180830381600087803b15801561104657600080fd5b505af115801561105a573d6000803e3d6000fd5b5050505080600260008282546110709190611777565b909155505060408051338152602081018390527f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f75910160405180910390a1506002546001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b1580156110f557600080fd5b505afa158015611109573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112d9190611560565b101561114b5760405162461bcd60e51b81526004016103a3906116be565b505060016000555050565b600080600080611164610641565b9350600060058054806020026020016040519081016040528092919081815260200182805480156111be57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116111a0575b50506003549394505050506001600160601b03868116600160a01b90920416148015906111ec575060008151115b156112d0576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016636c3f914c61122b60018861178e565b6040516001600160e01b031960e084901b1681526001600160601b03909116600482015260240160206040518083038186803b15801561126a57600080fd5b505afa15801561127e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a29190611560565b93508051846112b191906117d1565b92508083815181106112c5576112c5611827565b602002602001015191505b5090919293565b600154600160a01b900460ff16156113285760405162461bcd60e51b815260206004820152601460248201527314d34e8810555513c8185b1c9958591e481cd95d60621b60448201526064016103a3565b600180546001600160a01b039092166001600160a81b031990921691909117600160a01b179055565b60008060008061135f611156565b929650909450925090506001600160a01b038116156113ae57604080518082019091526001600160a01b0382168082526001600160601b0386166020909201829052600160a01b909102176003555b90919293565b60008083601f8401126113c657600080fd5b50813567ffffffffffffffff8111156113de57600080fd5b6020830191508360208285010111156113f657600080fd5b9250929050565b60006020828403121561140f57600080fd5b813561141a81611853565b9392505050565b60008060008060008060008060c0898b03121561143d57600080fd5b883561144881611853565b9750602089013561145881611853565b9650604089013561146881611853565b955060608901359450608089013567ffffffffffffffff8082111561148c57600080fd5b6114988c838d016113b4565b909650945060a08b01359150808211156114b157600080fd5b506114be8b828c016113b4565b999c989b5096995094979396929594505050565b600080602083850312156114e557600080fd5b823567ffffffffffffffff808211156114fd57600080fd5b818501915085601f83011261151157600080fd5b81358181111561152057600080fd5b8660208260051b850101111561153557600080fd5b60209290920196919550909350505050565b60006020828403121561155957600080fd5b5035919050565b60006020828403121561157257600080fd5b5051919050565b6000806040838503121561158c57600080fd5b50508035926020909101359150565b6000815180845260005b818110156115c1576020818501810151868301820152016115a5565b818111156115d3576000602083870101525b50601f01601f19169290920160200192915050565b8183823760009101908152919050565b600060018060a01b03808716835280861660208401525083604083015260a06060830152600060a083015260c0608083015261163760c083018461159b565b9695505050505050565b60018060a01b0384168152826020820152606060408201526000611668606083018461159b565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156116b25783516001600160a01b03168352928401929184019160010161168d565b50909695505050505050565b60208082526018908201527f534d3a20736f6d657468696e6720666973687920686572650000000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6000821982111561173f5761173f6117e5565b500190565b600082611753576117536117fb565b500490565b6000816000190483118215151615611772576117726117e5565b500290565b600082821015611789576117896117e5565b500390565b60006001600160601b03838116908316818110156117ae576117ae6117e5565b039392505050565b60006000198214156117ca576117ca6117e5565b5060010190565b6000826117e0576117e06117fb565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461186857600080fd5b5056fea2646970667358221220a95c2f693cb857d846b87bca276d119dd0e2e0e76cafc303e8bc18c442fa904f64736f6c63430008060033000000000000000000000000bab6d0b770b9970e9ff2af9a7e2a52b3d7aa157f

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

000000000000000000000000bab6d0b770b9970e9ff2af9a7e2a52b3d7aa157f

-----Decoded View---------------
Arg [0] : oracle (address): 0xbab6d0b770b9970e9ff2af9a7e2a52b3d7aa157f

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000bab6d0b770b9970e9ff2af9a7e2a52b3d7aa157f


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.