MNT Price: $0.86 (+1.62%)

Contract

0x89177746dD168FA4b8E81c20ba6f4e11fe3927E5
 

Overview

MNT Balance

Mantle Mainnet Network LogoMantle Mainnet Network LogoMantle Mainnet Network Logo0 MNT

MNT Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

1 Internal Transaction and > 10 Token Transfers found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
535483392024-02-08 8:08:05718 days ago1707379685  Contract Creation0 MNT

Cross-Chain Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xdc1F23E7...9d52F0D3f
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
WrappedExternalBribe

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "contracts/libraries/Math.sol";
import "contracts/ExternalBribe.sol";
import "contracts/interfaces/IERC20.sol";
import "contracts/interfaces/IGauge.sol";
import "contracts/interfaces/IPair.sol";
import "contracts/interfaces/IRouter.sol";
import "contracts/interfaces/IVoter.sol";
import "contracts/interfaces/IVotingEscrow.sol";
import "contracts/interfaces/IWrappedExternalBribe.sol";
import "contracts/interfaces/IWrappedExternalBribeFactory.sol";
import "contracts/interfaces/IMetaBribe.sol";
import "contracts/Constants.sol";

// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())
contract WrappedExternalBribe is IWrappedExternalBribe, Constants {
  struct MetaBribeInfo {
    address bribedToken;
    uint amount;
    uint value;
    bool partner;
    address gauge;
  }

  struct MetaBribeEpoch {
    uint totalValue;
    uint totalValueFromPartners;
    mapping(uint => MetaBribeInfo[]) bribes; // tokenId => MetaBribeInfo[]
  }

  address public immutable voter;
  address public immutable _ve;
  address public router;
  address public governor;
  IWrappedExternalBribeFactory public wxbFactory;
  ExternalBribe public underlying_bribe;

  uint internal constant DURATION = SECONDS_PER_EPOCH; // rewards are released over the voting period
  uint internal constant MAX_REWARD_TOKENS = 16;

  uint internal constant PRECISION = 10 ** 18;

  mapping(address => mapping(uint => uint)) public tokenRewardsPerEpoch;
  mapping(address => uint) public periodFinish;
  mapping(address => mapping(uint => uint)) public lastEarn;

  address[] public rewards;
  mapping(address => bool) public isReward;

  // Make sure MetaBribe weights are final at the end of epoch: Memorizing prevents changes in formula
  // weights, when updating MetaBribe partner/token whitelists with tokenIds that have already
  // bribed in the past.
  mapping(uint => MetaBribeEpoch) public metaBribeEpoch; // epoch => MetaBribeEpoch

  /// @notice A checkpoint for marking balance
  struct RewardCheckpoint {
    uint timestamp;
    uint balance;
  }

  event NotifyReward(
    address indexed from,
    address indexed reward,
    uint epoch,
    uint amount
  );
  event NotifyRewardMetaBribe(
    address indexed from,
    address indexed reward,
    uint epoch,
    uint amount,
    uint value,
    bool partner,
    address gauge,
    uint tokenId
  );
  event ClaimRewards(address indexed from, address indexed reward, uint amount);

  constructor(
    address _voter,
    address _old_bribe,
    address _router,
    address _governor
  ) {
    voter = _voter;
    router = _router;
    governor = _governor;
    _ve = IVoter(_voter)._ve();
    wxbFactory = IWrappedExternalBribeFactory(msg.sender);
    underlying_bribe = ExternalBribe(_old_bribe);

    for (uint i; i < underlying_bribe.rewardsListLength(); i++) {
      address underlying_reward = underlying_bribe.rewards(i);
      if (underlying_reward != address(0)) {
        isReward[underlying_reward] = true;
        rewards.push(underlying_reward);
      }
    }
  }

  // simple re-entrancy check
  uint internal _unlocked = 1;
  modifier lock() {
    require(_unlocked == 1);
    _unlocked = 2;
    _;
    _unlocked = 1;
  }

  function setRouter(address _newRouter) public {
    require(msg.sender == governor);
    require(_newRouter != address(0));
    router = _newRouter;
  }

  function setGovernor(address _governor) public {
    require(msg.sender == governor);
    require(_governor != address(0));
    governor = _governor;
  }

  function _bribeStart(uint timestamp) internal pure returns (uint) {
    return timestamp - (timestamp % SECONDS_PER_EPOCH);
  }

  function getEpochStart(uint timestamp) public pure returns (uint) {
    uint bribeStart = _bribeStart(timestamp);
    uint bribeEnd = bribeStart + DURATION;
    return timestamp < bribeEnd ? bribeStart : bribeStart + SECONDS_PER_EPOCH;
  }

  function rewardsListLength() external view returns (uint) {
    return rewards.length;
  }

  function getRewardByIndex(uint _i) external view returns (address) {
    return rewards[_i];
  }

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

  // allows a user to claim rewards for a given token
  function getReward(uint tokenId, address[] memory tokens) external lock {
    require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));
    for (uint i = 0; i < tokens.length; i++) {
      uint _reward = earned(tokens[i], tokenId);
      lastEarn[tokens[i]][tokenId] = block.timestamp;
      if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);

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

  // used by Voter to allow batched reward claims
  function getRewardForOwner(
    uint tokenId,
    address[] memory tokens
  ) external lock {
    require(msg.sender == voter);
    address _owner = IVotingEscrow(_ve).ownerOf(tokenId);
    for (uint i = 0; i < tokens.length; i++) {
      uint _reward = earned(tokens[i], tokenId);
      lastEarn[tokens[i]][tokenId] = block.timestamp;
      if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);

      emit ClaimRewards(_owner, tokens[i], _reward);
    }
  }

  function earned(address token, uint tokenId) public view returns (uint) {
    if (underlying_bribe.numCheckpoints(tokenId) == 0) {
      return 0;
    }

    uint reward = 0;
    uint _ts = 0;
    uint _bal = 0;
    uint _supply = 1;
    uint _index = 0;
    uint _currTs = _bribeStart(lastEarn[token][tokenId]); // take epoch last claimed in as starting point

    _index = underlying_bribe.getPriorBalanceIndex(tokenId, _currTs);
    (_ts, _bal) = underlying_bribe.checkpoints(tokenId, _index);
    // accounts for case where lastEarn is before first checkpoint
    _currTs = Math.max(_currTs, _bribeStart(_ts));

    for (uint k = 0; k < 50; k++) {
      if (_currTs == _bribeStart(block.timestamp)) {
        // if we reach the current epoch, exit
        break;
      }
      // get index of last checkpoint in this epoch
      _index = underlying_bribe.getPriorBalanceIndex(
        tokenId,
        _currTs + DURATION - 1
      );
      // get checkpoint in this epoch
      (_ts, _bal) = underlying_bribe.checkpoints(tokenId, _index);
      // get supply of last checkpoint in this epoch
      (, _supply) = underlying_bribe.supplyCheckpoints(
        underlying_bribe.getPriorSupplyIndex(_currTs + DURATION - 1)
      );
      reward += (_bal * tokenRewardsPerEpoch[token][_currTs]) / _supply;
      _currTs += DURATION;
    }

    return reward;
  }

  function left(address token) external view returns (uint) {
    uint adjustedTstamp = getEpochStart(block.timestamp);
    return tokenRewardsPerEpoch[token][adjustedTstamp];
  }

  // only for tests, debugging and insights, not used in contracts anymore
  function getMetaBribe(
    uint tokenId,
    uint ts
  )
    external
    view
    returns (
      address[] memory,
      uint[] memory,
      uint[] memory,
      bool[] memory,
      address[] memory
    )
  {
    MetaBribeInfo[] storage mb = metaBribeEpoch[ts].bribes[tokenId];
    uint n = mb.length;
    address[] memory bribedTokens = new address[](n);
    uint[] memory amounts = new uint[](n);
    uint[] memory values = new uint[](n);
    bool[] memory partner = new bool[](n);
    address[] memory gauges = new address[](n);
    for (uint i = 0; i < n; i++) {
      bribedTokens[i] = mb[i].bribedToken;
      amounts[i] = mb[i].amount;
      values[i] = mb[i].value;
      partner[i] = mb[i].partner;
      gauges[i] = mb[i].gauge;
    }
    return (bribedTokens, amounts, values, partner, gauges);
  }

  // emits a bribe by a user
  function notifyRewardAmount(
    address token,
    uint amount,
    address gauge,
    uint tokenId
  ) external lock {
    require(amount > 0);
    if (!isReward[token]) {
      require(
        IVoter(voter).isWhitelisted(token),
        "bribe tokens must be whitelisted"
      );
      require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens");
    }
    // bribes kick in at the start of next bribe period
    uint adjustedTstamp = getEpochStart(block.timestamp);
    uint epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];

    _safeTransferFrom(token, msg.sender, address(this), amount);
    tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;

    periodFinish[token] = adjustedTstamp + DURATION;

    if (!isReward[token]) {
      isReward[token] = true;
      rewards.push(token);
    }

    IMetaBribe _metaBribe = IMetaBribe(wxbFactory.metaBribe());
    uint value = _metaBribe.estimateValue(token, amount, _metaBribe.currency());

    bool isPartner = isPartnerToken(tokenId);

    metaBribeEpoch[adjustedTstamp].bribes[tokenId].push(
      MetaBribeInfo({
        bribedToken: token,
        amount: amount,
        value: value,
        partner: isPartner,
        gauge: gauge
      })
    );

    metaBribeEpoch[adjustedTstamp].totalValue += value;
    if (isPartner) {
      metaBribeEpoch[adjustedTstamp].totalValueFromPartners += value;
    }

    emit NotifyRewardMetaBribe(
      msg.sender,
      token,
      adjustedTstamp,
      amount,
      value,
      isPartner,
      gauge,
      tokenId
    );
  }

  /// @inheritdoc IWrappedExternalBribe
  function getTotalBribesValue(uint ts) external view returns (uint) {
    return metaBribeEpoch[getEpochStart(ts)].totalValue;
  }

  /// @inheritdoc IWrappedExternalBribe
  function getTotalPartnersBribesValue(uint ts) external view returns (uint) {
    return metaBribeEpoch[getEpochStart(ts)].totalValueFromPartners;
  }

  /// @inheritdoc IWrappedExternalBribe
  function getPartnerBribesValue(
    uint ts,
    uint tokenId
  ) external view returns (uint) {
    ts = getEpochStart(ts);
    uint sum = 0;
    MetaBribeInfo[] storage mb = metaBribeEpoch[ts].bribes[tokenId];
    for (uint i = 0; i < mb.length; i++) {
      if (mb[i].partner) {
        sum += mb[i].value;
      }
    }
    return sum;
  }

  function swapOutRewardToken(
    uint i,
    address oldToken,
    address newToken
  ) external {
    require(msg.sender == IVotingEscrow(_ve).team(), "only team");
    require(rewards[i] == oldToken);
    require(
      IVoter(voter).isWhitelisted(newToken),
      "newToken must be whitelisted"
    );
    isReward[oldToken] = false;
    isReward[newToken] = true;
    rewards[i] = newToken;
  }

  function _safeTransfer(address token, address to, uint256 value) internal {
    require(token.code.length > 0);
    (bool success, bytes memory data) = token.call(
      abi.encodeWithSelector(IERC20.transfer.selector, to, value)
    );
    require(success && (data.length == 0 || abi.decode(data, (bool))));
  }

  function _safeTransferFrom(
    address token,
    address from,
    address to,
    uint256 value
  ) internal {
    require(token.code.length > 0);
    (bool success, bytes memory data) = token.call(
      abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)
    );
    require(success && (data.length == 0 || abi.decode(data, (bool))));
  }

  /// @return true if tokenId is a whitelisted MetaBribe partner token
  function isPartnerToken(uint tokenId) public view returns (bool) {
    address metaBribe = wxbFactory.metaBribe();
    return IMetaBribe(metaBribe).isEligibleTokenId(tokenId);
  }
}

File 2 of 14 : Constants.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

contract Constants {
  uint public constant SECONDS_PER_EPOCH = 7 * 24 * 60 * 60;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "contracts/libraries/Math.sol";
import "contracts/interfaces/IBribe.sol";
import "contracts/interfaces/IERC20.sol";
import "contracts/interfaces/IGauge.sol";
import "contracts/interfaces/IVoter.sol";
import "contracts/interfaces/IVotingEscrow.sol";
import "contracts/Constants.sol";

// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())
contract ExternalBribe is IBribe, Constants {
  address public immutable voter; // only voter can modify balances (since it only happens on vote())
  address public immutable _ve; // 天使のたまご

  uint internal constant DURATION = SECONDS_PER_EPOCH; // rewards are released over the voting period
  uint internal constant MAX_REWARD_TOKENS = 16;

  uint internal constant PRECISION = 10 ** 18;

  uint public totalSupply;
  mapping(uint => uint) public balanceOf;
  mapping(address => mapping(uint => uint)) public tokenRewardsPerEpoch;
  mapping(address => uint) public periodFinish;
  mapping(address => mapping(uint => uint)) public lastEarn;

  address[] public rewards;
  mapping(address => bool) public isReward;

  /// @notice A checkpoint for marking balance
  struct Checkpoint {
    uint timestamp;
    uint balanceOf;
  }

  /// @notice A checkpoint for marking supply
  struct SupplyCheckpoint {
    uint timestamp;
    uint supply;
  }

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

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

  constructor(address _voter, address[] memory _allowedRewardTokens) {
    voter = _voter;
    _ve = IVoter(_voter)._ve();

    for (uint i; i < _allowedRewardTokens.length; i++) {
      if (_allowedRewardTokens[i] != address(0)) {
        isReward[_allowedRewardTokens[i]] = true;
        rewards.push(_allowedRewardTokens[i]);
      }
    }
  }

  // simple re-entrancy check
  uint internal _unlocked = 1;
  modifier lock() {
    require(_unlocked == 1);
    _unlocked = 2;
    _;
    _unlocked = 1;
  }

  function _bribeStart(uint timestamp) internal pure returns (uint) {
    return timestamp - (timestamp % SECONDS_PER_EPOCH);
  }

  function getEpochStart(uint timestamp) public pure returns (uint) {
    uint bribeStart = _bribeStart(timestamp);
    uint bribeEnd = bribeStart + DURATION;
    return timestamp < bribeEnd ? bribeStart : bribeStart + SECONDS_PER_EPOCH;
  }

  /**
   * @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 tokenId The token of the NFT to check
   * @param timestamp The timestamp to get the balance at
   * @return The balance the account had as of the given block
   */
  function getPriorBalanceIndex(
    uint tokenId,
    uint timestamp
  ) public view returns (uint) {
    uint nCheckpoints = numCheckpoints[tokenId];
    if (nCheckpoints == 0) {
      return 0;
    }
    // First check most recent balance
    if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {
      return (nCheckpoints - 1);
    }
    // Next check implicit zero balance
    if (checkpoints[tokenId][0].timestamp > timestamp) {
      return 0;
    }

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

  function getPriorSupplyIndex(uint timestamp) public view returns (uint) {
    uint nCheckpoints = supplyNumCheckpoints;
    if (nCheckpoints == 0) {
      return 0;
    }

    // First check most recent balance
    if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {
      return (nCheckpoints - 1);
    }

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

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

  function _writeCheckpoint(uint tokenId, uint balance) internal {
    uint _timestamp = block.timestamp;
    uint _nCheckPoints = numCheckpoints[tokenId];
    if (
      _nCheckPoints > 0 &&
      checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp
    ) {
      checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;
    } else {
      checkpoints[tokenId][_nCheckPoints] = Checkpoint(_timestamp, balance);
      numCheckpoints[tokenId] = _nCheckPoints + 1;
    }
  }

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

    if (
      _nCheckPoints > 0 &&
      supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp
    ) {
      supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;
    } else {
      supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(
        _timestamp,
        totalSupply
      );
      supplyNumCheckpoints = _nCheckPoints + 1;
    }
  }

  function rewardsListLength() external view returns (uint) {
    return rewards.length;
  }

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

  // allows a user to claim rewards for a given token
  function getReward(uint tokenId, address[] memory tokens) external lock {
    require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));
    for (uint i = 0; i < tokens.length; i++) {
      uint _reward = earned(tokens[i], tokenId);
      lastEarn[tokens[i]][tokenId] = block.timestamp;
      if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);

      emit ClaimRewards(msg.sender, tokens[i], _reward);
    }
    _writeCheckpoint(tokenId, balanceOf[tokenId]);
    _writeSupplyCheckpoint();
  }

  // used by Voter to allow batched reward claims
  function getRewardForOwner(
    uint tokenId,
    address[] memory tokens
  ) external lock {
    require(msg.sender == voter);
    address _owner = IVotingEscrow(_ve).ownerOf(tokenId);
    for (uint i = 0; i < tokens.length; i++) {
      uint _reward = earned(tokens[i], tokenId);
      lastEarn[tokens[i]][tokenId] = block.timestamp;
      if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);

      emit ClaimRewards(_owner, tokens[i], _reward);
    }
    _writeCheckpoint(tokenId, balanceOf[tokenId]);
    _writeSupplyCheckpoint();
  }

  function earned(address token, uint tokenId) public view returns (uint) {
    if (numCheckpoints[tokenId] == 0) {
      return 0;
    }

    uint reward = 0;
    uint _ts = 0;
    uint _bal = 0;
    uint _supply = 1;
    uint _index = 0;
    uint _currTs = _bribeStart(lastEarn[token][tokenId]); // take epoch last claimed in as starting point

    _index = getPriorBalanceIndex(tokenId, _currTs);
    _ts = checkpoints[tokenId][_index].timestamp;
    _bal = checkpoints[tokenId][_index].balanceOf;
    // accounts for case where lastEarn is before first checkpoint
    _currTs = Math.max(_currTs, _bribeStart(_ts));

    for (uint k = 0; k < 50; k++) {
      if (_currTs == _bribeStart(block.timestamp)) {
        // if we reach the current epoch, exit
        break;
      }
      // get index of last checkpoint in this epoch
      _index = getPriorBalanceIndex(tokenId, _currTs + DURATION - 1);
      // get checkpoint in this epoch
      _ts = checkpoints[tokenId][_index].timestamp;
      _bal = checkpoints[tokenId][_index].balanceOf;
      // get supply of last checkpoint in this epoch
      _supply = supplyCheckpoints[getPriorSupplyIndex(_currTs + DURATION - 1)]
        .supply;
      if (_supply > 0)
        // prevent div by 0
        reward += (_bal * tokenRewardsPerEpoch[token][_currTs]) / _supply;
      _currTs += DURATION;
    }

    return reward;
  }

  // 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 {
    require(msg.sender == voter);

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

    _writeCheckpoint(tokenId, balanceOf[tokenId]);
    _writeSupplyCheckpoint();

    emit Deposit(msg.sender, tokenId, amount);
  }

  function _withdraw(uint amount, uint tokenId) external {
    require(msg.sender == voter);

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

    _writeCheckpoint(tokenId, balanceOf[tokenId]);
    _writeSupplyCheckpoint();

    emit Withdraw(msg.sender, tokenId, amount);
  }

  function left(address token) external view returns (uint) {
    uint adjustedTstamp = getEpochStart(block.timestamp);
    return tokenRewardsPerEpoch[token][adjustedTstamp];
  }

  function notifyRewardAmount(address token, uint amount) external lock {
    require(amount > 0);
    if (!isReward[token]) {
      require(
        IVoter(voter).isWhitelisted(token),
        "bribe tokens must be whitelisted"
      );
      require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens");
    }
    // bribes kick in at the start of next bribe period
    uint adjustedTstamp = getEpochStart(block.timestamp);
    uint epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];

    _safeTransferFrom(token, msg.sender, address(this), amount);
    tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;

    periodFinish[token] = adjustedTstamp + DURATION;

    if (!isReward[token]) {
      isReward[token] = true;
      rewards.push(token);
    }

    emit NotifyReward(msg.sender, token, adjustedTstamp, amount);
  }

  function swapOutRewardToken(
    uint i,
    address oldToken,
    address newToken
  ) external {
    require(msg.sender == IVotingEscrow(_ve).team(), "only team");
    require(rewards[i] == oldToken);
    require(
      IVoter(voter).isWhitelisted(newToken),
      "newToken must be whitelisted"
    );
    isReward[oldToken] = false;
    isReward[newToken] = true;
    rewards[i] = newToken;
  }

  function _safeTransfer(address token, address to, uint256 value) internal {
    require(token.code.length > 0);
    (bool success, bytes memory data) = token.call(
      abi.encodeWithSelector(IERC20.transfer.selector, to, value)
    );
    require(success && (data.length == 0 || abi.decode(data, (bool))));
  }

  function _safeTransferFrom(
    address token,
    address from,
    address to,
    uint256 value
  ) internal {
    require(token.code.length > 0);
    (bool success, bytes memory data) = token.call(
      abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)
    );
    require(success && (data.length == 0 || abi.decode(data, (bool))));
  }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IBribe {
  struct Reward {
    uint256 periodFinish;
    uint256 rewardsPerEpoch;
    uint256 lastUpdateTime;
  }

  function _deposit(uint amount, uint tokenId) external;

  function _withdraw(uint amount, uint tokenId) external;

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

  function notifyRewardAmount(address token, uint amount) external;

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

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IWrappedExternalBribe {

  function getRewardByIndex(uint _i) external view returns (address);

  function rewardsListLength() external view returns (uint);

  /// @param ts timestamp will be rounded down to epoch
  /// @return summed bribe values of the epoch
  function getTotalBribesValue(uint ts) external view returns(uint);

  /// @param ts timestamp will be rounded down to epoch
  /// @return summed bribe values of the epoch, but only from MetaBribe partners
  function getTotalPartnersBribesValue(uint ts) external view returns(uint);

  /// @param ts timestamp will be rounded down to epoch
  /// @return summed bribe values of the epoch from given tokenId, only if it was
  ///         a partner tokenId a time of bribe emission
  function getPartnerBribesValue(uint ts, uint tokenId) external view returns(uint);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IERC20 {
  function totalSupply() external view returns (uint256);

  function transfer(address recipient, uint amount) external returns (bool);

  function decimals() external view returns (uint8);

  function symbol() external view returns (string memory);

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

  function transferFrom(
    address sender,
    address recipient,
    uint amount
  ) external returns (bool);

  function allowance(
    address owner,
    address spender
  ) external view returns (uint);

  function approve(address spender, uint value) external returns (bool);

  event Transfer(address indexed from, address indexed to, uint value);
  event Approval(address indexed owner, address indexed spender, uint value);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IGauge {
  function notifyRewardAmount(
    address token,
    uint amount,
    bool is3pool
  ) external;

  function getReward(address account, address[] memory tokens) external;

  function claimFees() external returns (uint claimed0, uint claimed1);

  function claimFeesFor3Pool(
    address _swapAddress
  ) external returns (uint[] memory claimed);

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

  function isForPair() external view returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IMetaBribe {
  function checkpoint_token() external;

  function checkpoint_total_supply() external;

  function isPartner(address _partner) external view returns (bool);

  function isEligibleTokenId(uint _tokenId) external view returns (bool);

  function currency() external returns(address);

  function estimateValue(
    address tokenIn,
    uint amountIn,
    address tokenOut
  ) external view returns (uint);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IPair {
  function metadata()
    external
    view
    returns (
      uint dec0,
      uint dec1,
      uint r0,
      uint r1,
      bool st,
      address t0,
      address t1
    );

  function claimFees() external returns (uint, uint);

  function tokens() external returns (address, address);

  function transferFrom(
    address src,
    address dst,
    uint amount
  ) external returns (bool);

  function permit(
    address owner,
    address spender,
    uint value,
    uint deadline,
    // uint8 v,
    // bytes32 r,
    // bytes32 s
    bytes calldata signature
  ) external;

  function swap(
    uint amount0Out,
    uint amount1Out,
    address to,
    bytes calldata data
  ) external;

  function burn(address to) external returns (uint amount0, uint amount1);

  function mint(address to) external returns (uint liquidity);

  function getReserves()
    external
    view
    returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);

  function getAmountOut(uint, address) external view returns (uint);

  function current(
    address tokenIn,
    uint amountIn
  ) external view returns (uint amountOut);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IRouter {
  struct route {
    address from;
    address to;
    bool stable;
  }

  function sortTokens(
    address tokenA,
    address tokenB
  ) external view returns (address token0, address token1);

  function pairFor(
    address tokenA,
    address tokenB,
    bool stable
  ) external view returns (address pair);

  function getReserves(
    address tokenA,
    address tokenB,
    bool stable
  ) external view returns (uint reserveA, uint reserveB);

  function getAmountOut(
    uint amountIn,
    address tokenIn,
    address tokenOut
  ) external view returns (uint amount, bool stable);

  function getAmountsOut(
    uint amountIn,
    route[] memory routes
  ) external view returns (uint[] memory amounts);

  function isPair(address pair) external view returns (bool);

  function quoteAddLiquidity(
    address tokenA,
    address tokenB,
    bool stable,
    uint amountADesired,
    uint amountBDesired
  ) external view returns (uint amountA, uint amountB, uint liquidity);

  function quoteRemoveLiquidity(
    address tokenA,
    address tokenB,
    bool stable,
    uint liquidity
  ) external view returns (uint amountA, uint amountB);

  function addLiquidity(
    address tokenA,
    address tokenB,
    bool stable,
    uint amountADesired,
    uint amountBDesired,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
  ) external returns (uint amountA, uint amountB, uint liquidity);

  function addLiquidityETH(
    address token,
    bool stable,
    uint amountTokenDesired,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline
  ) external payable returns (uint amountToken, uint amountETH, uint liquidity);

  function removeLiquidity(
    address tokenA,
    address tokenB,
    bool stable,
    uint liquidity,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
  ) external returns (uint amountA, uint amountB);

  function removeLiquidityETH(
    address token,
    bool stable,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline
  ) external returns (uint amountToken, uint amountETH);

  function removeLiquidityWithPermit(
    address tokenA,
    address tokenB,
    bool stable,
    uint liquidity,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline,
    bool approveMax,
    bytes calldata signature
  ) external returns (uint amountA, uint amountB);

  function removeLiquidityETHWithPermit(
    address token,
    bool stable,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline,
    bool approveMax,
    bytes calldata signature
  ) external returns (uint amountToken, uint amountETH);

  function removeLiquidityETHSupportingFeeOnTransferTokens(
    address token,
    bool stable,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline
  ) external returns (uint amountToken, uint amountETH);

  function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
    address token,
    bool stable,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline,
    bool approveMax,
    bytes calldata signature
  ) external returns (uint amountToken, uint amountETH);

  function swapExactTokensForTokensSimple(
    uint amountIn,
    uint amountOutMin,
    address tokenFrom,
    address tokenTo,
    bool stable,
    address to,
    uint deadline
  ) external returns (uint[] memory amounts);

  function swapExactTokensForTokens(
    uint amountIn,
    uint amountOutMin,
    route[] calldata routes,
    address to,
    uint deadline
  ) external returns (uint[] memory amounts);

  function swapExactETHForTokens(
    uint amountOutMin,
    route[] calldata routes,
    address to,
    uint deadline
  ) external payable returns (uint[] memory amounts);

  function swapExactTokensForETH(
    uint amountIn,
    uint amountOutMin,
    route[] calldata routes,
    address to,
    uint deadline
  ) external returns (uint[] memory amounts);

  function swapExactTokensForTokensSupportingFeeOnTransferTokens(
    uint amountIn,
    uint amountOutMin,
    route[] calldata routes,
    address to,
    uint deadline
  ) external;

  function swapExactETHForTokensSupportingFeeOnTransferTokens(
    uint amountOutMin,
    route[] calldata routes,
    address to,
    uint deadline
  ) external payable;

  function swapExactTokensForETHSupportingFeeOnTransferTokens(
    uint amountIn,
    uint amountOutMin,
    route[] calldata routes,
    address to,
    uint deadline
  ) external;

  function UNSAFE_swapExactTokensForTokens(
    uint[] memory amounts,
    route[] calldata routes,
    address to,
    uint deadline
  ) external returns (uint[] memory);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IVoter {
  function _ve() external view returns (address);

  function factory() external view returns (address);

  function minter() external view returns (address);

  function length() external view returns (uint);

  function gauges(address pool) external view returns (address);

  function weights(address pool) external view returns (uint);

  function isGauge(address _gauge) external view returns (bool);

  function external_bribes(address gauge) external view returns (address);

  function poolByIndex(uint _index) external view returns (address);

  function is3poolGauge(address _gauge) external view returns (bool);

  function poolForGauge(address _gauge) external view returns (address);

  function _LPTokenTo3Pool(address _LPToken) external view returns (address);

  function votesByNFTAndPool(
    uint _tokenId,
    address _pool
  ) external view returns (uint);

  function governor() external view returns (address);

  function emergencyCouncil() 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 isWhitelisted(address token) external view returns (bool);

  function notifyRewardAmount(uint amount) external;

  function distribute(address _gauge) external;

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

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IVotingEscrow {
  struct Point {
    int128 bias;
    int128 slope; // # -dweight / dt
    uint256 ts;
    uint256 blk; // block
  }

  function tokenId() external view returns (uint);

  function token() external view returns (address);

  function team() external returns (address);

  function epoch() external view returns (uint);

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

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

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

  function ownerOf(uint) external view returns (address);

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

  function transferFrom(address, address, uint) external;

  function voting(uint tokenId) external;

  function abstain(uint tokenId) external;

  function attach(uint tokenId) external;

  function detach(uint tokenId) external;

  function checkpoint() external;

  function deposit_for(uint tokenId, uint value) external;

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

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

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

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IWrappedExternalBribeFactory {
  function oldBribeToNew(address) external view returns (address);

  function metaBribe() external view returns (address);

  function createBribe(address existing_bribe) external returns (address);
}

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

  function cbrt(uint256 n) internal pure returns (uint256) {
    unchecked {
      uint256 x = 0;
      for (uint256 y = 1 << 255; y > 0; y >>= 3) {
        x <<= 1;
        uint256 z = 3 * x * (x + 1) + 1;
        if (n / y >= z) {
          n -= y * z;
          x += 1;
        }
      }
      return x;
    }
  }

  function sub(uint x, uint y) internal pure returns (uint z) {
    require((z = x - y) <= x, "Math: Sub-underflow");
  }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_voter","type":"address"},{"internalType":"address","name":"_old_bribe","type":"address"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_governor","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"}],"name":"ClaimRewards","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":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NotifyReward","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":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bool","name":"partner","type":"bool"},{"indexed":false,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NotifyRewardMetaBribe","type":"event"},{"inputs":[],"name":"SECONDS_PER_EPOCH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getEpochStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"getMetaBribe","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bool[]","name":"","type":"bool[]"},{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getPartnerBribesValue","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":"_i","type":"uint256"}],"name":"getRewardByIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getRewardForOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"getTotalBribesValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"getTotalPartnersBribesValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isPartnerToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isReward","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastEarn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"lastTimeRewardApplicable","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":"uint256","name":"","type":"uint256"}],"name":"metaBribeEpoch","outputs":[{"internalType":"uint256","name":"totalValue","type":"uint256"},{"internalType":"uint256","name":"totalValueFromPartners","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsListLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"setGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newRouter","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"address","name":"oldToken","type":"address"},{"internalType":"address","name":"newToken","type":"address"}],"name":"swapOutRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenRewardsPerEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying_bribe","outputs":[{"internalType":"contract ExternalBribe","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wxbFactory","outputs":[{"internalType":"contract IWrappedExternalBribeFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

0x60c06040526001600a553480156200001657600080fd5b50604051620026dd380380620026dd8339810160408190526200003991620002b2565b6001600160a01b038481166080819052600080546001600160a01b031990811686851617909155600180549091169284169290921790915560408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa158015620000ad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d391906200030f565b6001600160a01b0390811660a05260028054336001600160a01b0319918216179091556003805490911691851691909117905560005b600360009054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200015d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000183919062000334565b8110156200028a57600354604051637980d7a160e11b8152600481018390526000916001600160a01b03169063f301af4290602401602060405180830381865afa158015620001d6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fc91906200030f565b90506001600160a01b0381161562000274576001600160a01b0381166000818152600860205260408120805460ff191660019081179091556007805491820181559091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b03191690911790555b508062000281816200034e565b91505062000109565b505050505062000376565b80516001600160a01b0381168114620002ad57600080fd5b919050565b60008060008060808587031215620002c957600080fd5b620002d48562000295565b9350620002e46020860162000295565b9250620002f46040860162000295565b9150620003046060860162000295565b905092959194509250565b6000602082840312156200032257600080fd5b6200032d8262000295565b9392505050565b6000602082840312156200034757600080fd5b5051919050565b6000600182016200036f57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051612317620003c66000396000818161036101528181610e14015281816111ee0152611a6b0152600081816102a201528181610f42015281816111ab01526114a701526123176000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639647720911610104578063c42cf535116100a2578063f25e55a511610071578063f25e55a51461048d578063f301af42146104b8578063f5f8d365146104cb578063f887ea40146104de57600080fd5b8063c42cf5351461043f578063cf97675614610452578063da09d19d14610465578063e68863961461048557600080fd5b8063a4cc5882116100de578063a4cc5882146103fc578063a7852afa14610406578063aee8145d14610419578063c0d786551461042c57600080fd5b806396477209146103c3578063999ac29c146103d657806399bcc052146103e957600080fd5b80634d5ce0381161017c578063807cb6af1161014b578063807cb6af146103205780638dd598fb1461035c57806392777b29146103835780639418f939146103ae57600080fd5b80634d5ce038146102c45780634eef6526146102e7578063638634ee146102fa5780636c4f53981461030d57600080fd5b8063312d7d35116101b8578063312d7d35146102535780633e491d47146102775780633f895e7f1461028a57806346c96aac1461029d57600080fd5b80630175e23b146101df5780630c340a24146102055780630d3dce3614610230575b600080fd5b6101f26101ed366004611e35565b6104f1565b6040519081526020015b60405180910390f35b600154610218906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61024361023e366004611e35565b610533565b60405190151581526020016101fc565b610266610261366004611e4e565b61061f565b6040516101fc959493929190611ee4565b6101f2610285366004611f9f565b61097b565b600254610218906001600160a01b031681565b6102187f000000000000000000000000000000000000000000000000000000000000000081565b6102436102d2366004611fcb565b60086020526000908152604090205460ff1681565b6102186102f5366004611e35565b610dbe565b6101f2610308366004611fcb565b610dee565b600354610218906001600160a01b031681565b61034761032e366004611e35565b6009602052600090815260409020805460019091015482565b604080519283526020830191909152016101fc565b6102187f000000000000000000000000000000000000000000000000000000000000000081565b6101f2610391366004611f9f565b600460209081526000928352604080842090915290825290205481565b6103c16103bc366004611fe8565b610e12565b005b6101f26103d1366004611e35565b611079565b6101f26103e4366004611e4e565b6110a1565b6101f26103f7366004611fcb565b611153565b6101f262093a8081565b6103c1610414366004612040565b61118c565b6101f2610427366004611e35565b61138c565b6103c161043a366004611fcb565b6113b2565b6103c161044d366004611fcb565b6113fe565b6103c1610460366004612111565b61144a565b6101f2610473366004611fcb565b60056020526000908152604090205481565b6007546101f2565b6101f261049b366004611f9f565b600660209081526000928352604080842090915290825290205481565b6102186104c6366004611e35565b611a11565b6103c16104d9366004612040565b611a3b565b600054610218906001600160a01b031681565b6000806104fd83611c0f565b9050600061050e62093a808361216f565b90508084106105295761052462093a808361216f565b61052b565b815b949350505050565b600080600260009054906101000a90046001600160a01b03166001600160a01b031663cd0c3eaa6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ad9190612187565b60405162c84f8b60e61b8152600481018590529091506001600160a01b03821690633213e2c090602401602060405180830381865afa1580156105f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061891906121a4565b9392505050565b600081815260096020908152604080832085845260020190915281208054606092839283928392839291908167ffffffffffffffff8111156106635761066361202a565b60405190808252806020026020018201604052801561068c578160200160208202803683370190505b50905060008267ffffffffffffffff8111156106aa576106aa61202a565b6040519080825280602002602001820160405280156106d3578160200160208202803683370190505b50905060008367ffffffffffffffff8111156106f1576106f161202a565b60405190808252806020026020018201604052801561071a578160200160208202803683370190505b50905060008467ffffffffffffffff8111156107385761073861202a565b604051908082528060200260200182016040528015610761578160200160208202803683370190505b50905060008567ffffffffffffffff81111561077f5761077f61202a565b6040519080825280602002602001820160405280156107a8578160200160208202803683370190505b50905060005b86811015610965578781815481106107c8576107c86121c6565b600091825260209091206004909102015486516001600160a01b03909116908790839081106107f9576107f96121c6565b60200260200101906001600160a01b031690816001600160a01b03168152505087818154811061082b5761082b6121c6565b90600052602060002090600402016001015485828151811061084f5761084f6121c6565b60200260200101818152505087818154811061086d5761086d6121c6565b906000526020600020906004020160020154848281518110610891576108916121c6565b6020026020010181815250508781815481106108af576108af6121c6565b906000526020600020906004020160030160009054906101000a900460ff168382815181106108e0576108e06121c6565b602002602001019015159081151581525050878181548110610904576109046121c6565b906000526020600020906004020160030160019054906101000a90046001600160a01b031682828151811061093b5761093b6121c6565b6001600160a01b03909216602092830291909101909101528061095d816121dc565b9150506107ae565b50939d929c50909a509850909650945050505050565b600354604051635058979360e01b8152600481018390526000916001600160a01b031690635058979390602401602060405180830381865afa1580156109c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e991906121f5565b6000036109f857506000610db8565b6001600160a01b03831660009081526006602090815260408083208584529091528120548190819060019082908190610a3090611c0f565b6003546040516328a3532760e21b8152600481018b9052602481018390529192506001600160a01b03169063a28d4c9c90604401602060405180830381865afa158015610a81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa591906121f5565b600354604051631277308160e21b8152600481018b9052602481018390529193506001600160a01b0316906349dcc204906044016040805180830381865afa158015610af5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b19919061220e565b9095509350610b3081610b2b87611c0f565b611c28565b905060005b6032811015610dae57610b4742611c0f565b8214610dae576003546001600160a01b031663a28d4c9c8a6001610b6e62093a808761216f565b610b789190612232565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa158015610bb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdd91906121f5565b600354604051631277308160e21b8152600481018c9052602481018390529194506001600160a01b0316906349dcc204906044016040805180830381865afa158015610c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c51919061220e565b60035491975095506001600160a01b031663f7412baf816376f4be366001610c7c62093a808861216f565b610c869190612232565b6040518263ffffffff1660e01b8152600401610ca491815260200190565b602060405180830381865afa158015610cc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce591906121f5565b6040518263ffffffff1660e01b8152600401610d0391815260200190565b6040805180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d43919061220e565b6001600160a01b038c166000908152600460209081526040808320878452909152902054909550859150610d779087612249565b610d81919061227e565b610d8b908861216f565b9650610d9a62093a808361216f565b915080610da6816121dc565b915050610b35565b5094955050505050505b92915050565b600060078281548110610dd357610dd36121c6565b6000918252602090912001546001600160a01b031692915050565b6001600160a01b038116600090815260056020526040812054610db8904290611c3f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e969190612187565b6001600160a01b0316336001600160a01b031614610ee75760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660078481548110610f0457610f046121c6565b6000918252602090912001546001600160a01b031614610f2357600080fd5b604051633af32abf60e01b81526001600160a01b0382811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fad91906121a4565b610ff95760405162461bcd60e51b815260206004820152601c60248201527f6e6577546f6b656e206d7573742062652077686974656c6973746564000000006044820152606401610ede565b6001600160a01b03808316600090815260086020526040808220805460ff1990811690915592841682529020805490911660011790556007805482919085908110611046576110466121c6565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600060096000611088846104f1565b8152602001908152602001600020600101549050919050565b60006110ac836104f1565b6000818152600960209081526040808320868452600201909152812091945090815b8154811015611149578181815481106110e9576110e96121c6565b600091825260209091206003600490920201015460ff161561113757818181548110611117576111176121c6565b90600052602060002090600402016002015483611134919061216f565b92505b80611141816121dc565b9150506110ce565b5090949350505050565b60008061115f426104f1565b6001600160a01b039093166000908152600460209081526040808320958352949052929092205492915050565b600a5460011461119b57600080fd5b6002600a55336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111d557600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561123d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112619190612187565b905060005b8251811015611381576000611294848381518110611286576112866121c6565b60200260200101518661097b565b905042600660008685815181106112ad576112ad6121c6565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015611308576113088483815181106112f9576112f96121c6565b60200260200101518483611c4e565b83828151811061131a5761131a6121c6565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161136691815260200190565b60405180910390a35080611379816121dc565b915050611266565b50506001600a555050565b60006009600061139b846104f1565b815260208101919091526040016000205492915050565b6001546001600160a01b031633146113c957600080fd5b6001600160a01b0381166113dc57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461141557600080fd5b6001600160a01b03811661142857600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600a5460011461145957600080fd5b6002600a558261146857600080fd5b6001600160a01b03841660009081526008602052604090205460ff166115b057604051633af32abf60e01b81526001600160a01b0385811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa1580156114ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151291906121a4565b61155e5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610ede565b6007546010116115b05760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610ede565b60006115bb426104f1565b6001600160a01b03861660009081526004602090815260408083208484529091529020549091506115ee86333088611d3d565b6115f8858261216f565b6001600160a01b038716600090815260046020908152604080832086845290915290205561162962093a808361216f565b6001600160a01b03871660009081526005602090815260408083209390935560089052205460ff166116bb576001600160a01b0386166000818152600860205260408120805460ff191660019081179091556007805491820181559091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b03191690911790555b600254604080516366861f5560e11b815290516000926001600160a01b03169163cd0c3eaa9160048083019260209291908290030181865afa158015611705573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117299190612187565b90506000816001600160a01b03166378a231728989856001600160a01b031663e5a6b10f6040518163ffffffff1660e01b81526004016020604051808303816000875af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612187565b60405160e085901b6001600160e01b03191681526001600160a01b03938416600482015260248101929092529091166044820152606401602060405180830381865afa1580156117f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181a91906121f5565b9050600061182786610533565b90506009600086815260200190815260200160002060020160008781526020019081526020016000206040518060a001604052808b6001600160a01b031681526020018a81526020018481526020018315158152602001896001600160a01b0316815250908060018154018082558091505060019003906000526020600020906004020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015560608201518160030160006101000a81548160ff02191690831515021790555060808201518160030160016101000a8154816001600160a01b0302191690836001600160a01b0316021790555050508160096000878152602001908152602001600020600001600082825461196a919061216f565b9091555050801561199c576000858152600960205260408120600101805484929061199690849061216f565b90915550505b60408051868152602081018a905290810183905281151560608201526001600160a01b03888116608083015260a082018890528a169033907f8abb4e0f19ff083cfe74e0cbc9faa4deb11e0be1e1c65bf39ce07dc5d30ffde29060c00160405180910390a350506001600a5550505050505050565b60078181548110611a2157600080fd5b6000918252602090912001546001600160a01b0316905081565b600a54600114611a4a57600080fd5b6002600a5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ade91906121a4565b611ae757600080fd5b60005b8151811015611c05576000611b18838381518110611b0a57611b0a6121c6565b60200260200101518561097b565b90504260066000858581518110611b3157611b316121c6565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208882529092529020558015611b8c57611b8c838381518110611b7d57611b7d6121c6565b60200260200101513383611c4e565b828281518110611b9e57611b9e6121c6565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051611bea91815260200190565b60405180910390a35080611bfd816121dc565b915050611aea565b50506001600a5550565b6000611c1e62093a8083612292565b610db89083612232565b600081831015611c385781610618565b5090919050565b6000818310611c385781610618565b6000836001600160a01b03163b11611c6557600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611cc191906122a6565b6000604051808303816000865af19150503d8060008114611cfe576040519150601f19603f3d011682016040523d82523d6000602084013e611d03565b606091505b5091509150818015611d2d575080511580611d2d575080806020019051810190611d2d91906121a4565b611d3657600080fd5b5050505050565b6000846001600160a01b03163b11611d5457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611db891906122a6565b6000604051808303816000865af19150503d8060008114611df5576040519150601f19603f3d011682016040523d82523d6000602084013e611dfa565b606091505b5091509150818015611e24575080511580611e24575080806020019051810190611e2491906121a4565b611e2d57600080fd5b505050505050565b600060208284031215611e4757600080fd5b5035919050565b60008060408385031215611e6157600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015611ea95781516001600160a01b031687529582019590820190600101611e84565b509495945050505050565b600081518084526020808501945080840160005b83811015611ea957815187529582019590820190600101611ec8565b60a081526000611ef760a0830188611e70565b602083820381850152611f0a8289611eb4565b91508382036040850152611f1e8288611eb4565b8481036060860152865180825282880193509082019060005b81811015611f55578451151583529383019391830191600101611f37565b50508481036080860152611f698187611e70565b9a9950505050505050505050565b6001600160a01b0381168114611f8c57600080fd5b50565b8035611f9a81611f77565b919050565b60008060408385031215611fb257600080fd5b8235611fbd81611f77565b946020939093013593505050565b600060208284031215611fdd57600080fd5b813561061881611f77565b600080600060608486031215611ffd57600080fd5b83359250602084013561200f81611f77565b9150604084013561201f81611f77565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561205357600080fd5b8235915060208084013567ffffffffffffffff8082111561207357600080fd5b818601915086601f83011261208757600080fd5b8135818111156120995761209961202a565b8060051b604051601f19603f830116810181811085821117156120be576120be61202a565b6040529182528482019250838101850191898311156120dc57600080fd5b938501935b82851015612101576120f285611f8f565b845293850193928501926120e1565b8096505050505050509250929050565b6000806000806080858703121561212757600080fd5b843561213281611f77565b935060208501359250604085013561214981611f77565b9396929550929360600135925050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561218257612182612159565b500190565b60006020828403121561219957600080fd5b815161061881611f77565b6000602082840312156121b657600080fd5b8151801515811461061857600080fd5b634e487b7160e01b600052603260045260246000fd5b6000600182016121ee576121ee612159565b5060010190565b60006020828403121561220757600080fd5b5051919050565b6000806040838503121561222157600080fd5b505080516020909101519092909150565b60008282101561224457612244612159565b500390565b600081600019048311821515161561226357612263612159565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261228d5761228d612268565b500490565b6000826122a1576122a1612268565b500690565b6000825160005b818110156122c757602081860181015185830152016122ad565b818111156122d6576000828501525b50919091019291505056fea26469706673582212205d3c0c8a256d31187e647c785e3784947638272e9b2de3dc1b16c79787c38a9764736f6c634300080d0033000000000000000000000000d14884b51ff6cda4f6f92f0fe7ac198c6c63bc7a000000000000000000000000773c23e3c6c36cde603f2c0940f678324417b276000000000000000000000000e856d35f554a6656d70ccf1b11d4ae7cee24f473000000000000000000000000a01e41f99bbea25e9c061acca72cf544a9c8cc91

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101da5760003560e01c80639647720911610104578063c42cf535116100a2578063f25e55a511610071578063f25e55a51461048d578063f301af42146104b8578063f5f8d365146104cb578063f887ea40146104de57600080fd5b8063c42cf5351461043f578063cf97675614610452578063da09d19d14610465578063e68863961461048557600080fd5b8063a4cc5882116100de578063a4cc5882146103fc578063a7852afa14610406578063aee8145d14610419578063c0d786551461042c57600080fd5b806396477209146103c3578063999ac29c146103d657806399bcc052146103e957600080fd5b80634d5ce0381161017c578063807cb6af1161014b578063807cb6af146103205780638dd598fb1461035c57806392777b29146103835780639418f939146103ae57600080fd5b80634d5ce038146102c45780634eef6526146102e7578063638634ee146102fa5780636c4f53981461030d57600080fd5b8063312d7d35116101b8578063312d7d35146102535780633e491d47146102775780633f895e7f1461028a57806346c96aac1461029d57600080fd5b80630175e23b146101df5780630c340a24146102055780630d3dce3614610230575b600080fd5b6101f26101ed366004611e35565b6104f1565b6040519081526020015b60405180910390f35b600154610218906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61024361023e366004611e35565b610533565b60405190151581526020016101fc565b610266610261366004611e4e565b61061f565b6040516101fc959493929190611ee4565b6101f2610285366004611f9f565b61097b565b600254610218906001600160a01b031681565b6102187f000000000000000000000000d14884b51ff6cda4f6f92f0fe7ac198c6c63bc7a81565b6102436102d2366004611fcb565b60086020526000908152604090205460ff1681565b6102186102f5366004611e35565b610dbe565b6101f2610308366004611fcb565b610dee565b600354610218906001600160a01b031681565b61034761032e366004611e35565b6009602052600090815260409020805460019091015482565b604080519283526020830191909152016101fc565b6102187f00000000000000000000000028a8e21cfe4586002b4829ebdd7f6f3d88ed79c181565b6101f2610391366004611f9f565b600460209081526000928352604080842090915290825290205481565b6103c16103bc366004611fe8565b610e12565b005b6101f26103d1366004611e35565b611079565b6101f26103e4366004611e4e565b6110a1565b6101f26103f7366004611fcb565b611153565b6101f262093a8081565b6103c1610414366004612040565b61118c565b6101f2610427366004611e35565b61138c565b6103c161043a366004611fcb565b6113b2565b6103c161044d366004611fcb565b6113fe565b6103c1610460366004612111565b61144a565b6101f2610473366004611fcb565b60056020526000908152604090205481565b6007546101f2565b6101f261049b366004611f9f565b600660209081526000928352604080842090915290825290205481565b6102186104c6366004611e35565b611a11565b6103c16104d9366004612040565b611a3b565b600054610218906001600160a01b031681565b6000806104fd83611c0f565b9050600061050e62093a808361216f565b90508084106105295761052462093a808361216f565b61052b565b815b949350505050565b600080600260009054906101000a90046001600160a01b03166001600160a01b031663cd0c3eaa6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ad9190612187565b60405162c84f8b60e61b8152600481018590529091506001600160a01b03821690633213e2c090602401602060405180830381865afa1580156105f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061891906121a4565b9392505050565b600081815260096020908152604080832085845260020190915281208054606092839283928392839291908167ffffffffffffffff8111156106635761066361202a565b60405190808252806020026020018201604052801561068c578160200160208202803683370190505b50905060008267ffffffffffffffff8111156106aa576106aa61202a565b6040519080825280602002602001820160405280156106d3578160200160208202803683370190505b50905060008367ffffffffffffffff8111156106f1576106f161202a565b60405190808252806020026020018201604052801561071a578160200160208202803683370190505b50905060008467ffffffffffffffff8111156107385761073861202a565b604051908082528060200260200182016040528015610761578160200160208202803683370190505b50905060008567ffffffffffffffff81111561077f5761077f61202a565b6040519080825280602002602001820160405280156107a8578160200160208202803683370190505b50905060005b86811015610965578781815481106107c8576107c86121c6565b600091825260209091206004909102015486516001600160a01b03909116908790839081106107f9576107f96121c6565b60200260200101906001600160a01b031690816001600160a01b03168152505087818154811061082b5761082b6121c6565b90600052602060002090600402016001015485828151811061084f5761084f6121c6565b60200260200101818152505087818154811061086d5761086d6121c6565b906000526020600020906004020160020154848281518110610891576108916121c6565b6020026020010181815250508781815481106108af576108af6121c6565b906000526020600020906004020160030160009054906101000a900460ff168382815181106108e0576108e06121c6565b602002602001019015159081151581525050878181548110610904576109046121c6565b906000526020600020906004020160030160019054906101000a90046001600160a01b031682828151811061093b5761093b6121c6565b6001600160a01b03909216602092830291909101909101528061095d816121dc565b9150506107ae565b50939d929c50909a509850909650945050505050565b600354604051635058979360e01b8152600481018390526000916001600160a01b031690635058979390602401602060405180830381865afa1580156109c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e991906121f5565b6000036109f857506000610db8565b6001600160a01b03831660009081526006602090815260408083208584529091528120548190819060019082908190610a3090611c0f565b6003546040516328a3532760e21b8152600481018b9052602481018390529192506001600160a01b03169063a28d4c9c90604401602060405180830381865afa158015610a81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa591906121f5565b600354604051631277308160e21b8152600481018b9052602481018390529193506001600160a01b0316906349dcc204906044016040805180830381865afa158015610af5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b19919061220e565b9095509350610b3081610b2b87611c0f565b611c28565b905060005b6032811015610dae57610b4742611c0f565b8214610dae576003546001600160a01b031663a28d4c9c8a6001610b6e62093a808761216f565b610b789190612232565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa158015610bb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdd91906121f5565b600354604051631277308160e21b8152600481018c9052602481018390529194506001600160a01b0316906349dcc204906044016040805180830381865afa158015610c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c51919061220e565b60035491975095506001600160a01b031663f7412baf816376f4be366001610c7c62093a808861216f565b610c869190612232565b6040518263ffffffff1660e01b8152600401610ca491815260200190565b602060405180830381865afa158015610cc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce591906121f5565b6040518263ffffffff1660e01b8152600401610d0391815260200190565b6040805180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d43919061220e565b6001600160a01b038c166000908152600460209081526040808320878452909152902054909550859150610d779087612249565b610d81919061227e565b610d8b908861216f565b9650610d9a62093a808361216f565b915080610da6816121dc565b915050610b35565b5094955050505050505b92915050565b600060078281548110610dd357610dd36121c6565b6000918252602090912001546001600160a01b031692915050565b6001600160a01b038116600090815260056020526040812054610db8904290611c3f565b7f00000000000000000000000028a8e21cfe4586002b4829ebdd7f6f3d88ed79c16001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e969190612187565b6001600160a01b0316336001600160a01b031614610ee75760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660078481548110610f0457610f046121c6565b6000918252602090912001546001600160a01b031614610f2357600080fd5b604051633af32abf60e01b81526001600160a01b0382811660048301527f000000000000000000000000d14884b51ff6cda4f6f92f0fe7ac198c6c63bc7a1690633af32abf90602401602060405180830381865afa158015610f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fad91906121a4565b610ff95760405162461bcd60e51b815260206004820152601c60248201527f6e6577546f6b656e206d7573742062652077686974656c6973746564000000006044820152606401610ede565b6001600160a01b03808316600090815260086020526040808220805460ff1990811690915592841682529020805490911660011790556007805482919085908110611046576110466121c6565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600060096000611088846104f1565b8152602001908152602001600020600101549050919050565b60006110ac836104f1565b6000818152600960209081526040808320868452600201909152812091945090815b8154811015611149578181815481106110e9576110e96121c6565b600091825260209091206003600490920201015460ff161561113757818181548110611117576111176121c6565b90600052602060002090600402016002015483611134919061216f565b92505b80611141816121dc565b9150506110ce565b5090949350505050565b60008061115f426104f1565b6001600160a01b039093166000908152600460209081526040808320958352949052929092205492915050565b600a5460011461119b57600080fd5b6002600a55336001600160a01b037f000000000000000000000000d14884b51ff6cda4f6f92f0fe7ac198c6c63bc7a16146111d557600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000028a8e21cfe4586002b4829ebdd7f6f3d88ed79c16001600160a01b031690636352211e90602401602060405180830381865afa15801561123d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112619190612187565b905060005b8251811015611381576000611294848381518110611286576112866121c6565b60200260200101518661097b565b905042600660008685815181106112ad576112ad6121c6565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015611308576113088483815181106112f9576112f96121c6565b60200260200101518483611c4e565b83828151811061131a5761131a6121c6565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161136691815260200190565b60405180910390a35080611379816121dc565b915050611266565b50506001600a555050565b60006009600061139b846104f1565b815260208101919091526040016000205492915050565b6001546001600160a01b031633146113c957600080fd5b6001600160a01b0381166113dc57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461141557600080fd5b6001600160a01b03811661142857600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600a5460011461145957600080fd5b6002600a558261146857600080fd5b6001600160a01b03841660009081526008602052604090205460ff166115b057604051633af32abf60e01b81526001600160a01b0385811660048301527f000000000000000000000000d14884b51ff6cda4f6f92f0fe7ac198c6c63bc7a1690633af32abf90602401602060405180830381865afa1580156114ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151291906121a4565b61155e5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610ede565b6007546010116115b05760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610ede565b60006115bb426104f1565b6001600160a01b03861660009081526004602090815260408083208484529091529020549091506115ee86333088611d3d565b6115f8858261216f565b6001600160a01b038716600090815260046020908152604080832086845290915290205561162962093a808361216f565b6001600160a01b03871660009081526005602090815260408083209390935560089052205460ff166116bb576001600160a01b0386166000818152600860205260408120805460ff191660019081179091556007805491820181559091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b03191690911790555b600254604080516366861f5560e11b815290516000926001600160a01b03169163cd0c3eaa9160048083019260209291908290030181865afa158015611705573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117299190612187565b90506000816001600160a01b03166378a231728989856001600160a01b031663e5a6b10f6040518163ffffffff1660e01b81526004016020604051808303816000875af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612187565b60405160e085901b6001600160e01b03191681526001600160a01b03938416600482015260248101929092529091166044820152606401602060405180830381865afa1580156117f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181a91906121f5565b9050600061182786610533565b90506009600086815260200190815260200160002060020160008781526020019081526020016000206040518060a001604052808b6001600160a01b031681526020018a81526020018481526020018315158152602001896001600160a01b0316815250908060018154018082558091505060019003906000526020600020906004020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015560608201518160030160006101000a81548160ff02191690831515021790555060808201518160030160016101000a8154816001600160a01b0302191690836001600160a01b0316021790555050508160096000878152602001908152602001600020600001600082825461196a919061216f565b9091555050801561199c576000858152600960205260408120600101805484929061199690849061216f565b90915550505b60408051868152602081018a905290810183905281151560608201526001600160a01b03888116608083015260a082018890528a169033907f8abb4e0f19ff083cfe74e0cbc9faa4deb11e0be1e1c65bf39ce07dc5d30ffde29060c00160405180910390a350506001600a5550505050505050565b60078181548110611a2157600080fd5b6000918252602090912001546001600160a01b0316905081565b600a54600114611a4a57600080fd5b6002600a5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000028a8e21cfe4586002b4829ebdd7f6f3d88ed79c16001600160a01b03169063430c208190604401602060405180830381865afa158015611aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ade91906121a4565b611ae757600080fd5b60005b8151811015611c05576000611b18838381518110611b0a57611b0a6121c6565b60200260200101518561097b565b90504260066000858581518110611b3157611b316121c6565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208882529092529020558015611b8c57611b8c838381518110611b7d57611b7d6121c6565b60200260200101513383611c4e565b828281518110611b9e57611b9e6121c6565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051611bea91815260200190565b60405180910390a35080611bfd816121dc565b915050611aea565b50506001600a5550565b6000611c1e62093a8083612292565b610db89083612232565b600081831015611c385781610618565b5090919050565b6000818310611c385781610618565b6000836001600160a01b03163b11611c6557600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611cc191906122a6565b6000604051808303816000865af19150503d8060008114611cfe576040519150601f19603f3d011682016040523d82523d6000602084013e611d03565b606091505b5091509150818015611d2d575080511580611d2d575080806020019051810190611d2d91906121a4565b611d3657600080fd5b5050505050565b6000846001600160a01b03163b11611d5457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611db891906122a6565b6000604051808303816000865af19150503d8060008114611df5576040519150601f19603f3d011682016040523d82523d6000602084013e611dfa565b606091505b5091509150818015611e24575080511580611e24575080806020019051810190611e2491906121a4565b611e2d57600080fd5b505050505050565b600060208284031215611e4757600080fd5b5035919050565b60008060408385031215611e6157600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015611ea95781516001600160a01b031687529582019590820190600101611e84565b509495945050505050565b600081518084526020808501945080840160005b83811015611ea957815187529582019590820190600101611ec8565b60a081526000611ef760a0830188611e70565b602083820381850152611f0a8289611eb4565b91508382036040850152611f1e8288611eb4565b8481036060860152865180825282880193509082019060005b81811015611f55578451151583529383019391830191600101611f37565b50508481036080860152611f698187611e70565b9a9950505050505050505050565b6001600160a01b0381168114611f8c57600080fd5b50565b8035611f9a81611f77565b919050565b60008060408385031215611fb257600080fd5b8235611fbd81611f77565b946020939093013593505050565b600060208284031215611fdd57600080fd5b813561061881611f77565b600080600060608486031215611ffd57600080fd5b83359250602084013561200f81611f77565b9150604084013561201f81611f77565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561205357600080fd5b8235915060208084013567ffffffffffffffff8082111561207357600080fd5b818601915086601f83011261208757600080fd5b8135818111156120995761209961202a565b8060051b604051601f19603f830116810181811085821117156120be576120be61202a565b6040529182528482019250838101850191898311156120dc57600080fd5b938501935b82851015612101576120f285611f8f565b845293850193928501926120e1565b8096505050505050509250929050565b6000806000806080858703121561212757600080fd5b843561213281611f77565b935060208501359250604085013561214981611f77565b9396929550929360600135925050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561218257612182612159565b500190565b60006020828403121561219957600080fd5b815161061881611f77565b6000602082840312156121b657600080fd5b8151801515811461061857600080fd5b634e487b7160e01b600052603260045260246000fd5b6000600182016121ee576121ee612159565b5060010190565b60006020828403121561220757600080fd5b5051919050565b6000806040838503121561222157600080fd5b505080516020909101519092909150565b60008282101561224457612244612159565b500390565b600081600019048311821515161561226357612263612159565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261228d5761228d612268565b500490565b6000826122a1576122a1612268565b500690565b6000825160005b818110156122c757602081860181015185830152016122ad565b818111156122d6576000828501525b50919091019291505056fea26469706673582212205d3c0c8a256d31187e647c785e3784947638272e9b2de3dc1b16c79787c38a9764736f6c634300080d0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.