Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0xBdE4Dfb0dbb0Dd8833eFb6C5BD0Ce048C852C487
Balance 0 ETH
Nonce 1
Code Size 6219 bytes
Indexed Transactions 0 (1 on-chain, 1.3% indexed)
External Etherscan · Sourcify

Contract Bytecode

6219 bytes
0x608060405234801561001057600080fd5b50600436106101735760003560e01c80638f077b83116100de578063bfe1092811610097578063deac361a11610071578063deac361a1461039e578063ed4acaa8146103a6578063f3d86e4a146103ae578063f62ae76a146103b657610173565b8063bfe1092814610371578063c9f464ff14610379578063d7b96d4e1461039657610173565b80638f077b83146102fe578063900cf0cf146103065780639e5722f9146103345780639ebea88c1461033c578063a8dd07dc14610361578063af14052c1461036957610173565b8063481c6a7511610130578063481c6a75146102295780635a96ac0a146102315780636746f4c2146102395780637acb775714610287578063865e6fd3146102c75780638b7afe2e146102f657610173565b806303c2367014610178578063089208d8146101975780631e83409a1461019f57806322443c10146101c55780632986c0e5146101e957806346f68ee914610203575b600080fd5b6101956004803603602081101561018e57600080fd5b50356103d3565b005b610195610437565b610195600480360360208110156101b557600080fd5b50356001600160a01b03166104ce565b6101cd610682565b604080516001600160a01b039092168252519081900360200190f35b6101f16106a6565b60408051918252519081900360200190f35b6101956004803603602081101561021957600080fd5b50356001600160a01b0316610732565b6101cd61081f565b61019561082e565b61025f6004803603602081101561024f57600080fd5b50356001600160a01b03166108d8565b6040805194855260208501939093528383019190915215156060830152519081900360800190f35b6102b36004803603604081101561029d57600080fd5b50803590602001356001600160a01b0316610902565b604080519115158252519081900360200190f35b610195600480360360408110156102dd57600080fd5b50803560ff1690602001356001600160a01b0316610b4e565b6101f1610cc8565b610195610d74565b61030e610d98565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6101cd610da7565b6101956004803603604081101561035257600080fd5b50803590602001351515610dcb565b6101f1610e42565b610195610e48565b6101cd611056565b6101956004803603602081101561038f57600080fd5b5035611065565b6101cd6110b7565b6101f16110c6565b6101cd6110cc565b6101956110db565b610195600480360360208110156103cc57600080fd5b5035611285565b6007546001600160a01b031633146103ea57600080fd5b6008546103f790826112e7565b600855600754610434906001600160a01b037f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc8116911683611348565b50565b6000546001600160a01b03163314610484576040805162461bcd60e51b815260206004820181905260248201526000805160206117cc833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba908390a3600080546001600160a01b0319169055565b6104d6611713565b506001600160a01b0381166000908152600b6020908152604091829020825160808101845281548152600182015492810192909252600281015492820183905260039081015460ff16151560608301525490911180159061053a5750604081015115155b1561067e576001600160a01b038083166000908152600b602090815260408083208381556001810184905560028101939093556003909201805460ff19169055600954848201518351637965d56d60e01b8152600481019190915292519084169363c3a2a6659387937f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc90921692637965d56d92602480840193919291829003018186803b1580156105eb57600080fd5b505afa1580156105ff573d6000803e3d6000fd5b505050506040513d602081101561061557600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b039093166004840152602483019190915251604480830192600092919082900301818387803b15801561066557600080fd5b505af1158015610679573d6000803e3d6000fd5b505050505b5050565b7f000000000000000000000000c0d4ceb216b3ba9c3701b291766fdcba977cec3a81565b60007f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc6001600160a01b0316632986c0e56040518163ffffffff1660e01b815260040160206040518083038186803b15801561070157600080fd5b505afa158015610715573d6000803e3d6000fd5b505050506040513d602081101561072b57600080fd5b5051905090565b6000546001600160a01b0316331461077f576040805162461bcd60e51b815260206004820181905260248201526000805160206117cc833981519152604482015290519081900360640190fd5b6001600160a01b0381166107c45760405162461bcd60e51b81526004018080602001828103825260268152602001806117616026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba91a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031690565b6001546001600160a01b031633146108775760405162461bcd60e51b81526004018080602001828103825260228152602001806117aa6022913960400191505060405180910390fd5b600154600080546040516001600160a01b0393841693909116917faa151555690c956fc3ea32f106bb9f119b5237a061eaa8557cff3e51e3792c8d91a3600154600080546001600160a01b0319166001600160a01b03909216919091179055565b600b6020526000908152604090208054600182015460028301546003909301549192909160ff1684565b600061090c610e48565b6109416001600160a01b037f000000000000000000000000c0d4ceb216b3ba9c3701b291766fdcba977cec3a1633308661139f565b610949611713565b506001600160a01b0382166000908152600b602090815260409182902082516080810184528154815260018201549281019290925260028101549282019290925260039091015460ff1615801560608301526109ec576040805162461bcd60e51b815260206004820152601f60248201527f4465706f7369747320666f72206163636f756e7420617265206c6f636b656400604482015290519081900360640190fd5b604080516080810190915281518190610a0590876112e7565b8152602001610aa87f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc6001600160a01b0316631bd39674886040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a7157600080fd5b505afa158015610a85573d6000803e3d6000fd5b505050506040513d6020811015610a9b57600080fd5b50516020850151906112e7565b8152600a54600354602090920191610abf916112e7565b8152600060209182018190526001600160a01b038681168252600b8352604091829020845181559284015160018401559083015160028301556060909201516003909101805460ff1916911515919091179055600954610b44917f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc8116911686611348565b5060019392505050565b6000546001600160a01b03163314610b9b576040805162461bcd60e51b815260206004820181905260248201526000805160206117cc833981519152604482015290519081900360640190fd5b6000826002811115610ba957fe5b1415610bcf57600680546001600160a01b0319166001600160a01b03831617905561067e565b6001826002811115610bdd57fe5b1415610c4b576009546001600160a01b031615610c2b5760405162461bcd60e51b81526004018080602001828103825260238152602001806117876023913960400191505060405180910390fd5b600980546001600160a01b0319166001600160a01b03831617905561067e565b6002826002811115610c5957fe5b141561067e576007546001600160a01b031615610ca75760405162461bcd60e51b815260040180806020018281038252602381526020018061173e6023913960400191505060405180910390fd5b600780546001600160a01b0383166001600160a01b03199091161790555050565b6000610d6f6008547f000000000000000000000000c0d4ceb216b3ba9c3701b291766fdcba977cec3a6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610d3d57600080fd5b505afa158015610d51573d6000803e3d6000fd5b505050506040513d6020811015610d6757600080fd5b5051906112e7565b905090565b336000908152600b60205260409020600301805460ff19811660ff90911615179055565b60025460035460045460055484565b7f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc81565b8015610dd957610dd9610e48565b610e0e6001600160a01b037f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc1633308561139f565b61067e6001600160a01b037f000000000000000000000000c0d4ceb216b3ba9c3701b291766fdcba977cec3a163384611348565b60085481565b6004544310611054577f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc6001600160a01b031663058ecdb46002600301546002600101546040518363ffffffff1660e01b81526004018083815260200182815260200192505050602060405180830381600087803b158015610ec957600080fd5b505af1158015610edd573d6000803e3d6000fd5b505050506040513d6020811015610ef357600080fd5b5050600254600454610f04916112e7565b6004556003805460010190556006546001600160a01b031615610f9e57600660009054906101000a90046001600160a01b03166001600160a01b031663e4fc6b6d6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7157600080fd5b505af1158015610f85573d6000803e3d6000fd5b505050506040513d6020811015610f9b57600080fd5b50505b6000610fa8610cc8565b905060007f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc6001600160a01b0316639358928b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561100557600080fd5b505afa158015611019573d6000803e3d6000fd5b505050506040513d602081101561102f57600080fd5b5051905080821161104457600060055561067e565b61104e82826113ff565b60055550505b565b6006546001600160a01b031681565b6000546001600160a01b031633146110b2576040805162461bcd60e51b815260206004820181905260248201526000805160206117cc833981519152604482015290519081900360640190fd5b600a55565b6007546001600160a01b031681565b600a5481565b6009546001600160a01b031681565b6110e3611713565b50336000818152600b602081815260408084208151608081018352815481526001820180548286019081526002840180548487015260038501805460ff8116151560608701529a8a5297875293889055908790559590915560ff1990951690925560095492518251637965d56d60e01b8152600481019190915291516001600160a01b039384169363c3a2a6659330937f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc90921692637965d56d92602480840193919291829003018186803b1580156111bb57600080fd5b505afa1580156111cf573d6000803e3d6000fd5b505050506040513d60208110156111e557600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b039093166004840152602483019190915251604480830192600092919082900301818387803b15801561123557600080fd5b505af1158015611249573d6000803e3d6000fd5b5050825161043492506001600160a01b037f000000000000000000000000c0d4ceb216b3ba9c3701b291766fdcba977cec3a1691503390611348565b6007546001600160a01b0316331461129c57600080fd5b6008546112a990826113ff565b600855600754610434906001600160a01b037f000000000000000000000000cc94faf235cc5d3bf4bed3a30db5984306c86abc81169116308461139f565b600082820183811015611341576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261139a908490611441565b505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526113f9908590611441565b50505050565b600061134183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506114f2565b6060611496826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115899092919063ffffffff16565b80519091501561139a578080602001905160208110156114b557600080fd5b505161139a5760405162461bcd60e51b815260040180806020018281038252602a8152602001806117ec602a913960400191505060405180910390fd5b600081848411156115815760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561154657818101518382015260200161152e565b50505050905090810190601f1680156115735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061159884846000856115a0565b949350505050565b60606115ab8561170d565b6115fc576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061163b5780518252601f19909201916020918201910161161c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461169d576040519150601f19603f3d011682016040523d82523d6000602084013e6116a2565b606091505b509150915081156116b65791506115989050565b8051156116c65780518082602001fd5b60405162461bcd60e51b815260206004820181815286516024840152865187939192839260440191908501908083836000831561154657818101518382015260200161152e565b3b151590565b6040518060800160405280600081526020016000815260200160008152602001600015158152509056fe4c6f636b65722063616e6e6f7420626520736574206d6f7265207468616e206f6e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573735761726d75702063616e6e6f7420626520736574206d6f7265207468616e206f6e63654f776e61626c653a206d757374206265206e6577206f776e657220746f2070756c6c4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122007099e9dba3fd3df5ab44891b0d4ba01592ecb39757d1359d9d7aca12ba0258364736f6c63430007050033

Verified Source Code Full Match

Compiler: v0.7.5+commit.eb77ed08 EVM: istanbul Optimization: Yes (200 runs)
Staking.sol 746 lines
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;

library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }
}

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

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

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

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

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

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

  /**
   * @dev Emitted when `value` tokens are moved from one account (`from`) to
   * another (`to`).
   *
   * Note that `value` may be zero.
   */
  event Transfer(address indexed from, address indexed to, uint256 value);

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

library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }

  /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.3._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.3._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }

    function addressToString(address _address) internal pure returns(string memory) {
        bytes32 _bytes = bytes32(uint256(_address));
        bytes memory HEX = "0123456789abcdef";
        bytes memory _addr = new bytes(42);

        _addr[0] = '0';
        _addr[1] = 'x';

        for(uint256 i = 0; i < 20; i++) {
            _addr[2+i*2] = HEX[uint8(_bytes[i + 12] >> 4)];
            _addr[3+i*2] = HEX[uint8(_bytes[i + 12] & 0x0f)];
        }

        return string(_addr);

    }
}

library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

interface IOwnable {
  function manager() external view returns (address);

  function renounceManagement() external;
  
  function pushManagement( address newOwner_ ) external;
  
  function pullManagement() external;
}

contract Ownable is IOwnable {

    address internal _owner;
    address internal _newOwner;

    event OwnershipPushed(address indexed previousOwner, address indexed newOwner);
    event OwnershipPulled(address indexed previousOwner, address indexed newOwner);

    constructor () {
        _owner = msg.sender;
        emit OwnershipPushed( address(0), _owner );
    }

    function manager() public view override returns (address) {
        return _owner;
    }

    modifier onlyManager() {
        require( _owner == msg.sender, "Ownable: caller is not the owner" );
        _;
    }

    function renounceManagement() public virtual override onlyManager() {
        emit OwnershipPushed( _owner, address(0) );
        _owner = address(0);
    }

    function pushManagement( address newOwner_ ) public virtual override onlyManager() {
        require( newOwner_ != address(0), "Ownable: new owner is the zero address");
        emit OwnershipPushed( _owner, newOwner_ );
        _newOwner = newOwner_;
    }
    
    function pullManagement() public virtual override {
        require( msg.sender == _newOwner, "Ownable: must be new owner to pull");
        emit OwnershipPulled( _owner, _newOwner );
        _owner = _newOwner;
    }
}

interface IsBTRFLY {
    function rebase( uint256 btrflyProfit_, uint epoch_) external returns (uint256);

    function circulatingSupply() external view returns (uint256);

    function balanceOf(address who) external view returns (uint256);

    function gonsForBalance( uint amount ) external view returns ( uint );

    function balanceForGons( uint gons ) external view returns ( uint );
    
    function index() external view returns ( uint );
}

interface IWarmup {
    function retrieve( address staker_, uint amount_ ) external;
}

interface IDistributor {
    function distribute() external returns ( bool );
}

contract REDACTEDStaking is Ownable {

    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    address public immutable BTRFLY;
    address public immutable sBTRFLY;

    struct Epoch {
        uint length;
        uint number;
        uint endBlock;
        uint distribute;
    }
    Epoch public epoch;

    address public distributor;
    
    address public locker;
    uint public totalBonus;
    
    address public warmupContract;
    uint public warmupPeriod;
    
    constructor ( 
        address _BTRFLY, 
        address _sBTRFLY, 
        uint _epochLength,
        uint _firstEpochNumber,
        uint _firstEpochBlock
    ) {
        require( _BTRFLY != address(0) );
        BTRFLY = _BTRFLY;
        require( _sBTRFLY != address(0) );
        sBTRFLY = _sBTRFLY;
        
        epoch = Epoch({
            length: _epochLength,
            number: _firstEpochNumber,
            endBlock: _firstEpochBlock,
            distribute: 0
        });
    }

    struct Claim {
        uint deposit;
        uint gons;
        uint expiry;
        bool lock; // prevents malicious delays
    }
    mapping( address => Claim ) public warmupInfo;

    /**
        @notice stake BTRFLY to enter warmup
        @param _amount uint
        @return bool
     */
    function stake( uint _amount, address _recipient ) external returns ( bool ) {
        rebase();
        
        IERC20( BTRFLY ).safeTransferFrom( msg.sender, address(this), _amount );

        Claim memory info = warmupInfo[ _recipient ];
        require( !info.lock, "Deposits for account are locked" );

        warmupInfo[ _recipient ] = Claim ({
            deposit: info.deposit.add( _amount ),
            gons: info.gons.add( IsBTRFLY( sBTRFLY ).gonsForBalance( _amount ) ),
            expiry: epoch.number.add( warmupPeriod ),
            lock: false
        });
        
        IERC20( sBTRFLY ).safeTransfer( warmupContract, _amount );
        return true;
    }

    /**
        @notice retrieve sBTRFLY from warmup
        @param _recipient address
     */
    function claim ( address _recipient ) public {
        Claim memory info = warmupInfo[ _recipient ];
        if ( epoch.number >= info.expiry && info.expiry != 0 ) {
            delete warmupInfo[ _recipient ];
            IWarmup( warmupContract ).retrieve( _recipient, IsBTRFLY( sBTRFLY ).balanceForGons( info.gons ) );
        }
    }

    /**
        @notice forfeit sBTRFLY in warmup and retrieve BTRFLY
     */
    function forfeit() external {
        Claim memory info = warmupInfo[ msg.sender ];
        delete warmupInfo[ msg.sender ];

        IWarmup( warmupContract ).retrieve( address(this), IsBTRFLY( sBTRFLY ).balanceForGons( info.gons ) );
        IERC20( BTRFLY ).safeTransfer( msg.sender, info.deposit );
    }

    /**
        @notice prevent new deposits to address (protection from malicious activity)
     */
    function toggleDepositLock() external {
        warmupInfo[ msg.sender ].lock = !warmupInfo[ msg.sender ].lock;
    }

    /**
        @notice redeem sBTRFLY for BTRFLY
        @param _amount uint
        @param _trigger bool
     */
    function unstake( uint _amount, bool _trigger ) external {
        if ( _trigger ) {
            rebase();
        }
        IERC20( sBTRFLY ).safeTransferFrom( msg.sender, address(this), _amount );
        IERC20( BTRFLY ).safeTransfer( msg.sender, _amount );
    }

    /**
        @notice returns the sBTRFLY index, which tracks rebase growth
        @return uint
     */
    function index() public view returns ( uint ) {
        return IsBTRFLY( sBTRFLY ).index();
    }

    /**
        @notice trigger rebase if epoch over
     */
    function rebase() public {
        if( epoch.endBlock <= block.number ) {

            IsBTRFLY( sBTRFLY ).rebase( epoch.distribute, epoch.number );

            epoch.endBlock = epoch.endBlock.add( epoch.length );
            epoch.number++;
            
            if ( distributor != address(0) ) {
                IDistributor( distributor ).distribute();
            }

            uint balance = contractBalance();
            uint staked = IsBTRFLY( sBTRFLY ).circulatingSupply();

            if( balance <= staked ) {
                epoch.distribute = 0;
            } else {
                epoch.distribute = balance.sub( staked );
            }
        }
    }

    /**
        @notice returns contract BTRFLY holdings, including bonuses provided
        @return uint
     */
    function contractBalance() public view returns ( uint ) {
        return IERC20( BTRFLY ).balanceOf( address(this) ).add( totalBonus );
    }

    /**
        @notice provide bonus to locked staking contract
        @param _amount uint
     */
    function giveLockBonus( uint _amount ) external {
        require( msg.sender == locker );
        totalBonus = totalBonus.add( _amount );
        IERC20( sBTRFLY ).safeTransfer( locker, _amount );
    }

    /**
        @notice reclaim bonus from locked staking contract
        @param _amount uint
     */
    function returnLockBonus( uint _amount ) external {
        require( msg.sender == locker );
        totalBonus = totalBonus.sub( _amount );
        IERC20( sBTRFLY ).safeTransferFrom( locker, address(this), _amount );
    }

    enum CONTRACTS { DISTRIBUTOR, WARMUP, LOCKER }

    /**
        @notice sets the contract address for LP staking
        @param _contract address
     */
    function setContract( CONTRACTS _contract, address _address ) external onlyManager() {
        if( _contract == CONTRACTS.DISTRIBUTOR ) { // 0
            distributor = _address;
        } else if ( _contract == CONTRACTS.WARMUP ) { // 1
            require( warmupContract == address( 0 ), "Warmup cannot be set more than once" );
            warmupContract = _address;
        } else if ( _contract == CONTRACTS.LOCKER ) { // 2
            require( locker == address(0), "Locker cannot be set more than once" );
            locker = _address;
        }
    }
    
    /**
     * @notice set warmup period for new stakers
     * @param _warmupPeriod uint
     */
    function setWarmup( uint _warmupPeriod ) external onlyManager() {
        warmupPeriod = _warmupPeriod;
    }
}

Read Contract

BTRFLY 0x22443c10 → address
contractBalance 0x8b7afe2e → uint256
distributor 0xbfe10928 → address
epoch 0x900cf0cf → uint256, uint256, uint256, uint256
index 0x2986c0e5 → uint256
locker 0xd7b96d4e → address
manager 0x481c6a75 → address
sBTRFLY 0x9e5722f9 → address
totalBonus 0xa8dd07dc → uint256
warmupContract 0xed4acaa8 → address
warmupInfo 0x6746f4c2 → uint256, uint256, uint256, bool
warmupPeriod 0xdeac361a → uint256

Write Contract 13 functions

These functions modify contract state and require a wallet transaction to execute.

claim 0x1e83409a
address _recipient
forfeit 0xf3d86e4a
No parameters
giveLockBonus 0x03c23670
uint256 _amount
pullManagement 0x5a96ac0a
No parameters
pushManagement 0x46f68ee9
address newOwner_
rebase 0xaf14052c
No parameters
renounceManagement 0x089208d8
No parameters
returnLockBonus 0xf62ae76a
uint256 _amount
setContract 0x865e6fd3
uint8 _contract
address _address
setWarmup 0xc9f464ff
uint256 _warmupPeriod
stake 0x7acb7757
uint256 _amount
address _recipient
returns: bool
toggleDepositLock 0x8f077b83
No parameters
unstake 0x9ebea88c
uint256 _amount
bool _trigger

Recent Transactions

This address has 1 on-chain transactions, but only 1.3% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →