Contract 0x4c142ef96bf46e65df8c49d7502252d9cba030b5

 
 
Txn Hash
Method
Block
From
To
Value [Txn Fee]
0xb19fccf2210d7c5076b799bdff4d179a34e8ca1b4bb1bae26c850ab0fe483467Notify Reward Am...401479962023-03-09 14:10:2879 days 16 hrs ago0x2408e836ebfcf135731df4cf357c10a7b65193bf IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.187903117893 228.420035343
0xdc8476ebeb8e4ca05267f60ec018e544687af2d20f4eef7d15f440b1fd42fb02Notify Reward Am...341372122022-10-09 18:40:39230 days 11 hrs ago 0xclearnproject.nft  IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.004962867 39
0x3f1a04d3f2c037c7c46e44b92e7d3c7ec3c12ea1819483df1cee6314606d771eNotify Reward Am...341369032022-10-09 18:30:05230 days 12 hrs ago 0xclearnproject.nft  IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.016909893 39
0x56343238935b1f84962e93126d7fc213f527a03a1cc685fa3275c8aa8ee1b4a5Notify Reward Am...341367732022-10-09 18:25:37230 days 12 hrs ago 0xclearnproject.nft  IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.006503445 39
0x9c652255281e60424766fdc73feff5d11bcbbebb68593fae8aa3f3acde1cb577Notify Reward Am...327487482022-09-06 4:11:54264 days 2 hrs ago0x320e732862e03b164abbb69e86f560b1c0c70122 IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.0047053836
0x5eb2b0d84d5cc4523385c0e80746bf29411332efe3a3f231ac1f101957e6e25fNotify Reward Am...318960482022-08-14 21:46:11286 days 8 hrs ago0x694b5ebd3fe3a91f348d6764239b4c8d11491103 IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.00627384 48
0xf3e2e3923d38b7b6ef9c7d22fee96b4001009a68cb1545804a5cc3f7d4689138Notify Reward Am...311078162022-07-25 2:48:08307 days 3 hrs ago0xd64e5de2d257f9a093cc108f9420f449657b07f1 IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.006403957 49
0x7c9365ed172b13064a9a7c47f866483ee9c4366e2bf19ea9ab41e716c2253bedNotify Reward Am...300741742022-06-27 22:02:10334 days 8 hrs ago0x89113b648fc83d52b3956976b9a41e2e56d32cae IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.005882265 45
0xa279a908fe79e7e9fbdf44e3ef0df8e323b1168ffc310d8628427db0dc522224Notify Reward Am...298705512022-06-22 14:37:33339 days 15 hrs ago0x49bbefa1d94702c0e9a5eaddec7c3c5d3eb9086b IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.01734283522 132.686853761
0xa149641cffb5f9e3c7ba0bd203f4c627f9d21a88dc5b70ed11c2f3074cfd5914Notify Reward Am...298551352022-06-22 4:51:47340 days 1 hr ago0x4a170561126a1d765a6b80a081db639945a8b53b IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.0153091 100
0x9909a757857a29fbcdf97f63b1511578b4e3558c7ee858debca120469262ccd3Notify Reward Am...291840842022-06-05 5:44:56357 days 45 mins ago0x4a170561126a1d765a6b80a081db639945a8b53b IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.0153091 100
0x8ffa49d0ecbecc66e8578d04f4c0d9286a9ffa241b0a6c2c2ff5ae7bc921b57aNotify Reward Am...291542672022-06-04 12:15:00357 days 18 hrs ago0xd77be683836b65125626b19f491693bf02c9599f IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.005665185 45
0xd84a2774b3b072c759be36436b7d41b782eaccf4f2798466a4ee7cca6fb6eff0Notify Reward Am...289240242022-05-29 19:31:17363 days 10 hrs ago0x447782d80c55056d0d86876db656790f0637b79a IN  0x4c142ef96bf46e65df8c49d7502252d9cba030b50 MATIC0.008162812 49
[ Download CSV Export 
Latest 1 internal transaction
Parent Txn Hash Block From To Value
0x2c34752d8120a6e41c50b0fe56df0cb7c155756a5daa1a05e3fdb015f0463c76284102162022-05-17 1:11:58376 days 5 hrs ago 0x7add42d9c53df14c1bc2507034f63b0ac924345f  Contract Creation0 MATIC
[ Download CSV Export 
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x76ff85109C9236101961784D5F779e25Cec85C10

Contract Name:
Bribe

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 14 : Bribe.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

import "../../interface/IBribe.sol";
import "../../interface/IERC721.sol";
import "../../interface/IVoter.sol";
import "../../interface/IVe.sol";
import "./MultiRewardsPoolBase.sol";

/// @title Bribes pay out rewards for a given pool based on the votes
///        that were received from the user (goes hand in hand with Gauges.vote())
contract Bribe is IBribe, MultiRewardsPoolBase {

  /// @dev Only voter can modify balances (since it only happens on vote())
  address public immutable voter;
  address public immutable ve;

  // Assume that will be created from voter contract through factory
  constructor(
    address _voter,
    address[] memory _allowedRewardTokens
  ) MultiRewardsPoolBase(address(0), _voter, _allowedRewardTokens) {
    voter = _voter;
    ve = IVoter(_voter).ve();
  }

  function getReward(uint tokenId, address[] memory tokens) external {
    require(IVe(ve).isApprovedOrOwner(msg.sender, tokenId), "Not token owner");
    _getReward(_tokenIdToAddress(tokenId), tokens, msg.sender);
  }

  /// @dev Used by Voter to allow batched reward claims
  function getRewardForOwner(uint tokenId, address[] memory tokens) external override {
    require(msg.sender == voter, "Not voter");
    address owner = IERC721(ve).ownerOf(tokenId);
    _getReward(_tokenIdToAddress(tokenId), tokens, owner);
  }

  /// @dev This is an external function, but internal notation is used
  ///      since it can only be called "internally" from Gauges
  function _deposit(uint amount, uint tokenId) external override {
    require(msg.sender == voter, "Not voter");
    require(amount > 0, "Zero amount");

    address adr = _tokenIdToAddress(tokenId);
    _increaseBalance(adr, amount);
    emit Deposit(adr, amount);
  }

  function _withdraw(uint amount, uint tokenId) external override {
    require(msg.sender == voter, "Not voter");
    require(amount > 0, "Zero amount");

    address adr = _tokenIdToAddress(tokenId);
    _decreaseBalance(adr, amount);
    emit Withdraw(adr, amount);
  }

  /// @dev Used to notify a gauge/bribe of a given reward,
  ///      this can create griefing attacks by extending rewards
  function notifyRewardAmount(address token, uint amount) external override {
    _notifyRewardAmount(token, amount);
  }

  // use tokenId instead of address for

  function tokenIdToAddress(uint tokenId) external pure returns (address) {
    return _tokenIdToAddress(tokenId);
  }

  function _tokenIdToAddress(uint tokenId) internal pure returns (address) {
    address adr = address(uint160(tokenId));
    require(_addressToTokenId(adr) == tokenId, "Wrong convert");
    return adr;
  }

  function addressToTokenId(address adr) external pure returns (uint) {
    return _addressToTokenId(adr);
  }

  function _addressToTokenId(address adr) internal pure returns (uint) {
    return uint(uint160(adr));
  }

}

File 2 of 14 : IBribe.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface IBribe {

  function notifyRewardAmount(address token, uint amount) external;

  function _deposit(uint amount, uint tokenId) external;

  function _withdraw(uint amount, uint tokenId) external;

  function getRewardForOwner(uint tokenId, address[] memory tokens) external;

}

File 3 of 14 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
  /**
   * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
   */
  event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

  /**
   * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
   */
  event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

  /**
   * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
   */
  event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

  /**
   * @dev Returns the number of tokens in ``owner``'s account.
   */
  function balanceOf(address owner) external view returns (uint256 balance);

  /**
   * @dev Returns the owner of the `tokenId` token.
   *
   * Requirements:
   *
   * - `tokenId` must exist.
   */
  function ownerOf(uint256 tokenId) external view returns (address owner);

  /**
   * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
   * are aware of the ERC721 protocol to prevent tokens from being forever locked.
   *
   * Requirements:
   *
   * - `from` cannot be the zero address.
   * - `to` cannot be the zero address.
   * - `tokenId` token must exist and be owned by `from`.
   * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
   * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
   *
   * Emits a {Transfer} event.
   */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId
  ) external;

  /**
   * @dev Transfers `tokenId` token from `from` to `to`.
   *
   * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
   *
   * Requirements:
   *
   * - `from` cannot be the zero address.
   * - `to` cannot be the zero address.
   * - `tokenId` token must be owned by `from`.
   * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
   *
   * Emits a {Transfer} event.
   */
  function transferFrom(
    address from,
    address to,
    uint256 tokenId
  ) external;

  /**
   * @dev Gives permission to `to` to transfer `tokenId` token to another account.
   * The approval is cleared when the token is transferred.
   *
   * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
   *
   * Requirements:
   *
   * - The caller must own the token or be an approved operator.
   * - `tokenId` must exist.
   *
   * Emits an {Approval} event.
   */
  function approve(address to, uint256 tokenId) external;

  /**
   * @dev Returns the account approved for `tokenId` token.
   *
   * Requirements:
   *
   * - `tokenId` must exist.
   */
  function getApproved(uint256 tokenId) external view returns (address operator);

  /**
   * @dev Approve or remove `operator` as an operator for the caller.
   * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
   *
   * Requirements:
   *
   * - The `operator` cannot be the caller.
   *
   * Emits an {ApprovalForAll} event.
   */
  function setApprovalForAll(address operator, bool _approved) external;

  /**
   * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
   *
   * See {setApprovalForAll}
   */
  function isApprovedForAll(address owner, address operator) external view returns (bool);

  /**
   * @dev Safely transfers `tokenId` token from `from` to `to`.
   *
   * Requirements:
   *
   * - `from` cannot be the zero address.
   * - `to` cannot be the zero address.
   * - `tokenId` token must exist and be owned by `from`.
   * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
   * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
   *
   * Emits a {Transfer} event.
   */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes calldata data
  ) external;
}

File 4 of 14 : IVoter.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface IVoter {

  function ve() external view returns (address);

  function attachTokenToGauge(uint _tokenId, address account) external;

  function detachTokenFromGauge(uint _tokenId, address account) external;

  function emitDeposit(uint _tokenId, address account, uint amount) external;

  function emitWithdraw(uint _tokenId, address account, uint amount) external;

  function distribute(address _gauge) external;

  function notifyRewardAmount(uint amount) external;

}

File 5 of 14 : IVe.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface IVe {

  enum DepositType {
    DEPOSIT_FOR_TYPE,
    CREATE_LOCK_TYPE,
    INCREASE_LOCK_AMOUNT,
    INCREASE_UNLOCK_TIME,
    MERGE_TYPE
  }

  struct Point {
    int128 bias;
    int128 slope; // # -dweight / dt
    uint ts;
    uint blk; // block
  }
  /* We cannot really do block numbers per se b/c slope is per time, not per block
  * and per block could be fairly bad b/c Ethereum changes blocktimes.
  * What we can do is to extrapolate ***At functions */

  struct LockedBalance {
    int128 amount;
    uint end;
  }

  function token() external view returns (address);

  function balanceOfNFT(uint) external view returns (uint);

  function isApprovedOrOwner(address, uint) external view returns (bool);

  function createLockFor(uint, uint, address) external returns (uint);

  function userPointEpoch(uint tokenId) external view returns (uint);

  function epoch() external view returns (uint);

  function userPointHistory(uint tokenId, uint loc) external view returns (Point memory);

  function pointHistory(uint loc) external view returns (Point memory);

  function checkpoint() external;

  function depositFor(uint tokenId, uint value) external;

  function attachToken(uint tokenId) external;

  function detachToken(uint tokenId) external;

  function voting(uint tokenId) external;

  function abstain(uint tokenId) external;
}

File 6 of 14 : MultiRewardsPoolBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

import "../../interface/IERC20.sol";
import "../../interface/IMultiRewardsPool.sol";
import "../../lib/Math.sol";
import "../../lib/SafeERC20.sol";
import "../../lib/CheckpointLib.sol";
import "../Reentrancy.sol";

abstract contract MultiRewardsPoolBase is Reentrancy, IMultiRewardsPool {
  using SafeERC20 for IERC20;
  using CheckpointLib for mapping(uint => CheckpointLib.Checkpoint);

  /// @dev Operator can add/remove reward tokens
  address public operator;

  /// @dev The LP token that needs to be staked for rewards
  address public immutable override underlying;

  uint public override derivedSupply;
  mapping(address => uint) public override derivedBalances;

  /// @dev Rewards are released over 7 days
  uint internal constant DURATION = 7 days;
  uint internal constant PRECISION = 10 ** 18;
  uint internal constant MAX_REWARD_TOKENS = 10;

  /// Default snx staking contract implementation
  /// https://github.com/Synthetixio/synthetix/blob/develop/contracts/StakingRewards.sol

  /// @dev Reward rate with precision 1e18
  mapping(address => uint) public rewardRate;
  mapping(address => uint) public periodFinish;
  mapping(address => uint) public lastUpdateTime;
  mapping(address => uint) public rewardPerTokenStored;

  mapping(address => mapping(address => uint)) public lastEarn;
  mapping(address => mapping(address => uint)) public userRewardPerTokenStored;

  uint public override totalSupply;
  mapping(address => uint) public override balanceOf;

  address[] public override rewardTokens;
  mapping(address => bool) public override isRewardToken;

  /// @notice A record of balance checkpoints for each account, by index
  mapping(address => mapping(uint => CheckpointLib.Checkpoint)) public checkpoints;
  /// @notice The number of checkpoints for each account
  mapping(address => uint) public numCheckpoints;
  /// @notice A record of balance checkpoints for each token, by index
  mapping(uint => CheckpointLib.Checkpoint) public supplyCheckpoints;
  /// @notice The number of checkpoints
  uint public supplyNumCheckpoints;
  /// @notice A record of balance checkpoints for each token, by index
  mapping(address => mapping(uint => CheckpointLib.Checkpoint)) public rewardPerTokenCheckpoints;
  /// @notice The number of checkpoints for each token
  mapping(address => uint) public rewardPerTokenNumCheckpoints;

  event Deposit(address indexed from, uint amount);
  event Withdraw(address indexed from, uint amount);
  event NotifyReward(address indexed from, address indexed reward, uint amount);
  event ClaimRewards(address indexed from, address indexed reward, uint amount, address recepient);

  constructor(address _stake, address _operator, address[] memory _allowedRewardTokens) {
    underlying = _stake;
    operator = _operator;
    for (uint i; i < _allowedRewardTokens.length; i++) {
      if (_allowedRewardTokens[i] != address(0)) {
        _registerRewardToken(_allowedRewardTokens[i]);
      }
    }
  }

  modifier onlyOperator() {
    require(msg.sender == operator, "Not operator");
    _;
  }

  //**************************************************************************
  //************************ VIEWS *******************************************
  //**************************************************************************

  function rewardTokensLength() external view override returns (uint) {
    return rewardTokens.length;
  }

  function rewardPerToken(address token) external view returns (uint) {
    return _rewardPerToken(token);
  }

  function _rewardPerToken(address token) internal view returns (uint) {
    if (derivedSupply == 0) {
      return rewardPerTokenStored[token];
    }
    return rewardPerTokenStored[token]
    + (
    (_lastTimeRewardApplicable(token) - Math.min(lastUpdateTime[token], periodFinish[token]))
    * rewardRate[token]
    / derivedSupply
    );
  }

  function derivedBalance(address account) external view override returns (uint) {
    return _derivedBalance(account);
  }

  function left(address token) external view override returns (uint) {
    if (block.timestamp >= periodFinish[token]) return 0;
    uint _remaining = periodFinish[token] - block.timestamp;
    return _remaining * rewardRate[token] / PRECISION;
  }

  function earned(address token, address account) external view override returns (uint) {
    return _earned(token, account);
  }

  //**************************************************************************
  //************************ OPERATOR ACTIONS ********************************
  //**************************************************************************

  function registerRewardToken(address token) external onlyOperator {
    _registerRewardToken(token);
  }

  function _registerRewardToken(address token) internal {
    require(rewardTokens.length < MAX_REWARD_TOKENS, "Too many reward tokens");
    require(!isRewardToken[token], "Already registered");
    isRewardToken[token] = true;
    rewardTokens.push(token);
  }

  function removeRewardToken(address token) external onlyOperator {
    require(periodFinish[token] < block.timestamp, "Rewards not ended");
    require(isRewardToken[token], "Not reward token");

    isRewardToken[token] = false;
    uint length = rewardTokens.length;
    require(length > 3, "First 3 tokens should not be removed");
    // keep 3 tokens as guarantee against malicious actions
    // assume it will be DYST + pool tokens
    uint i = 3;
    bool found = false;
    for (; i < length; i++) {
      address t = rewardTokens[i];
      if (t == token) {
        found = true;
        break;
      }
    }
    require(found, "First tokens forbidden to remove");
    rewardTokens[i] = rewardTokens[length - 1];
    rewardTokens.pop();
  }

  //**************************************************************************
  //************************ USER ACTIONS ************************************
  //**************************************************************************

  function _deposit(uint amount) internal virtual lock {
    require(amount > 0, "Zero amount");
    _increaseBalance(msg.sender, amount);
    IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount);
    emit Deposit(msg.sender, amount);
  }

  function _increaseBalance(address account, uint amount) internal virtual {
    _updateRewardForAllTokens();

    totalSupply += amount;
    balanceOf[account] += amount;

    _updateDerivedBalanceAndWriteCheckpoints(account);
  }

  function _withdraw(uint amount) internal lock virtual {
    _decreaseBalance(msg.sender, amount);
    IERC20(underlying).safeTransfer(msg.sender, amount);
    emit Withdraw(msg.sender, amount);
  }

  function _decreaseBalance(address account, uint amount) internal virtual {
    _updateRewardForAllTokens();

    totalSupply -= amount;
    balanceOf[account] -= amount;

    _updateDerivedBalanceAndWriteCheckpoints(account);
  }

  /// @dev Implement restriction checks!
  function _getReward(address account, address[] memory tokens, address recipient) internal lock virtual {

    for (uint i = 0; i < tokens.length; i++) {
      (rewardPerTokenStored[tokens[i]], lastUpdateTime[tokens[i]]) = _updateRewardPerToken(tokens[i], type(uint).max, true);

      uint _reward = _earned(tokens[i], account);
      lastEarn[tokens[i]][account] = block.timestamp;
      userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[tokens[i]];
      if (_reward > 0) {
        IERC20(tokens[i]).safeTransfer(recipient, _reward);
      }

      emit ClaimRewards(msg.sender, tokens[i], _reward, recipient);
    }

    _updateDerivedBalanceAndWriteCheckpoints(account);
  }

  function _updateDerivedBalanceAndWriteCheckpoints(address account) internal {
    uint __derivedBalance = derivedBalances[account];
    derivedSupply -= __derivedBalance;
    __derivedBalance = _derivedBalance(account);
    derivedBalances[account] = __derivedBalance;
    derivedSupply += __derivedBalance;

    _writeCheckpoint(account, __derivedBalance);
    _writeSupplyCheckpoint();
  }

  //**************************************************************************
  //************************ REWARDS CALCULATIONS ****************************
  //**************************************************************************

  // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run
  function _earned(address token, address account) internal view returns (uint) {
    // zero checkpoints means zero deposits
    if (numCheckpoints[account] == 0) {
      return 0;
    }
    // last claim rewards time
    uint _startTimestamp = Math.max(lastEarn[token][account], rewardPerTokenCheckpoints[token][0].timestamp);

    // find an index of the balance that the user had on the last claim
    uint _startIndex = _getPriorBalanceIndex(account, _startTimestamp);
    uint _endIndex = numCheckpoints[account] - 1;

    uint reward = 0;

    // calculate previous snapshots if exist
    if (_endIndex > 0) {
      for (uint i = _startIndex; i <= _endIndex - 1; i++) {
        CheckpointLib.Checkpoint memory cp0 = checkpoints[account][i];
        CheckpointLib.Checkpoint memory cp1 = checkpoints[account][i + 1];
        (uint _rewardPerTokenStored0,) = _getPriorRewardPerToken(token, cp0.timestamp);
        (uint _rewardPerTokenStored1,) = _getPriorRewardPerToken(token, cp1.timestamp);
        reward += cp0.value * (_rewardPerTokenStored1 - _rewardPerTokenStored0) / PRECISION;
      }
    }

    CheckpointLib.Checkpoint memory cp = checkpoints[account][_endIndex];
    (uint _rewardPerTokenStored,) = _getPriorRewardPerToken(token, cp.timestamp);
    reward += cp.value * (_rewardPerToken(token) - Math.max(_rewardPerTokenStored, userRewardPerTokenStored[token][account])) / PRECISION;
    return reward;
  }

  function _derivedBalance(address account) internal virtual view returns (uint) {
    // supposed to be implemented in a parent contract
    return balanceOf[account];
  }

  /// @dev Update stored rewardPerToken values without the last one snapshot
  ///      If the contract will get "out of gas" error on users actions this will be helpful
  function batchUpdateRewardPerToken(address token, uint maxRuns) external {
    (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, maxRuns, false);
  }

  function _updateRewardForAllTokens() internal {
    uint length = rewardTokens.length;
    for (uint i; i < length; i++) {
      address token = rewardTokens[i];
      (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true);
    }
  }

  /// @dev Should be called only with properly updated snapshots, or with actualLast=false
  function _updateRewardPerToken(address token, uint maxRuns, bool actualLast) internal returns (uint, uint) {
    uint _startTimestamp = lastUpdateTime[token];
    uint reward = rewardPerTokenStored[token];

    if (supplyNumCheckpoints == 0) {
      return (reward, _startTimestamp);
    }

    if (rewardRate[token] == 0) {
      return (reward, block.timestamp);
    }
    uint _startIndex = _getPriorSupplyIndex(_startTimestamp);
    uint _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);

    if (_endIndex > 0) {
      for (uint i = _startIndex; i <= _endIndex - 1; i++) {
        CheckpointLib.Checkpoint memory sp0 = supplyCheckpoints[i];
        if (sp0.value > 0) {
          CheckpointLib.Checkpoint memory sp1 = supplyCheckpoints[i + 1];
          (uint _reward, uint _endTime) = _calcRewardPerToken(
            token,
            sp1.timestamp,
            sp0.timestamp,
            sp0.value,
            _startTimestamp
          );
          reward += _reward;
          _writeRewardPerTokenCheckpoint(token, reward, _endTime);
          _startTimestamp = _endTime;
        }
      }
    }

    // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions
    if (actualLast) {
      CheckpointLib.Checkpoint memory sp = supplyCheckpoints[_endIndex];
      if (sp.value > 0) {
        (uint _reward,) = _calcRewardPerToken(token, _lastTimeRewardApplicable(token), Math.max(sp.timestamp, _startTimestamp), sp.value, _startTimestamp);
        reward += _reward;
        _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);
        _startTimestamp = block.timestamp;
      }
    }

    return (reward, _startTimestamp);
  }

  function _calcRewardPerToken(
    address token,
    uint lastSupplyTs1,
    uint lastSupplyTs0,
    uint supply,
    uint startTimestamp
  ) internal view returns (uint, uint) {
    uint endTime = Math.max(lastSupplyTs1, startTimestamp);
    uint _periodFinish = periodFinish[token];
    return (
    (Math.min(endTime, _periodFinish) - Math.min(Math.max(lastSupplyTs0, startTimestamp), _periodFinish))
    * rewardRate[token] / supply
    , endTime);
  }

  /// @dev Returns the last time the reward was modified or periodFinish if the reward has ended
  function _lastTimeRewardApplicable(address token) internal view returns (uint) {
    return Math.min(block.timestamp, periodFinish[token]);
  }

  //**************************************************************************
  //************************ NOTIFY ******************************************
  //**************************************************************************

  function _notifyRewardAmount(address token, uint amount) internal lock virtual {
    require(token != underlying, "Wrong token for rewards");
    require(amount > 0, "Zero amount");
    require(isRewardToken[token], "Token not allowed");
    if (rewardRate[token] == 0) {
      _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);
    }
    (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true);

    if (block.timestamp >= periodFinish[token]) {
      IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
      rewardRate[token] = amount * PRECISION / DURATION;
    } else {
      uint _remaining = periodFinish[token] - block.timestamp;
      uint _left = _remaining * rewardRate[token];
      // not sure what the reason was in the original solidly implementation for this restriction
      // however, by design probably it is a good idea against human errors
      require(amount > _left / PRECISION, "Amount should be higher than remaining rewards");
      IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
      rewardRate[token] = (amount * PRECISION + _left) / DURATION;
    }

    periodFinish[token] = block.timestamp + DURATION;
    emit NotifyReward(msg.sender, token, amount);
  }

  //**************************************************************************
  //************************ CHECKPOINTS *************************************
  //**************************************************************************

  function getPriorBalanceIndex(address account, uint timestamp) external view returns (uint) {
    return _getPriorBalanceIndex(account, timestamp);
  }

  /// @notice Determine the prior balance for an account as of a block number
  /// @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
  /// @param account The address of the account to check
  /// @param timestamp The timestamp to get the balance at
  /// @return The balance the account had as of the given block
  function _getPriorBalanceIndex(address account, uint timestamp) internal view returns (uint) {
    uint nCheckpoints = numCheckpoints[account];
    if (nCheckpoints == 0) {
      return 0;
    }
    return checkpoints[account].findLowerIndex(nCheckpoints, timestamp);
  }

  function getPriorSupplyIndex(uint timestamp) external view returns (uint) {
    return _getPriorSupplyIndex(timestamp);
  }

  function _getPriorSupplyIndex(uint timestamp) internal view returns (uint) {
    uint nCheckpoints = supplyNumCheckpoints;
    if (nCheckpoints == 0) {
      return 0;
    }
    return supplyCheckpoints.findLowerIndex(nCheckpoints, timestamp);
  }

  function getPriorRewardPerToken(address token, uint timestamp) external view returns (uint, uint) {
    return _getPriorRewardPerToken(token, timestamp);
  }

  function _getPriorRewardPerToken(address token, uint timestamp) internal view returns (uint, uint) {
    uint nCheckpoints = rewardPerTokenNumCheckpoints[token];
    if (nCheckpoints == 0) {
      return (0, 0);
    }
    mapping(uint => CheckpointLib.Checkpoint) storage cps = rewardPerTokenCheckpoints[token];
    uint lower = cps.findLowerIndex(nCheckpoints, timestamp);
    CheckpointLib.Checkpoint memory cp = cps[lower];
    return (cp.value, cp.timestamp);
  }

  function _writeCheckpoint(address account, uint balance) internal {
    uint _timestamp = block.timestamp;
    uint _nCheckPoints = numCheckpoints[account];

    if (_nCheckPoints > 0 && checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp) {
      checkpoints[account][_nCheckPoints - 1].value = balance;
    } else {
      checkpoints[account][_nCheckPoints] = CheckpointLib.Checkpoint(_timestamp, balance);
      numCheckpoints[account] = _nCheckPoints + 1;
    }
  }

  function _writeRewardPerTokenCheckpoint(address token, uint reward, uint timestamp) internal {
    uint _nCheckPoints = rewardPerTokenNumCheckpoints[token];

    if (_nCheckPoints > 0 && rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == timestamp) {
      rewardPerTokenCheckpoints[token][_nCheckPoints - 1].value = reward;
    } else {
      rewardPerTokenCheckpoints[token][_nCheckPoints] = CheckpointLib.Checkpoint(timestamp, reward);
      rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;
    }
  }

  function _writeSupplyCheckpoint() internal {
    uint _nCheckPoints = supplyNumCheckpoints;
    uint _timestamp = block.timestamp;

    if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) {
      supplyCheckpoints[_nCheckPoints - 1].value = derivedSupply;
    } else {
      supplyCheckpoints[_nCheckPoints] = CheckpointLib.Checkpoint(_timestamp, derivedSupply);
      supplyNumCheckpoints = _nCheckPoints + 1;
    }
  }
}

File 7 of 14 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
  /**
   * @dev Returns true if this contract implements the interface defined by
   * `interfaceId`. See the corresponding
   * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
   * to learn more about how these ids are created.
   *
   * This function call must use less than 30 000 gas.
   */
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 8 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
  /**
   * @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);
}

File 9 of 14 : IMultiRewardsPool.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface IMultiRewardsPool {

  function underlying() external view returns (address);

  function derivedSupply() external view returns (uint);

  function derivedBalances(address account) external view returns (uint);

  function totalSupply() external view returns (uint);

  function balanceOf(address account) external view returns (uint);

  function rewardTokens(uint id) external view returns (address);

  function isRewardToken(address token) external view returns (bool);

  function rewardTokensLength() external view returns (uint);

  function derivedBalance(address account) external view returns (uint);

  function left(address token) external view returns (uint);

  function earned(address token, address account) external view returns (uint);

  function registerRewardToken(address token) external;

  function removeRewardToken(address token) external;

}

File 10 of 14 : Math.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

library Math {

  function max(uint a, uint b) internal pure returns (uint) {
    return a >= b ? a : b;
  }

  function min(uint a, uint b) internal pure returns (uint) {
    return a < b ? a : b;
  }

  function positiveInt128(int128 value) internal pure returns (int128) {
    return value < 0 ? int128(0) : value;
  }

  function closeTo(uint a, uint b, uint target) internal pure returns (bool) {
    if (a > b) {
      if (a - b <= target) {
        return true;
      }
    } else {
      if (b - a <= target) {
        return true;
      }
    }
    return false;
  }

  function sqrt(uint y) internal pure returns (uint z) {
    if (y > 3) {
      z = y;
      uint x = y / 2 + 1;
      while (x < z) {
        z = x;
        x = (y / x + x) / 2;
      }
    } else if (y != 0) {
      z = 1;
    }
  }

}

File 11 of 14 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.13;

import "../interface/IERC20.sol";
import "./Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
  using Address for address;

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

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

  function safeIncreaseAllowance(
    IERC20 token,
    address spender,
    uint value
  ) internal {
    uint newAllowance = token.allowance(address(this), spender) + value;
    _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
      require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }
  }

}

File 12 of 14 : CheckpointLib.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

library CheckpointLib {

  /// @notice A checkpoint for uint value
  struct Checkpoint {
    uint timestamp;
    uint value;
  }

  function findLowerIndex(mapping(uint => Checkpoint) storage checkpoints, uint size, uint timestamp) internal view returns (uint) {
    require(size != 0, "Empty checkpoints");

    // First check most recent value
    if (checkpoints[size - 1].timestamp <= timestamp) {
      return (size - 1);
    }

    // Next check implicit zero value
    if (checkpoints[0].timestamp > timestamp) {
      return 0;
    }

    uint lower = 0;
    uint upper = size - 1;
    while (upper > lower) {
      // ceil, avoiding overflow
      uint center = upper - (upper - lower) / 2;
      Checkpoint memory cp = checkpoints[center];
      if (cp.timestamp == timestamp) {
        return center;
      } else if (cp.timestamp < timestamp) {
        lower = center;
      } else {
        upper = center - 1;
      }
    }
    return lower;
  }

}

File 13 of 14 : Reentrancy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

abstract contract Reentrancy {

  /// @dev simple re-entrancy check
  uint internal _unlocked = 1;

  modifier lock() {
    require(_unlocked == 1, "Reentrant call");
    _unlocked = 2;
    _;
    _unlocked = 1;
  }

}

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

pragma solidity ^0.8.13;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
  /**
   * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
  function isContract(address account) internal view returns (bool) {
    // This method relies on extcodesize/address.code.length, which returns 0
    // for contracts in construction, since the code is only stored at the end
    // of the constructor execution.

    return account.code.length > 0;
  }

  function functionCall(
    address target,
    bytes memory data,
    string memory errorMessage
  ) internal returns (bytes memory) {
    require(isContract(target), "Address: call to non-contract");
    (bool success, bytes memory returndata) = target.call(data);
    return verifyCallResult(success, returndata, errorMessage);
  }

  /**
   * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
  function verifyCallResult(
    bool success,
    bytes memory returndata,
    string memory errorMessage
  ) internal pure returns (bytes memory) {
    if (success) {
      return returndata;
    } else {
      // 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
        assembly {
          let returndata_size := mload(returndata)
          revert(add(32, returndata), returndata_size)
        }
      } else {
        revert(errorMessage);
      }
    }
  }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_voter","type":"address"},{"internalType":"address[]","name":"_allowedRewardTokens","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recepient","type":"address"}],"name":"ClaimRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NotifyReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"_deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"_withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"}],"name":"addressToTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"maxRuns","type":"uint256"}],"name":"batchUpdateRewardPerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"checkpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"derivedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"derivedBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"derivedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorBalanceIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorRewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorSupplyIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getRewardForOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isRewardToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"lastEarn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"left","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"registerRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardPerTokenCheckpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardPerTokenNumCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardTokensLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supplyCheckpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyNumCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenIdToAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60e060405260016000553480156200001657600080fd5b5060405162002db838038062002db88339810160408190526200003991620002cb565b60006080819052600180546001600160a01b0319166001600160a01b0385161790558282825b8151811015620000e25760006001600160a01b0316828281518110620000895762000089620003b4565b60200260200101516001600160a01b031614620000cd57620000cd828281518110620000b957620000b9620003b4565b60200260200101516200017a60201b60201c565b80620000d981620003ca565b9150506200005f565b50505050816001600160a01b031660a0816001600160a01b031681525050816001600160a01b0316631f8507166040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001659190620003f2565b6001600160a01b031660c05250620004179050565b600c54600a11620001d25760405162461bcd60e51b815260206004820152601660248201527f546f6f206d616e792072657761726420746f6b656e730000000000000000000060448201526064015b60405180910390fd5b6001600160a01b0381166000908152600d602052604090205460ff1615620002325760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481c9959da5cdd195c995960721b6044820152606401620001c9565b6001600160a01b03166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b0319169091179055565b80516001600160a01b0381168114620002b057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215620002df57600080fd5b620002ea8362000298565b602084810151919350906001600160401b03808211156200030a57600080fd5b818601915086601f8301126200031f57600080fd5b815181811115620003345762000334620002b5565b8060051b604051601f19603f830116810181811085821117156200035c576200035c620002b5565b6040529182528482019250838101850191898311156200037b57600080fd5b938501935b82851015620003a457620003948562000298565b8452938501939285019262000380565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b600060018201620003eb57634e487b7160e01b600052601160045260246000fd5b5060010190565b6000602082840312156200040557600080fd5b620004108262000298565b9392505050565b60805160a05160c051612947620004716000396000818161032501528181610be10152610dd00152600081816103df01528181610ac401528181610b8b0152610d0501526000818161045f015261178201526129476000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c80637bb7bed11161013b578063d35e2544116100b8578063f12297771161007c578063f122977714610631578063f320772314610644578063f5f8d36514610657578063f7412baf1461066a578063fd3140981461069157600080fd5b8063d35e2544146105d9578063d7da4bb0146105ec578063da09d19d146105f5578063e46dbc9814610615578063e8111a121461062857600080fd5b8063a7852afa116100ff578063a7852afa14610558578063aa4796521461056b578063b5fd73f81461058b578063b66503cf146105be578063bf199e62146105d157600080fd5b80637bb7bed1146104d457806399bcc052146104e75780639ce43f90146104fa5780639e2bf22c1461051a578063a495e5b51461052d57600080fd5b80633d509c97116101c957806368fcee1a1161018d57806368fcee1a146104475780636f307dc31461045a5780636fcfff451461048157806370a08231146104a157806376f4be36146104c157600080fd5b80633d509c97146103c557806346c96aac146103da578063570ca7351461040157806363fb415b146104145780636511bf2e1461043457600080fd5b80631f850716116102105780631f85071614610320578063211dc32d14610347578063221ca18c1461035a5780632ce9aead1461037a5780633ca068b61461039a57600080fd5b806301316ddf1461024d57806308bb76a5146102995780630cdfebfa146102c4578063115c6f39146102f657806318160ddd14610317575b600080fd5b61027f61025b3660046125a0565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b6102ac6102a73660046125cc565b6106a4565b6040516001600160a01b039091168152602001610290565b61027f6102d23660046125a0565b600e6020908152600092835260408084209091529082529020805460019091015482565b6103096103043660046125a0565b6106b5565b604051908152602001610290565b610309600a5481565b6102ac7f000000000000000000000000000000000000000000000000000000000000000081565b6103096103553660046125e5565b6106c8565b61030961036836600461261e565b60046020526000908152604090205481565b61030961038836600461261e565b60066020526000908152604090205481565b6103096103a83660046125e5565b600960209081526000928352604080842090915290825290205481565b6103d86103d336600461261e565b6106d4565b005b6102ac7f000000000000000000000000000000000000000000000000000000000000000081565b6001546102ac906001600160a01b031681565b61030961042236600461261e565b60036020526000908152604090205481565b61030961044236600461261e565b6109b4565b6103d86104553660046125a0565b6109c5565b6102ac7f000000000000000000000000000000000000000000000000000000000000000081565b61030961048f36600461261e565b600f6020526000908152604090205481565b6103096104af36600461261e565b600b6020526000908152604090205481565b6103096104cf3660046125cc565b6109ff565b6102ac6104e23660046125cc565b610a0a565b6103096104f536600461261e565b610a34565b61030961050836600461261e565b60076020526000908152604090205481565b6103d861052836600461263b565b610ab9565b61030961053b3660046125e5565b600860209081526000928352604080842090915290825290205481565b6103d8610566366004612673565b610b80565b61030961057936600461261e565b60136020526000908152604090205481565b6105ae61059936600461261e565b600d6020526000908152604090205460ff1681565b6040519015158152602001610290565b6103d86105cc3660046125a0565b610c6e565b600c54610309565b6103096105e736600461261e565b610c7c565b61030960025481565b61030961060336600461261e565b60056020526000908152604090205481565b6103d861062336600461261e565b610c9a565b61030960115481565b61030961063f36600461261e565b610cef565b6103d861065236600461263b565b610cfa565b6103d8610665366004612673565b610db4565b61027f6106783660046125cc565b6010602052600090815260409020805460019091015482565b61027f61069f3660046125a0565b610e94565b60006106af82610ead565b92915050565b60006106c18383610ef8565b9392505050565b60006106c18383610f4d565b6001546001600160a01b031633146107225760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b60448201526064015b60405180910390fd5b6001600160a01b038116600090815260056020526040902054421161077d5760405162461bcd60e51b815260206004820152601160248201527014995dd85c991cc81b9bdd08195b991959607a1b6044820152606401610719565b6001600160a01b0381166000908152600d602052604090205460ff166107d85760405162461bcd60e51b815260206004820152601060248201526f2737ba103932bbb0b932103a37b5b2b760811b6044820152606401610719565b6001600160a01b0381166000908152600d60205260409020805460ff19169055600c54600381116108575760405162461bcd60e51b8152602060048201526024808201527f4669727374203320746f6b656e732073686f756c64206e6f742062652072656d6044820152631bdd995960e21b6064820152608401610719565b600360005b828210156108b7576000600c838154811061087957610879612744565b6000918252602090912001546001600160a01b039081169150851681036108a45760019150506108b7565b50816108af81612770565b92505061085c565b806109045760405162461bcd60e51b815260206004820181905260248201527f466972737420746f6b656e7320666f7262696464656e20746f2072656d6f76656044820152606401610719565b600c610911600185612789565b8154811061092157610921612744565b600091825260209091200154600c80546001600160a01b03909216918490811061094d5761094d612744565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600c80548061098c5761098c6127a0565b600082815260209020810160001990810180546001600160a01b031916905501905550505050565b60006001600160a01b0382166106af565b6109d1828260006111ce565b6001600160a01b03909316600090815260076020908152604080832060069092529091209390935590915550565b60006106af826113be565b600c8181548110610a1a57600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0381166000908152600560205260408120544210610a5b57506000919050565b6001600160a01b038216600090815260056020526040812054610a7f904290612789565b6001600160a01b038416600090815260046020526040902054909150670de0b6b3a764000090610aaf90836127b6565b6106c191906127d5565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b015760405162461bcd60e51b8152600401610719906127f7565b60008211610b215760405162461bcd60e51b81526004016107199061281a565b6000610b2c82610ead565b9050610b3881846113e0565b806001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436484604051610b7391815260200190565b60405180910390a2505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610bc85760405162461bcd60e51b8152600401610719906127f7565b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c54919061283f565b9050610c69610c6284610ead565b8383611436565b505050565b610c788282611730565b5050565b6001600160a01b0381166000908152600b60205260408120546106af565b6001546001600160a01b03163314610ce35760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b6044820152606401610719565b610cec81611ac1565b50565b60006106af82611bd0565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d425760405162461bcd60e51b8152600401610719906127f7565b60008211610d625760405162461bcd60e51b81526004016107199061281a565b6000610d6d82610ead565b9050610d798184611c7b565b806001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c84604051610b7391815260200190565b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015610e1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e43919061285c565b610e815760405162461bcd60e51b815260206004820152600f60248201526e2737ba103a37b5b2b71037bbb732b960891b6044820152606401610719565b610c78610e8d83610ead565b8233611436565b600080610ea18484611cc2565b915091505b9250929050565b600081806001600160a01b038116146106af5760405162461bcd60e51b815260206004820152600d60248201526c15dc9bdb99c818dbdb9d995c9d609a1b6044820152606401610719565b6001600160a01b0382166000908152600f6020526040812054808203610f225760009150506106af565b6001600160a01b0384166000908152600e60205260409020610f45908285611d4c565b949350505050565b6001600160a01b0381166000908152600f60205260408120548103610f74575060006106af565b6001600160a01b03808416600081815260086020908152604080832094871683529381528382205492825260128152838220828052905291822054610fb99190611e92565b90506000610fc78483610ef8565b6001600160a01b0385166000908152600f602052604081205491925090610ff090600190612789565b90506000811561110257825b611007600184612789565b8111611100576001600160a01b0387166000818152600e60208181526040808420868552808352818520825180840190935280548352600190810154838501529585529290915292829061105c90869061287e565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061109b8b8460000151611cc2565b50905060006110ae8c8460000151611cc2565b509050670de0b6b3a76400006110c48383612789565b85602001516110d391906127b6565b6110dd91906127d5565b6110e7908761287e565b95505050505080806110f890612770565b915050610ffc565b505b6001600160a01b0386166000908152600e6020908152604080832085845282528083208151808301909252805480835260019091015492820192909252919061114c908a90611cc2565b506001600160a01b03808b166000908152600960209081526040808320938d1683529290522054909150670de0b6b3a76400009061118b908390611e92565b6111948b611bd0565b61119e9190612789565b83602001516111ad91906127b6565b6111b791906127d5565b6111c1908461287e565b9998505050505050505050565b6001600160a01b038316600090815260066020908152604080832054600790925282205460115483929190830361120857925090506113b6565b6001600160a01b03871660009081526004602052604081205490036112335792504291506113b69050565b600061123e836113be565b9050600061125a60016011546112549190612789565b89611ea9565b9050801561133357815b61126f600183612789565b811161133157600081815260106020908152604091829020825180840190935280548352600101549082018190521561131e5760006010816112b285600161287e565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806112fd8e8460000151866000015187602001518d611eb8565b909250905061130c828961287e565b97506113198e8983611f3c565b975050505b508061132981612770565b915050611264565b505b86156113ad5760008181526010602090815260409182902082518084019093528054835260010154908201819052156113ab57600061138c8b6113758d612045565b8451611381908a611e92565b85602001518a611eb8565b509050611399818661287e565b94506113a68b8642611f3c565b429550505b505b50909350909150505b935093915050565b6011546000908082036113d45750600092915050565b6106c160108285611d4c565b6113e8612069565b80600a60008282546113fa9190612789565b90915550506001600160a01b0382166000908152600b602052604081208054839290611427908490612789565b90915550610c789050826120ed565b6000546001146114795760405162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b6044820152606401610719565b600260009081555b825181101561171c576114b183828151811061149f5761149f612744565b602002602001015160001960016111ce565b600760008685815181106114c7576114c7612744565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006006600088878151811061150757611507612744565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000849190505583919050555050600061156284838151811061155457611554612744565b602002602001015186610f4d565b9050426008600086858151811061157b5761157b612744565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000876001600160a01b03166001600160a01b0316815260200190815260200160002081905550600760008584815181106115e0576115e0612744565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546009600086858151811061161f5761161f612744565b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120938a168152929052902055801561169157611691838286858151811061167157611671612744565b60200260200101516001600160a01b03166121709092919063ffffffff16565b8382815181106116a3576116a3612744565b60200260200101516001600160a01b0316336001600160a01b03167fe4394b3c25e336e9d6b7fcefab7e3234f1c6b373f13655dc3920664b080b098d83866040516117019291909182526001600160a01b0316602082015260400190565b60405180910390a3508061171481612770565b915050611481565b50611726836120ed565b5050600160005550565b6000546001146117735760405162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b6044820152606401610719565b60026000556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036117f35760405162461bcd60e51b815260206004820152601760248201527f57726f6e6720746f6b656e20666f7220726577617264730000000000000000006044820152606401610719565b600081116118135760405162461bcd60e51b81526004016107199061281a565b6001600160a01b0382166000908152600d602052604090205460ff1661186f5760405162461bcd60e51b8152602060048201526011602482015270151bdad95b881b9bdd08185b1b1bddd959607a1b6044820152606401610719565b6001600160a01b038216600090815260046020526040812054900361189a5761189a82600042611f3c565b6118a88260001960016111ce565b6001600160a01b0384166000908152600760209081526040808320600683528184209490945593909255600590915220544210611932576118f46001600160a01b0383163330846121d3565b62093a8061190a670de0b6b3a7640000836127b6565b61191491906127d5565b6001600160a01b038316600090815260046020526040902055611a52565b6001600160a01b038216600090815260056020526040812054611956904290612789565b6001600160a01b0384166000908152600460205260408120549192509061197d90836127b6565b9050611991670de0b6b3a7640000826127d5565b83116119f65760405162461bcd60e51b815260206004820152602e60248201527f416d6f756e742073686f756c6420626520686967686572207468616e2072656d60448201526d61696e696e67207265776172647360901b6064820152608401610719565b611a0b6001600160a01b0385163330866121d3565b62093a8081611a22670de0b6b3a7640000866127b6565b611a2c919061287e565b611a3691906127d5565b6001600160a01b03851660009081526004602052604090205550505b611a5f62093a804261287e565b6001600160a01b0383166000818152600560205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf5082690611ab09085815260200190565b60405180910390a350506001600055565b600c54600a11611b0c5760405162461bcd60e51b8152602060048201526016602482015275546f6f206d616e792072657761726420746f6b656e7360501b6044820152606401610719565b6001600160a01b0381166000908152600d602052604090205460ff1615611b6a5760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481c9959da5cdd195c995960721b6044820152606401610719565b6001600160a01b03166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b0319169091179055565b6000600254600003611bf857506001600160a01b031660009081526007602052604090205490565b6002546001600160a01b03831660009081526004602090815260408083205460068352818420546005909352922054611c319190611ea9565b611c3a85612045565b611c449190612789565b611c4e91906127b6565b611c5891906127d5565b6001600160a01b0383166000908152600760205260409020546106af919061287e565b611c83612069565b80600a6000828254611c95919061287e565b90915550506001600160a01b0382166000908152600b60205260408120805483929061142790849061287e565b6001600160a01b0382166000908152601360205260408120548190808203611cf1576000809250925050610ea6565b6001600160a01b038516600090815260126020526040812090611d15828488611d4c565b6000908152602092835260409081902081518083019092528054808352600190910154919093018190529791965090945050505050565b600082600003611d925760405162461bcd60e51b8152602060048201526011602482015270456d70747920636865636b706f696e747360781b6044820152606401610719565b81846000611da1600187612789565b81526020019081526020016000206000015411611dca57611dc3600184612789565b90506106c1565b600080805260208590526040902054821015611de8575060006106c1565b600080611df6600186612789565b90505b81811115611e895760006002611e0f8484612789565b611e1991906127d5565b611e239083612789565b60008181526020898152604091829020825180840190935280548084526001909101549183019190915291925090869003611e63575092506106c1915050565b8051861115611e7457819350611e82565b611e7f600183612789565b92505b5050611df9565b50949350505050565b600081831015611ea257816106c1565b5090919050565b6000818310611ea257816106c1565b6000806000611ec78785611e92565b6001600160a01b038916600090815260056020908152604080832054600490925290912054919250908690611f05611eff8a89611e92565b84611ea9565b611f0f8585611ea9565b611f199190612789565b611f2391906127b6565b611f2d91906127d5565b99919850909650505050505050565b6001600160a01b0383166000908152601360205260409020548015801590611f9857506001600160a01b03841660009081526012602052604081208391611f84600185612789565b815260200190815260200160002060000154145b15611fdb576001600160a01b03841660009081526012602052604081208491611fc2600185612789565b815260208101919091526040016000206001015561203f565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561202590829061287e565b6001600160a01b0385166000908152601360205260409020555b50505050565b6001600160a01b0381166000908152600560205260408120546106af904290611ea9565b600c5460005b81811015610c78576000600c828154811061208c5761208c612744565b6000918252602090912001546001600160a01b031690506120b18160001960016111ce565b6001600160a01b0390921660009081526007602090815260408083206006909252909120929092559055806120e581612770565b91505061206f565b6001600160a01b0381166000908152600360205260408120546002805491928392612119908490612789565b9091555050506001600160a01b0381166000908152600b602090815260408083205460039092528220819055600280549192839261215890849061287e565b909155506121689050828261220b565b610c786122fc565b6040516001600160a01b038316602482015260448101829052610c6990849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526123a0565b6040516001600160a01b038085166024830152831660448201526064810182905261203f9085906323b872dd60e01b9060840161219c565b6001600160a01b0382166000908152600f60205260409020544290801580159061226957506001600160a01b0384166000908152600e602052604081208391612255600185612789565b815260200190815260200160002060000154145b15612293576001600160a01b0384166000908152600e602052604081208491611fc2600185612789565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556122dd90829061287e565b6001600160a01b0385166000908152600f602052604090205550505050565b60115442811580159061232e5750806010600061231a600186612789565b815260200190815260200160002060000154145b1561235d5760025460106000612345600186612789565b81526020810191909152604001600020600101555050565b6040805180820182528281526002546020808301918252600086815260109091529290922090518155905160019182015561239990839061287e565b6011555050565b60006123f5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124729092919063ffffffff16565b805190915015610c695780806020019051810190612413919061285c565b610c695760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610719565b60606001600160a01b0384163b6124cb5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610719565b600080856001600160a01b0316856040516124e691906128c2565b6000604051808303816000865af19150503d8060008114612523576040519150601f19603f3d011682016040523d82523d6000602084013e612528565b606091505b5091509150612538828286612542565b9695505050505050565b606083156125515750816106c1565b8251156125615782518084602001fd5b8160405162461bcd60e51b815260040161071991906128de565b6001600160a01b0381168114610cec57600080fd5b803561259b8161257b565b919050565b600080604083850312156125b357600080fd5b82356125be8161257b565b946020939093013593505050565b6000602082840312156125de57600080fd5b5035919050565b600080604083850312156125f857600080fd5b82356126038161257b565b915060208301356126138161257b565b809150509250929050565b60006020828403121561263057600080fd5b81356106c18161257b565b6000806040838503121561264e57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561268657600080fd5b8235915060208084013567ffffffffffffffff808211156126a657600080fd5b818601915086601f8301126126ba57600080fd5b8135818111156126cc576126cc61265d565b8060051b604051601f19603f830116810181811085821117156126f1576126f161265d565b60405291825284820192508381018501918983111561270f57600080fd5b938501935b828510156127345761272585612590565b84529385019392850192612714565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016127825761278261275a565b5060010190565b60008282101561279b5761279b61275a565b500390565b634e487b7160e01b600052603160045260246000fd5b60008160001904831182151516156127d0576127d061275a565b500290565b6000826127f257634e487b7160e01b600052601260045260246000fd5b500490565b6020808252600990820152682737ba103b37ba32b960b91b604082015260600190565b6020808252600b908201526a16995c9bc8185b5bdd5b9d60aa1b604082015260600190565b60006020828403121561285157600080fd5b81516106c18161257b565b60006020828403121561286e57600080fd5b815180151581146106c157600080fd5b600082198211156128915761289161275a565b500190565b60005b838110156128b1578181015183820152602001612899565b8381111561203f5750506000910152565b600082516128d4818460208701612896565b9190910192915050565b60208152600082518060208401526128fd816040850160208701612896565b601f01601f1916919091016040019291505056fea26469706673582212203a96e6088b0b370ddb7df141bb1eacf5da3a10634caf16402c5764bbdca6564964736f6c634300080d0033000000000000000000000000649bdf58b09a0cd4ac848b42c4b5e1390a72a49a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000039ab6574c289c3ae4d88500eec792ab5b947a5eb

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