Contract
0x1430F4CB9D123F1542d908a29D6987bA05a858e3
2
Contract Overview
Balance:
0 AVAX
AVAX Value:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xf2c5d997b7698cbed1dfef1a37b362759d1198d3526037664303e96b015fc673 | Set AUTO | 7647835 | 482 days 20 hrs ago | 0x3f09e942b0089b8af73ccb9603da8064b6c4b637 | IN | 0x1430f4cb9d123f1542d908a29d6987ba05a858e3 | 0 AVAX | 0.001170162551 | |
0x556619733774d1f62b3163b43ed693e16a45a99c342e6cfd4f43d05fa6a529af | 0x60a06040 | 7647657 | 482 days 20 hrs ago | 0x3f09e942b0089b8af73ccb9603da8064b6c4b637 | IN | Create: StakeManager | 0 AVAX | 0.0368896 |
[ Download CSV Export ]
Contract Name:
StakeManager
Compiler Version
v0.8.6+commit.11564f7e
Contract Source Code (Solidity Standard Json-Input format)
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"); } }
// 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); }
// 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; } }
// 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; }
// 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); }
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; }
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; }
pragma solidity 0.8.6; interface IPriceOracle { function getAUTOPerETH() external view returns (uint); function getGasPriceFast() external view returns (uint); }
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"); _; } }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "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"}]
Contract Creation Code
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
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.