FTM Price: $1.03 (-2.59%)
Gas: 119 GWei

Contract

0x841eF913b7b1808CF603D053bA465919B217AbB9
 

Sponsored

Transaction Hash
Method
Block
From
To
Value
Withdraw564950162023-02-25 14:47:58396 days ago1677336478IN
0x841eF913...9B217AbB9
0 FTM0.0050248327.58758639
Get Reward564949222023-02-25 14:45:49396 days ago1677336349IN
0x841eF913...9B217AbB9
0 FTM0.0068018227.58758639
Get Reward456224702022-08-25 2:00:41581 days ago1661392841IN
0x841eF913...9B217AbB9
0 FTM0.000551412.5
Withdraw456223692022-08-25 1:58:52581 days ago1661392732IN
0x841eF913...9B217AbB9
0 FTM0.000639362.5
Get Reward453103302022-08-20 14:45:11585 days ago1661006711IN
0x841eF913...9B217AbB9
0 FTM0.00061992.5
Get Reward451353302022-08-18 1:38:11588 days ago1660786691IN
0x841eF913...9B217AbB9
0 FTM0.0042711219.36458042
Withdraw451352822022-08-18 1:36:26588 days ago1660786586IN
0x841eF913...9B217AbB9
0 FTM0.0049750719.45312935
Get Reward451347472022-08-18 1:22:32588 days ago1660785752IN
0x841eF913...9B217AbB9
0 FTM0.000978153.94478056
Get Reward451347222022-08-18 1:22:06588 days ago1660785726IN
0x841eF913...9B217AbB9
0 FTM0.001050944.23830687
Get Reward447202452022-08-12 3:12:05594 days ago1660273925IN
0x841eF913...9B217AbB9
0 FTM0.000684512.7605424
Get Reward443275472022-08-06 7:38:29600 days ago1659771509IN
0x841eF913...9B217AbB9
0 FTM0.000657272.80549319
Deposit436617922022-07-27 13:55:47610 days ago1658930147IN
0x841eF913...9B217AbB9
0 FTM0.0153654255.92327196
Get Reward423840092022-07-09 14:14:28628 days ago1657376068IN
0x841eF913...9B217AbB9
0 FTM0.000587892.50932379
Deposit420722222022-07-05 11:50:04632 days ago1657021804IN
0x841eF913...9B217AbB9
0 FTM0.001312535.19079344
Withdraw398000222022-06-04 23:42:51662 days ago1654386171IN
0x841eF913...9B217AbB9
0 FTM0.001463756.13295024
Get Reward397997552022-06-04 23:38:04662 days ago1654385884IN
0x841eF913...9B217AbB9
0 FTM0.001578956.31091292
Get Reward393161682022-05-29 10:35:36669 days ago1653820536IN
0x841eF913...9B217AbB9
0 FTM0.000901873.6046914
Withdraw385883452022-05-19 13:50:01679 days ago1652968201IN
0x841eF913...9B217AbB9
0 FTM0.05319892222.91703334
Get Reward385883042022-05-19 13:49:19679 days ago1652968159IN
0x841eF913...9B217AbB9
0 FTM0.06318222252.53194133
Get Reward383493562022-05-16 7:14:09682 days ago1652685249IN
0x841eF913...9B217AbB9
0 FTM0.537721532,149.20976121
Get Reward383020082022-05-15 14:54:34682 days ago1652626474IN
0x841eF913...9B217AbB9
0 FTM0.12192151462.0426952
Get Reward382837172022-05-15 8:57:59683 days ago1652605079IN
0x841eF913...9B217AbB9
0 FTM0.08858166396.34919447
Withdraw380994342022-05-12 13:54:05686 days ago1652363645IN
0x841eF913...9B217AbB9
0 FTM0.370946111,554.35856203
Get Reward380740032022-05-12 2:43:52686 days ago1652323432IN
0x841eF913...9B217AbB9
0 FTM0.283987771,270.67292
Withdraw380715482022-05-12 1:38:51686 days ago1652319531IN
0x841eF913...9B217AbB9
0 FTM0.355954271,391.8110315
View all transactions

Latest 1 internal transaction

Parent Txn Hash Block From To Value
374429822022-05-03 7:47:07695 days ago1651564027  Contract Creation0 FTM
Loading...
Loading

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

Contract Name:
SpiritBoostedFarm

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 4 : SpiritBoostedFarm.sol
pragma solidity ^0.6.7;

import "./libraries/SafeMath.sol";
import "./libraries/SafeERC20.sol";

abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor () public {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

interface IGauge {
    function derivedBalances(address account) external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function rewards(address account) external view returns (uint256);
    function earned(address account) external view returns (uint256);
    function TOKEN() external view returns (address);
}

interface IDepositor {
    function deposit(address _gauge, address _underlying) external;
    function withdraw(address _gauge, address _underlying, uint256 _amount) external;
    function withdrawAll(address _gauge, address _underlying) external;
    function claimGaugeReward(address _gauge) external;
}

interface IRewardsHandlerForBoostedFarm {
    function handleRewards(
        address token,
        uint256 amount,
        address account,
        bytes32[] memory params
    ) external;
}

interface IZapperForBoostedFarm {
    function unzip(
        address token,
        uint256 amount,
        address acount,
        bytes32[] memory params
    ) external;
}

contract SpiritBoostedFarm is ReentrancyGuard {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    event NewOwner(address indexed oldOwner, address indexed newOwner);
    event NewRewardsFeeRate(uint oldRewardsFeeRate, uint newRewardsFeeRate);
    event NewTreasury(address indexed oldTreasury, address indexed newTreasury);

    event FarmRetired(uint lpBalance, uint rewardBalance);

    /// @notice the address that holds our inSPIRIT (ie. strategy proxy) and the one that would deposit the LPs in the gauges
    address public constant DEPOSITOR = address(0x099EA71e5B0C7E350dee2f5EA397AB4E7C489580);
    address public constant SPIRIT = address(0x5Cc61A78F164885776AA610fb0FE1257df78E59B);
    address public immutable GAUGE;
    address public immutable TOKEN; // gauge token

    address public owner;
    address public treasury;
    uint256 public rewardFeeRate;
    bool public retired;

    mapping(address => uint256) public userRewardPerTokenPaid; // depositor indexes
    mapping(address => uint256) public rewards;
    mapping(address => uint256) private _balances;

    uint256 public rewardPerTokenStored; // general index 
    uint256 public totalSupply; // == gauge.balances(address(this))
    uint256 public totalReward;
    uint256 public rewardDistributed;

    mapping(address => bool) public rewardsClaimersWhitelist;
    address[] public rewardsClaimersList;
    mapping(IRewardsHandlerForBoostedFarm => bool) public rewardsHandlersWhitelist;
    IRewardsHandlerForBoostedFarm[] rewardsHandlersList;

    IZapperForBoostedFarm public zapper;

    event Staked(address indexed farmer, uint256 amount);
    event Withdrawn(address indexed farmer, uint256 amount, uint256 actualReceivedAmount);
    event RewardPaid(address indexed farmer, uint256 reward);
    event IndexUpdated(uint256 previousIndex, uint256 newIndex, uint256 deltaReward);
    event UserRewardUpdated(address indexed farmer, uint256 previousReward, uint256 newReward);
    event SetZapper(IZapperForBoostedFarm zapper);
    event WhitelistRewardsHandler(IRewardsHandlerForBoostedFarm handler, bool value); // value == true -> whitelisting, value == false -> blacklisting
    event WhitelistRewardsClaimer(address claimer, bool value); // value == true -> whitelisting, value == false -> blacklisting

    function isContract(address addr) public view returns (bool) {
      uint32 size;
      assembly {
        size := extcodesize(addr)
      }
      return (size > 0);
    }

    constructor(address _gauge, address _owner) public {
        require(_gauge != address(0), "no gauge");
        GAUGE = _gauge;
        require(isContract(_gauge), "Not contract");
        TOKEN = IGauge(_gauge).TOKEN();
        require(_owner != address(0), "no owner");
        owner = _owner;

        emit NewOwner(address(0), owner);
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "only owner");
        _;
    }

    // **** Views ****

    /**
     * @return The effective boost factor gained by farming via this contract
     */
    function getBoostFactor() external view returns (uint256) {
        // uint256 balance = IGauge(GAUGE).balanceOf(address(this));
        uint256 refBalance = totalSupply.mul(40).div(100);
        uint256 derivedBalance = IGauge(GAUGE).derivedBalances(DEPOSITOR);
        return derivedBalance.mul(1e18).div(refBalance);
    }

    /**
     * @param farmer address
     * @return The current balance of gauge tokens deposits by the farmer
     */
    function balanceOf(address farmer) external view returns (uint256) {
        return _balances[farmer];
    }

    /**
     * @return The amount of reward tokens the Depositor is entitled to (at the Gauge)
     */
    function rewardDelta() public view returns (uint256) {
        uint256 rewardsStored = IGauge(GAUGE).rewards(DEPOSITOR); // consider: use 'totalReward' instead of 'IGauge(GAUGE).rewards(DEPOSITOR)'
        uint256 rewardsCurrent = IGauge(GAUGE).earned(DEPOSITOR);
        return rewardsCurrent.sub(rewardsStored);
    }

    /**
     * @return The ratio between deposited gauge tokens and earned rewards
     */
    function rewardPerTokenCurrent() public view returns (uint256) {
        uint256 deltaReward = rewardDelta();
        uint256 supply = totalSupply;
        if (supply == 0 || deltaReward == 0) {
            return rewardPerTokenStored;
        }
        return rewardPerTokenStored.add(deltaReward.mul(1e18).div(supply));
    }

    /**
     * @notice Calculates the amount of rewards the farmer is currently entitled to before fee considerations
     * @param farmer address
     */
    function earnedCurrent(address farmer) public view returns (uint256) {
        uint256 rewardPerToken = rewardPerTokenCurrent();
        return _balances[farmer].mul(rewardPerToken.sub(userRewardPerTokenPaid[farmer])).div(1e18).add(rewards[farmer]);
    }

    /**
     * @notice Calculates the amount of rewards the farmer is currently entitled to after fee considerations
     * @param farmer address
     */
    function earnedCurrentMinusFee(address farmer) external view returns (uint256) {
        uint256 reward = earnedCurrent(farmer);
        uint256 feeAmount = reward.mul(rewardFeeRate).div(10000);
        uint256 userAmount = reward.sub(feeAmount);
        return userAmount;
    }

    // **** User Interactions ****

    /**
     * @notice Sender will deposit ALL gauge tokens they own
     */
    function depositAll() external {
        _deposit(msg.sender, msg.sender, IERC20(TOKEN).balanceOf(msg.sender));
    }

    /**
     * @notice Sender will deposit SOME gauge tokens
     * @param amount The GaugeToken amount to deposit
     */
    function deposit(uint amount) external {
        _deposit(msg.sender, msg.sender, amount);
    }

    /**
     * @notice Sender will deposit gauge tokens on behalf of the farmer
     * @param farmer The farmer who will get credited with the deposit
     * @param amount The GaugeToken amount to deposit
     */
    function depositOnBehalf(address farmer, uint amount) external {
        _deposit(farmer, msg.sender, amount);
    }

    /**
     * @notice Sender will withdraw ALL gauge token deposited
     * @dev Allowed after retire
     */
    function withdrawAll() public {
        bytes32[] memory empty;
        _withdraw(msg.sender, _balances[msg.sender], false, empty);
    }

    /**
     * @notice Sender will withdraw ALL gauge token deposited and will be using the zapper while withdrawing
     */
    function withdrawAllZapping(bytes32[] memory params) public {
        _withdraw(msg.sender, _balances[msg.sender], true, params);
    }

    /**
     * @notice Sender will withdraw SOME gauge tokens
     */
    function withdraw(uint256 amount) external {
        bytes32[] memory empty;
        _withdraw(msg.sender, amount, false, empty);
    }

    /**
     * @notice Sender will withdraw SOME gauge tokens and will be using the zapper while withdrawing
     */
    function withdrawZapping(uint256 amount, bytes32[] memory params) external {
        _withdraw(msg.sender, amount, true, params);
    }

    /**
     * @notice Sender will receive the rewards they are entitled to
     * @dev Allowed after retire
     */
    function getReward(IRewardsHandlerForBoostedFarm handler, bytes32[] memory params) public {
        _claimRewards(msg.sender, handler, params);
    }

    /**
     * @dev True if the given claimer is whitelisted
     */
    function isRewardsClaimerWhitelisted(address claimer) public view returns (bool) {
        return rewardsClaimersWhitelist[claimer];
    }

    /**
     * @dev True if the given handler is whitelisted
     */
    function isRewardsHandlerWhitelisted(IRewardsHandlerForBoostedFarm handler) public view returns (bool) {
        return rewardsHandlersWhitelist[handler];
    }

    /**
    * @notice Returns a list of all the whitelisted rewardsHandlers
    */
    function getRewardsHandlersWhitelist() external returns (IRewardsHandlerForBoostedFarm[] memory) {
        return rewardsHandlersList;
    }

    /**
    * @notice Returns a list of all the whitelisted rewardsClaimers
    */
    function getRewardsClaimersWhitelist() external returns (address[] memory) {
        return rewardsClaimersList;
    }

    /**
     * @notice Sender will receive the rewards they are entitled to
     * @dev Allowed after retire
     */
    function getRewardFor(address farmer, IRewardsHandlerForBoostedFarm handler, bytes32[] memory params) public {
        require(true == isRewardsClaimerWhitelisted(msg.sender), "!whitelisted claimer");
        _claimRewards(farmer, handler, params);
    }

    /**
     * @notice Sender will withdraw ALL gauge token deposited and receive all rewards they are entitled to
     * @dev Allowed after retire
     */
    function exit(IRewardsHandlerForBoostedFarm rewardsHandler, bytes32[] memory rewardsHandlerParams) external {
        withdrawAll();
        getReward(rewardsHandler, rewardsHandlerParams);
    }
    
    /**
     * @notice Sender will withdraw ALL gauge token deposited and receive all rewards they are entitled to and will be using the zapper while withdrawing
     */
    function exitZapping(IRewardsHandlerForBoostedFarm rewardsHandler, bytes32[] memory rewardsHandlerParams, bytes32[] memory zapperParams) external {
        withdrawAllZapping(zapperParams);
        getReward(rewardsHandler, rewardsHandlerParams);
    }

    // **** Admin Functions ****

    /**
     * @notice Retires the farm. Withdrawing all LP and rewards tokens to self.
     * @dev Retired farms cannot be reactivated.
     * @dev A farm should be retired before blacklisted.
     */
    function retireFarm() external onlyOwner nonReentrant{
        retired = true;

        if (0 < IGauge(GAUGE).balanceOf(DEPOSITOR)) {
            // DEPOSITOR withdraws all of TOKEN from GAUGE and sends it to 'farmer' namely to address(this)
            IDepositor(DEPOSITOR).withdrawAll(GAUGE, TOKEN);
        }
        uint256 ownLpBalance = IERC20(TOKEN).balanceOf(address(this));

        // DEPOSITOR pulls reward from gauge
        IDepositor(DEPOSITOR).claimGaugeReward(GAUGE);
        uint256 ownSpiritBalance = IERC20(SPIRIT).balanceOf(address(this));

        emit FarmRetired(ownLpBalance, ownSpiritBalance);
    }

    /**
     * @notice Admin function to set the owner address
     */
    function setOwner(address newOwner) external onlyOwner {
        require(newOwner != address(0), "no owner");
        require(newOwner != owner, "same owner");

        address oldOwner = owner;
        owner = newOwner;
        emit NewOwner(oldOwner, owner);
    }

    /**
     * @notice Admin function to set the fee
     * @dev The fee is divided by 10k so the maximum fee rate is 25%
     */
    function setRewardFeeRate(uint256 newRewardFeeRate) external onlyOwner {
        require(newRewardFeeRate <= 2500, "newRewardFeeRate too high");
        if (newRewardFeeRate > 0) {
            require(treasury != address(0), "treasury not set");
        }

        uint oldFeeRate = rewardFeeRate;
        rewardFeeRate = newRewardFeeRate;
        emit NewRewardsFeeRate(oldFeeRate, rewardFeeRate);
    }

    /**
    * @notice Admin function to set the zapper
    */
    function setZapper(IZapperForBoostedFarm _zapper) external onlyOwner {
        zapper = _zapper;
        emit SetZapper(_zapper);
    }

    /**
    * @notice Admin function to whitelist a rewards claimer
    */
    function whitelistRewardsClaimer(address claimer) external onlyOwner {
        require(false == rewardsClaimersWhitelist[claimer], "rewardsClaaimer already whitelisted");
        rewardsClaimersWhitelist[claimer] = true;
        rewardsClaimersList.push(claimer);

        emit WhitelistRewardsClaimer(claimer, true);
    }

    /**
    * @notice Admin function to blacklist a rewards claimer
    */
    function blacklistRewardsClaimer(address claimer, uint256 index) external onlyOwner {
        require(true == rewardsClaimersWhitelist[claimer], "rewardsClaimer isn't whitelisted");
        rewardsClaimersWhitelist[claimer] = false;

        uint256 listLength = rewardsClaimersList.length;
        require((index < listLength) && (rewardsClaimersList[index] == claimer), "Wrong index");
        rewardsClaimersList[index] = rewardsClaimersList[listLength - 1];
        rewardsClaimersList.pop();

        emit WhitelistRewardsClaimer(claimer, false);
    }

    /**
    * @notice Admin function to whitelist a rewards handler
    */
    function whitelistRewardsHandler(IRewardsHandlerForBoostedFarm handler) external onlyOwner {
        require(false == rewardsHandlersWhitelist[handler], "rewardsHandler already whitelisted");

        rewardsHandlersWhitelist[handler] = true;
        rewardsHandlersList.push(handler);

        emit WhitelistRewardsHandler(handler, true);
    }

    /**
    * @notice Admin function to blocklist a rewards handler
    */
    function blacklistRewardsHandler(IRewardsHandlerForBoostedFarm handler, uint256 index) external onlyOwner {
        require(true == rewardsHandlersWhitelist[handler], "rewardsHandler isn't whitelisted");
        rewardsHandlersWhitelist[handler] = false;

        uint256 listLength = rewardsHandlersList.length;
        require((index < listLength) && (rewardsHandlersList[index] == handler), "Wrong index");
        rewardsHandlersList[index] = rewardsHandlersList[listLength - 1];
        rewardsHandlersList.pop();

        emit WhitelistRewardsHandler(handler, false);
    }

    /**
     * @notice Admin function to set the treasury address
     * @param newTreasury address
     */
    function setTreasury(address newTreasury) external onlyOwner {
        if (newTreasury == address(0)) {
            require(rewardFeeRate == 0, "reward fee rate > 0");
        }

        address oldTreasury = treasury;
        treasury = newTreasury;
        emit NewTreasury(oldTreasury, treasury);
    }

    // **** Internal Views ****

    /**
     * @notice we pass rewardPerToken as input to avoid reading rewardPerTokenStored from state
     * @return The amount of rewards the farmer gained since the last time their
     */
    function earned(address farmer, uint256 rewardPerToken) internal view returns (uint256) {
        return _balances[farmer].mul(rewardPerToken.sub(userRewardPerTokenPaid[farmer])).div(1e18).add(rewards[farmer]);
    }

    // **** Internal NonReentereant Farm Functions ****

    function _deposit(address farmer, address payer, uint256 amount) internal nonReentrant {
        require(!retired, "retired");
        uint256 balanceBefore = IGauge(GAUGE).balanceOf(DEPOSITOR);
        uint256 rewardPrior = IGauge(GAUGE).rewards(DEPOSITOR);
        
        // DEPOSITOR deposits 'amount' of TOKEN to GAUGE (note: requires DEPOSITOR to approve GAUGE to spend)
        IERC20(TOKEN).safeTransferFrom(payer, DEPOSITOR, amount);
        IDepositor(DEPOSITOR).deposit(GAUGE, TOKEN);

        // verify something was indeed deposited in gauge
        uint256 balanceAfter = IGauge(GAUGE).balanceOf(DEPOSITOR);
        require(balanceAfter > balanceBefore, "nothing deposited");
        amount = balanceAfter.sub(balanceBefore);

        // update global index + total reward, and farmer's index + farmer's reward **before** updating farmer's balance and the total supply
        uint256 rewardAfter = IGauge(GAUGE).rewards(DEPOSITOR); 
        updateReward(farmer, rewardAfter.sub(rewardPrior));

        // update farmer's balance and the total supply
        _balances[farmer] = _balances[farmer].add(amount); // state
        totalSupply = totalSupply.add(amount); // state
        
        emit Staked(farmer, amount);
    }

    function _withdraw(address farmer, uint amount, bool zapping, bytes32[] memory params) internal nonReentrant {
        require(amount > 0, "Cannot withdraw 0");

        uint amountOut;

        if (!retired) {
            uint256 tokenBalanceBefore = IERC20(TOKEN).balanceOf(DEPOSITOR);
            uint256 balanceBefore = IGauge(GAUGE).balanceOf(DEPOSITOR);
            uint256 rewardPrior = IGauge(GAUGE).rewards(DEPOSITOR);

            // DEPOSITOR withdraws 'amount' of TOKEN from GAUGE and sends it to 'farmer' namely to address(this)
            IDepositor(DEPOSITOR).withdraw(GAUGE, TOKEN, amount);

            // verify something was indeed withdrawan from gauge
            uint256 balanceAfter = IGauge(GAUGE).balanceOf(DEPOSITOR);
            require(balanceAfter < balanceBefore, "nothing withdrawn");
            amount = balanceBefore.sub(balanceAfter);

            // update global index + total reward, and farmer's index + farmer's reward **before** updating farmer's balance and the total supply
            uint256 rewardAfter = IGauge(GAUGE).rewards(DEPOSITOR);
            updateReward(farmer, rewardAfter.sub(rewardPrior));

            // update farmer's balance and the total supply
            /// @notice fails if farmer is trying to withdraw more that they had deposited
            _balances[farmer] = _balances[farmer].sub(amount); // state
            totalSupply = totalSupply.sub(amount); // state

            uint256 tokenBalanceAfter = IERC20(TOKEN).balanceOf(address(this));
            require(tokenBalanceAfter > tokenBalanceBefore, "nothing received");
            amountOut = tokenBalanceAfter.sub(tokenBalanceBefore);
        } else {
            updateReward(farmer, 0);

            uint256 farmerBalance = _balances[farmer];
            // When retired, we don't allow partial withdrawals - only withdrawing all funds.
            require(amount == farmerBalance, "Can't partial withdraw when retired");

            // update farmer's balance and the total supply
            _balances[farmer] = 0;
            totalSupply = totalSupply.sub(amount); // state
            amountOut = amount;
        }

        // NO STATE CHANGES AFTER THIS LINE
        if (zapping) {
            require(address(0) != address(zapper), "!zapper");
            IERC20(TOKEN).safeTransfer(address(zapper), amountOut);
            zapper.unzip(TOKEN, amountOut, farmer, params);
        } else {
            IERC20(TOKEN).safeTransfer(farmer, amountOut);
        }

        emit Withdrawn(farmer, amount, amountOut);
    }

    function _claimRewards(address farmer, IRewardsHandlerForBoostedFarm rewardsHandler, bytes32[] memory params) internal nonReentrant {
        uint256 spiritBalanceAfter;

        if (!retired) {
            uint256 rewardPrior = IGauge(GAUGE).rewards(DEPOSITOR);
            uint256 spiritBalanceBefore = IERC20(SPIRIT).balanceOf(address(this));

            // DEPOSITOR pulls reward from gauge
            IDepositor(DEPOSITOR).claimGaugeReward(GAUGE);

            // update global index + total reward, and farmer's index + farmer's reward **before** updating farmer's balance and the total supply
            spiritBalanceAfter = IERC20(SPIRIT).balanceOf(address(this));

            uint256 spiritDelta = spiritBalanceAfter.sub(spiritBalanceBefore);
            updateReward(farmer, spiritDelta.sub(rewardPrior));
        } else {
            updateReward(farmer, 0);
            spiritBalanceAfter = IERC20(SPIRIT).balanceOf(address(this));
        }

        uint256 reward = rewards[farmer];
        if (reward > 0) {
            require(true == isRewardsHandlerWhitelisted(rewardsHandler), "RewardsHandler not whitelisted");
            require(spiritBalanceAfter >= reward, "SPIRIT balance not sufficient");
            rewards[farmer] = 0; // state
            rewardDistributed = rewardDistributed.add(reward); // state

            uint256 feeAmount = reward.mul(rewardFeeRate).div(10000);
            uint256 userAmount = reward.sub(feeAmount);

            // NO STATE CHANGES AFTER THIS LINE

            IERC20(SPIRIT).safeTransfer(treasury, feeAmount);
            IERC20(SPIRIT).safeTransfer(address(rewardsHandler), userAmount);
            rewardsHandler.handleRewards(SPIRIT, userAmount, msg.sender, params);

            emit RewardPaid(farmer, userAmount);
        }
    }

    // **** Internal Rewards Accounting Functions ****

    /**
     * @notice Updates the general farm 'index', then the farmer index.
     */
    function updateReward(address farmer, uint256 deltaReward) internal {
        // Updates gain rewards for the farm, if there was a change
//        if (deltaReward > 0) {
//            uint256 _previousIndex = rewardPerTokenStored;
//            uint256 _rewardPerTokenCurrent = rewardPerToken(deltaReward);
//            rewardPerTokenStored = _rewardPerTokenCurrent; // state
//            emit IndexUpdated(_previousIndex, _rewardPerTokenCurrent, deltaReward);
//        }

        uint256 _rewardPerTokenCurrent = updateRewardPerToken(deltaReward);

        uint256 _previousReward = rewards[farmer];
        uint256 _newReward = earned(farmer, _rewardPerTokenCurrent);
        rewards[farmer] = _newReward; // state
        userRewardPerTokenPaid[farmer] = _rewardPerTokenCurrent; // state

        emit UserRewardUpdated(farmer, _previousReward, _newReward);
    }

    /**
     * @notice Updates the 'rewardPerToken' index by the given deltaReward
     * @return The current (post change) 'rewardPerToken'
     * @dev Returning the updated value saves a bit of gas
     * @dev there isn't a good way to get the current rewardPerToken in a view function because 'deltaReward' can't be obtained
     */
    function updateRewardPerToken(uint256 deltaReward) internal returns (uint256) {
        uint256 supply = totalSupply;
        if (supply == 0 || deltaReward == 0) {
            return rewardPerTokenStored;
        }

        uint256 _previousIndex = rewardPerTokenStored;

        uint256 _rewardPerTokenCurrent = rewardPerTokenStored.add(deltaReward.mul(1e18).div(supply));

        /// @notice this state change is here for gas savings (if deltaReward == 0 no need to update 'totalReward')
        totalReward = totalReward.add(deltaReward); // state
        rewardPerTokenStored = _rewardPerTokenCurrent; // state

        emit IndexUpdated(_previousIndex, _rewardPerTokenCurrent, deltaReward);

        return _rewardPerTokenCurrent;
    }
}

File 2 of 4 : SafeMath.sol
pragma solidity ^0.6.7;

library SafeMath {
    function add(uint a, uint b) internal pure returns (uint) {
        uint c = a + b;
        require(c >= a, "add: +");

        return c;
    }
    function add(uint a, uint b, string memory errorMessage) internal pure returns (uint) {
        uint c = a + b;
        require(c >= a, errorMessage);

        return c;
    }
    function sub(uint a, uint b) internal pure returns (uint) {
        return sub(a, b, "sub: -");
    }
    function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) {
        require(b <= a, errorMessage);
        uint c = a - b;

        return c;
    }
    function mul(uint a, uint b) internal pure returns (uint) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint c = a * b;
        require(c / a == b, "mul: *");

        return c;
    }
    function mul(uint a, uint b, string memory errorMessage) internal pure returns (uint) {
        if (a == 0) {
            return 0;
        }

        uint c = a * b;
        require(c / a == b, errorMessage);

        return c;
    }
    function div(uint a, uint b) internal pure returns (uint) {
        return div(a, b, "div: /");
    }
    function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) {
        require(b > 0, errorMessage);
        uint c = a / b;

        return c;
    }
}

File 3 of 4 : SafeERC20.sol
pragma solidity ^0.6.7;

import "./SafeMath.sol";
import "./Address.sol";

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}

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

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

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

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

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

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 4 of 4 : Address.sol
pragma solidity ^0.6.7;

library Address {
    function isContract(address account) internal view returns (bool) {
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != 0x0 && codehash != accountHash);
    }
    function toPayable(address account) internal pure returns (address payable) {
        return address(uint160(account));
    }
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

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

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lpBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardBalance","type":"uint256"}],"name":"FarmRetired","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deltaReward","type":"uint256"}],"name":"IndexUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRewardsFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRewardsFeeRate","type":"uint256"}],"name":"NewRewardsFeeRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldTreasury","type":"address"},{"indexed":true,"internalType":"address","name":"newTreasury","type":"address"}],"name":"NewTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"farmer","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IZapperForBoostedFarm","name":"zapper","type":"address"}],"name":"SetZapper","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"farmer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"farmer","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newReward","type":"uint256"}],"name":"UserRewardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"claimer","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"WhitelistRewardsClaimer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IRewardsHandlerForBoostedFarm","name":"handler","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"WhitelistRewardsHandler","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"farmer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualReceivedAmount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"DEPOSITOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GAUGE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SPIRIT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"farmer","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"claimer","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"blacklistRewardsClaimer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRewardsHandlerForBoostedFarm","name":"handler","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"blacklistRewardsHandler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"farmer","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositOnBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"farmer","type":"address"}],"name":"earnedCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"farmer","type":"address"}],"name":"earnedCurrentMinusFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRewardsHandlerForBoostedFarm","name":"rewardsHandler","type":"address"},{"internalType":"bytes32[]","name":"rewardsHandlerParams","type":"bytes32[]"}],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRewardsHandlerForBoostedFarm","name":"rewardsHandler","type":"address"},{"internalType":"bytes32[]","name":"rewardsHandlerParams","type":"bytes32[]"},{"internalType":"bytes32[]","name":"zapperParams","type":"bytes32[]"}],"name":"exitZapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBoostFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRewardsHandlerForBoostedFarm","name":"handler","type":"address"},{"internalType":"bytes32[]","name":"params","type":"bytes32[]"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"farmer","type":"address"},{"internalType":"contract IRewardsHandlerForBoostedFarm","name":"handler","type":"address"},{"internalType":"bytes32[]","name":"params","type":"bytes32[]"}],"name":"getRewardFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardsClaimersWhitelist","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardsHandlersWhitelist","outputs":[{"internalType":"contract IRewardsHandlerForBoostedFarm[]","name":"","type":"address[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"claimer","type":"address"}],"name":"isRewardsClaimerWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRewardsHandlerForBoostedFarm","name":"handler","type":"address"}],"name":"isRewardsHandlerWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"retireFarm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardDelta","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardsClaimersList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsClaimersWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRewardsHandlerForBoostedFarm","name":"","type":"address"}],"name":"rewardsHandlersWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRewardFeeRate","type":"uint256"}],"name":"setRewardFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTreasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IZapperForBoostedFarm","name":"_zapper","type":"address"}],"name":"setZapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"claimer","type":"address"}],"name":"whitelistRewardsClaimer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRewardsHandlerForBoostedFarm","name":"handler","type":"address"}],"name":"whitelistRewardsHandler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"params","type":"bytes32[]"}],"name":"withdrawAllZapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"params","type":"bytes32[]"}],"name":"withdrawZapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"zapper","outputs":[{"internalType":"contract IZapperForBoostedFarm","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102bb5760003560e01c806382bfefc811610182578063a8b3728a116100e9578063de5f6268116100a2578063f0f442601161007c578063f0f4426014610b46578063f597813714610b6c578063f5de2d1f14610b92578063f800f83014610b9a576102bb565b8063de5f626814610b2e578063df136d6514610b36578063e9483ac014610b3e576102bb565b8063a8b3728a14610a7a578063aa6697ef14610a82578063b6b55f2514610aa8578063bd51ea2a14610ac5578063c6116df114610aeb578063c73f9e8014610b08576102bb565b806393a9076b1161013b57806393a9076b146108385780639cf17a42146108f25780639e462de414610918578063a7a21712146109b9578063a7c5c6e5146109c1578063a7fa806b14610a72576102bb565b806382bfefc8146107c657806383162aa8146107ce578063853828b6146107d65780638788f0b2146107de5780638b8763471461080a5780638da5cb5b14610830576102bb565b80632eb38ae01161022657806344bc253a116101df57806344bc253a1461064d57806355021e9a1461065557806361d027b31461078857806370a0823114610790578063750142e6146107b65780637651b1e6146107be576102bb565b80632eb38ae0146104ff5780632fdbd157146105075780633182add41461053357806334c5cdcb146105e45780633de0a9631461060a5780634243517514610627576102bb565b80631c0a026d116102785780631c0a026d146103de5780631e711b1614610486578063258cd1881461048e57806327282ecf146104b457806327a6e7a0146104bc5780632e1a7d4d146104e2576102bb565b806306c85884146102c05780630700037d1461031857806313af403514610350578063162790551461037857806316ad25a5146103b257806318160ddd146103d6575b600080fd5b6102c8610bc6565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103045781810151838201526020016102ec565b505050509050019250505060405180910390f35b61033e6004803603602081101561032e57600080fd5b50356001600160a01b0316610c29565b60408051918252519081900360200190f35b6103766004803603602081101561036657600080fd5b50356001600160a01b0316610c3b565b005b61039e6004803603602081101561038e57600080fd5b50356001600160a01b0316610d71565b604080519115158252519081900360200190f35b6103ba610d81565b604080516001600160a01b039092168252519081900360200190f35b61033e610d93565b610376600480360360408110156103f457600080fd5b81359190810190604081016020820135600160201b81111561041557600080fd5b82018360208201111561042757600080fd5b803590602001918460208302840111600160201b8311171561044857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610d99945050505050565b610376610daa565b61033e600480360360208110156104a457600080fd5b50356001600160a01b031661119e565b6102c86111e6565b61039e600480360360208110156104d257600080fd5b50356001600160a01b0316611246565b610376600480360360208110156104f857600080fd5b503561125b565b61039e61126a565b6103766004803603604081101561051d57600080fd5b506001600160a01b038135169060200135611273565b6103766004803603604081101561054957600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561057357600080fd5b82018360208201111561058557600080fd5b803590602001918460208302840111600160201b831117156105a657600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061127e945050505050565b61039e600480360360208110156105fa57600080fd5b50356001600160a01b0316611289565b6103ba6004803603602081101561062057600080fd5b50356112a7565b6103766004803603602081101561063d57600080fd5b50356001600160a01b03166112ce565b61033e61136e565b6103766004803603606081101561066b57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561069557600080fd5b8201836020820111156106a757600080fd5b803590602001918460208302840111600160201b831117156106c857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561071757600080fd5b82018360208201111561072957600080fd5b803590602001918460208302840111600160201b8311171561074a57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506114cf945050505050565b6103ba6114e7565b61033e600480360360208110156107a657600080fd5b50356001600160a01b03166114f6565b61033e611511565b6103ba611517565b6103ba61153b565b61033e61155f565b610376611640565b610376600480360360408110156107f457600080fd5b506001600160a01b038135169060200135611663565b61033e6004803603602081101561082057600080fd5b50356001600160a01b0316611899565b6103ba6118ab565b6103766004803603606081101561084e57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b81111561088157600080fd5b82018360208201111561089357600080fd5b803590602001918460208302840111600160201b831117156108b457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506118ba945050505050565b61039e6004803603602081101561090857600080fd5b50356001600160a01b031661191b565b6103766004803603602081101561092e57600080fd5b810190602081018135600160201b81111561094857600080fd5b82018360208201111561095a57600080fd5b803590602001918460208302840111600160201b8311171561097b57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611930945050505050565b6103ba61194d565b610376600480360360408110156109d757600080fd5b6001600160a01b038235169190810190604081016020820135600160201b811115610a0157600080fd5b820183602082011115610a1357600080fd5b803590602001918460208302840111600160201b83111715610a3457600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061195c945050505050565b6103ba61196e565b61033e611986565b61033e60048036036020811015610a9857600080fd5b50356001600160a01b03166119d5565b61037660048036036020811015610abe57600080fd5b5035611a55565b61037660048036036020811015610adb57600080fd5b50356001600160a01b0316611a60565b61037660048036036020811015610b0157600080fd5b5035611ba7565b61037660048036036020811015610b1e57600080fd5b50356001600160a01b0316611ce7565b610376611e2e565b61033e611ed3565b61033e611ed9565b61037660048036036020811015610b5c57600080fd5b50356001600160a01b0316611edf565b61039e60048036036020811015610b8257600080fd5b50356001600160a01b0316611fd8565b61033e611ff6565b61037660048036036040811015610bb057600080fd5b506001600160a01b038135169060200135611ffc565b6060600f805480602002602001604051908101604052809291908181526020018280548015610c1e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c00575b505050505090505b90565b60066020526000908152604090205481565b6001546001600160a01b03163314610c87576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6001600160a01b038116610ccd576040805162461bcd60e51b815260206004820152600860248201526737379037bbb732b960c11b604482015290519081900360640190fd5b6001546001600160a01b0382811691161415610d1d576040805162461bcd60e51b815260206004820152600a60248201526939b0b6b29037bbb732b960b11b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236490600090a35050565b63ffffffff813b1615155b919050565b600080516020613c2783398151915281565b60095481565b610da63383600184612232565b5050565b6001546001600160a01b03163314610df6576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b60026000541415610e3c576040805162461bcd60e51b815260206004820152601f6024820152600080516020613c47833981519152604482015290519081900360640190fd5b60026000556004805460ff19166001178155604080516370a0823160e01b8152600080516020613c2783398151915292810192909252516001600160a01b037f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d516916370a08231916024808301926020929190829003018186803b158015610ec357600080fd5b505afa158015610ed7573d6000803e3d6000fd5b505050506040513d6020811015610eed57600080fd5b505115610faa57604080516301395c5960e31b81526001600160a01b037f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d5811660048301527f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a751660248201529051600080516020613c27833981519152916309cae2c891604480830192600092919082900301818387803b158015610f9157600080fd5b505af1158015610fa5573d6000803e3d6000fd5b505050505b60007f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a756001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561101957600080fd5b505afa15801561102d573d6000803e3d6000fd5b505050506040513d602081101561104357600080fd5b50516040805163354dd5c360e01b81527f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b031660048201529051919250600080516020613c278339815191529163354dd5c39160248082019260009290919082900301818387803b1580156110be57600080fd5b505af11580156110d2573d6000803e3d6000fd5b5050604080516370a0823160e01b8152306004820152905160009350735cc61a78f164885776aa610fb0fe1257df78e59b92506370a0823191602480820192602092909190829003018186803b15801561112b57600080fd5b505afa15801561113f573d6000803e3d6000fd5b505050506040513d602081101561115557600080fd5b5051604080518481526020810183905281519293507f5e33968e099deace5af7ff74932b48ff861b93b67b121fa0200c5ae6da4854ef929081900390910190a150506001600055565b6000806111aa836119d5565b905060006111cf6127106111c960035485612b0790919063ffffffff16565b90612b68565b905060006111dd8383612b93565b95945050505050565b6060600d805480602002602001604051908101604052809291908181526020018280548015610c1e576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610c00575050505050905090565b600c6020526000908152604090205460ff1681565b6060610da63383600084612232565b60045460ff1681565b610da6823383612bbe565b610da63383836130e5565b6001600160a01b03166000908152600c602052604090205460ff1690565b600d81815481106112b457fe5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461131a576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b601080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fe1e732dbbc8e3554486963da7b8477bf9f5066e9172819ed0397db8535ac527e9181900360200190a150565b6000807f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b0316630700037d600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156113ec57600080fd5b505afa158015611400573d6000803e3d6000fd5b505050506040513d602081101561141657600080fd5b5051604080516246613160e11b8152600080516020613c27833981519152600482015290519192506000916001600160a01b037f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d51691628cc262916024808301926020929190829003018186803b15801561149057600080fd5b505afa1580156114a4573d6000803e3d6000fd5b505050506040513d60208110156114ba57600080fd5b505190506114c88183612b93565b9250505090565b6114d881611930565b6114e2838361127e565b505050565b6002546001600160a01b031681565b6001600160a01b031660009081526007602052604090205490565b600a5481565b7f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d581565b7f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a7581565b60008061157d60646111c96028600954612b0790919063ffffffff16565b905060007f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b03166363fb415b600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156115fc57600080fd5b505afa158015611610573d6000803e3d6000fd5b505050506040513d602081101561162657600080fd5b505190506114c8826111c983670de0b6b3a7640000612b07565b336000818152600760205260408120546060926116609290919084612232565b50565b6001546001600160a01b031633146116af576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6001600160a01b0382166000908152600c602052604090205460ff161515600114611721576040805162461bcd60e51b815260206004820181905260248201527f72657761726473436c61696d65722069736e27742077686974656c6973746564604482015290519081900360640190fd5b6001600160a01b0382166000908152600c60205260409020805460ff19169055600d54808210801561177c5750826001600160a01b0316600d838154811061176557fe5b6000918252602090912001546001600160a01b0316145b6117bb576040805162461bcd60e51b815260206004820152600b60248201526a0aee4dedcce40d2dcc8caf60ab1b604482015290519081900360640190fd5b600d60018203815481106117cb57fe5b600091825260209091200154600d80546001600160a01b0390921691849081106117f157fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600d80548061182a57fe5b60008281526020808220830160001990810180546001600160a01b0319169055909201909255604080516001600160a01b03871681529182019290925281517f3d01ac0069fd477e43463a3f90651df97bf41586640912a772b001e60639d9ea929181900390910190a1505050565b60056020526000908152604090205481565b6001546001600160a01b031681565b6118c333611289565b1515600114611910576040805162461bcd60e51b815260206004820152601460248201527310bbb434ba32b634b9ba32b21031b630b4b6b2b960611b604482015290519081900360640190fd5b6114e28383836130e5565b600e6020526000908152604090205460ff1681565b336000818152600760205260409020546116609190600184612232565b6010546001600160a01b031681565b611964611640565b610da6828261127e565b735cc61a78f164885776aa610fb0fe1257df78e59b81565b60008061199161136e565b6009549091508015806119a2575081155b156119b35760085492505050610c26565b6114c86119cc826111c985670de0b6b3a7640000612b07565b600854906136c0565b6000806119e0611986565b6001600160a01b038416600090815260066020908152604080832054600590925290912054919250611a4e91611a4890670de0b6b3a7640000906111c990611a29908790612b93565b6001600160a01b03891660009081526007602052604090205490612b07565b906136c0565b9392505050565b611660333383612bbe565b6001546001600160a01b03163314611aac576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6001600160a01b0381166000908152600e602052604090205460ff1615611b045760405162461bcd60e51b8152600401808060200182810382526022815260200180613c676022913960400191505060405180910390fd5b6001600160a01b0381166000818152600e60209081526040808320805460ff19166001908117909155600f8054808301825594527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac80290930180546001600160a01b0319168517905580519384529083019190915280517fce52ea0e1c53eeec7b3d553517877c8d0d842a565fb54387b4225dc81bf123d39281900390910190a150565b6001546001600160a01b03163314611bf3576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6109c4811115611c4a576040805162461bcd60e51b815260206004820152601960248201527f6e65775265776172644665655261746520746f6f206869676800000000000000604482015290519081900360640190fd5b8015611ca0576002546001600160a01b0316611ca0576040805162461bcd60e51b815260206004820152601060248201526f1d1c99585cdd5c9e481b9bdd081cd95d60821b604482015290519081900360640190fd5b6003805490829055604080518281526020810184905281517f423eee14d00e23a4c89848d88217777c0b6d9f8d7a64b3599dfe2421e79cc3a9929181900390910190a15050565b6001546001600160a01b03163314611d33576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6001600160a01b0381166000908152600c602052604090205460ff1615611d8b5760405162461bcd60e51b8152600401808060200182810382526023815260200180613c896023913960400191505060405180910390fd5b6001600160a01b0381166000818152600c60209081526040808320805460ff19166001908117909155600d8054808301825594527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb590930180546001600160a01b0319168517905580519384529083019190915280517f3d01ac0069fd477e43463a3f90651df97bf41586640912a772b001e60639d9ea9281900390910190a150565b611ed133337f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a756001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015611ea057600080fd5b505afa158015611eb4573d6000803e3d6000fd5b505050506040513d6020811015611eca57600080fd5b5051612bbe565b565b60085481565b600b5481565b6001546001600160a01b03163314611f2b576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6001600160a01b038116611f845760035415611f84576040805162461bcd60e51b81526020600482015260136024820152720726577617264206665652072617465203e203606c1b604482015290519081900360640190fd5b600280546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f567657fa3f286518b318f4a29870674f433f622fdfc819691acb13105b22822590600090a35050565b6001600160a01b03166000908152600e602052604090205460ff1690565b60035481565b6001546001600160a01b03163314612048576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6001600160a01b0382166000908152600e602052604090205460ff1615156001146120ba576040805162461bcd60e51b815260206004820181905260248201527f7265776172647348616e646c65722069736e27742077686974656c6973746564604482015290519081900360640190fd5b6001600160a01b0382166000908152600e60205260409020805460ff19169055600f5480821080156121155750826001600160a01b0316600f83815481106120fe57fe5b6000918252602090912001546001600160a01b0316145b612154576040805162461bcd60e51b815260206004820152600b60248201526a0aee4dedcce40d2dcc8caf60ab1b604482015290519081900360640190fd5b600f600182038154811061216457fe5b600091825260209091200154600f80546001600160a01b03909216918490811061218a57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600f8054806121c357fe5b60008281526020808220830160001990810180546001600160a01b0319169055909201909255604080516001600160a01b03871681529182019290925281517fce52ea0e1c53eeec7b3d553517877c8d0d842a565fb54387b4225dc81bf123d3929181900390910190a1505050565b60026000541415612278576040805162461bcd60e51b815260206004820152601f6024820152600080516020613c47833981519152604482015290519081900360640190fd5b6002600055826122c3576040805162461bcd60e51b8152602060048201526011602482015270043616e6e6f74207769746864726177203607c1b604482015290519081900360640190fd5b60045460009060ff166128845760007f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a756001600160a01b03166370a08231600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561234d57600080fd5b505afa158015612361573d6000803e3d6000fd5b505050506040513d602081101561237757600080fd5b5051604080516370a0823160e01b8152600080516020613c27833981519152600482015290519192506000916001600160a01b037f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d516916370a08231916024808301926020929190829003018186803b1580156123f357600080fd5b505afa158015612407573d6000803e3d6000fd5b505050506040513d602081101561241d57600080fd5b505160408051630700037d60e01b8152600080516020613c27833981519152600482015290519192506000916001600160a01b037f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d51691630700037d916024808301926020929190829003018186803b15801561249957600080fd5b505afa1580156124ad573d6000803e3d6000fd5b505050506040513d60208110156124c357600080fd5b505160408051636ce5768960e11b81526001600160a01b037f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d5811660048301527f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a75166024820152604481018a90529051919250600080516020613c278339815191529163d9caed129160648082019260009290919082900301818387803b15801561256d57600080fd5b505af1158015612581573d6000803e3d6000fd5b5050505060007f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b03166370a08231600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561260257600080fd5b505afa158015612616573d6000803e3d6000fd5b505050506040513d602081101561262c57600080fd5b50519050828110612678576040805162461bcd60e51b81526020600482015260116024820152703737ba3434b733903bb4ba34323930bbb760791b604482015290519081900360640190fd5b6126828382612b93565b975060007f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b0316630700037d600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561270157600080fd5b505afa158015612715573d6000803e3d6000fd5b505050506040513d602081101561272b57600080fd5b505190506127428a61273d8386612b93565b613703565b6001600160a01b038a16600090815260076020526040902054612765908a612b93565b6001600160a01b038b1660009081526007602052604090205560095461278b908a612b93565b600955604080516370a0823160e01b815230600482015290516000916001600160a01b037f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a7516916370a0823191602480820192602092909190829003018186803b1580156127f857600080fd5b505afa15801561280c573d6000803e3d6000fd5b505050506040513d602081101561282257600080fd5b5051905085811161286d576040805162461bcd60e51b815260206004820152601060248201526f1b9bdd1a1a5b99c81c9958d95a5d995960821b604482015290519081900360640190fd5b6128778187612b93565b9650505050505050612914565b61288f856000613703565b6001600160a01b0385166000908152600760205260409020548481146128e65760405162461bcd60e51b8152600401808060200182810382526023815260200180613cd66023913960400191505060405180910390fd5b6001600160a01b03861660009081526007602052604081205560095461290c9086612b93565b600955508390505b8215612a84576010546001600160a01b0316612961576040805162461bcd60e51b815260206004820152600760248201526610bd30b83832b960c91b604482015290519081900360640190fd5b60105461299b906001600160a01b037f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a7581169116836137a0565b6010546040516308cfb7a560e31b81527f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a756001600160a01b0381811660048401908152602484018690528982166044850152608060648501908152875160848601528751929095169463467dbd289487938c938a939092909160a4909101906020808601910280838360005b83811015612a3f578181015183820152602001612a27565b5050505090500195505050505050600060405180830381600087803b158015612a6757600080fd5b505af1158015612a7b573d6000803e3d6000fd5b50505050612ab8565b612ab86001600160a01b037f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a751686836137a0565b604080518581526020810183905281516001600160a01b038816927f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6928290030190a250506001600055505050565b600082612b1657506000612b62565b82820282848281612b2357fe5b0414612b5f576040805162461bcd60e51b815260206004820152600660248201526536bab61d101560d11b604482015290519081900360640190fd5b90505b92915050565b6000612b5f8383604051806040016040528060068152602001656469763a202f60d01b8152506137f2565b6000612b5f8383604051806040016040528060068152602001657375623a202d60d01b815250613894565b60026000541415612c04576040805162461bcd60e51b815260206004820152601f6024820152600080516020613c47833981519152604482015290519081900360640190fd5b600260005560045460ff1615612c4b576040805162461bcd60e51b81526020600482015260076024820152661c995d1a5c995960ca1b604482015290519081900360640190fd5b60007f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b03166370a08231600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612cc857600080fd5b505afa158015612cdc573d6000803e3d6000fd5b505050506040513d6020811015612cf257600080fd5b505160408051630700037d60e01b8152600080516020613c27833981519152600482015290519192506000916001600160a01b037f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d51691630700037d916024808301926020929190829003018186803b158015612d6e57600080fd5b505afa158015612d82573d6000803e3d6000fd5b505050506040513d6020811015612d9857600080fd5b50519050612ddf6001600160a01b037f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a751685600080516020613c27833981519152866138ee565b60408051631f2c13e160e31b81526001600160a01b037f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d5811660048301527f0000000000000000000000005a6880d3e9d715bef5848c9749cea5f23a982a751660248201529051600080516020613c278339815191529163f9609f0891604480830192600092919082900301818387803b158015612e7c57600080fd5b505af1158015612e90573d6000803e3d6000fd5b5050505060007f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b03166370a08231600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612f1157600080fd5b505afa158015612f25573d6000803e3d6000fd5b505050506040513d6020811015612f3b57600080fd5b50519050828111612f87576040805162461bcd60e51b81526020600482015260116024820152701b9bdd1a1a5b99c819195c1bdcda5d1959607a1b604482015290519081900360640190fd5b612f918184612b93565b935060007f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b0316630700037d600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561301057600080fd5b505afa158015613024573d6000803e3d6000fd5b505050506040513d602081101561303a57600080fd5b5051905061304c8761273d8386612b93565b6001600160a01b03871660009081526007602052604090205461306f90866136c0565b6001600160a01b03881660009081526007602052604090205560095461309590866136c0565b6009556040805186815290516001600160a01b038916917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a2505060016000555050505050565b6002600054141561312b576040805162461bcd60e51b815260206004820152601f6024820152600080516020613c47833981519152604482015290519081900360640190fd5b6002600090815560045460ff1661339c5760007f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b0316630700037d600080516020613c278339815191526040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156131b957600080fd5b505afa1580156131cd573d6000803e3d6000fd5b505050506040513d60208110156131e357600080fd5b5051604080516370a0823160e01b81523060048201529051919250600091735cc61a78f164885776aa610fb0fe1257df78e59b916370a08231916024808301926020929190829003018186803b15801561323c57600080fd5b505afa158015613250573d6000803e3d6000fd5b505050506040513d602081101561326657600080fd5b50516040805163354dd5c360e01b81527f000000000000000000000000ca05dc1ab089173f8dedd89f39dc48dde36479d56001600160a01b031660048201529051919250600080516020613c278339815191529163354dd5c39160248082019260009290919082900301818387803b1580156132e157600080fd5b505af11580156132f5573d6000803e3d6000fd5b5050604080516370a0823160e01b81523060048201529051735cc61a78f164885776aa610fb0fe1257df78e59b93506370a0823192506024808301926020929190829003018186803b15801561334a57600080fd5b505afa15801561335e573d6000803e3d6000fd5b505050506040513d602081101561337457600080fd5b5051925060006133848483612b93565b90506133948761273d8386612b93565b505050613427565b6133a7846000613703565b604080516370a0823160e01b81523060048201529051735cc61a78f164885776aa610fb0fe1257df78e59b916370a08231916024808301926020929190829003018186803b1580156133f857600080fd5b505afa15801561340c573d6000803e3d6000fd5b505050506040513d602081101561342257600080fd5b505190505b6001600160a01b03841660009081526006602052604090205480156136b45761344f84611fd8565b15156001146134a5576040805162461bcd60e51b815260206004820152601e60248201527f5265776172647348616e646c6572206e6f742077686974656c69737465640000604482015290519081900360640190fd5b808210156134fa576040805162461bcd60e51b815260206004820152601d60248201527f5350495249542062616c616e6365206e6f742073756666696369656e74000000604482015290519081900360640190fd5b6001600160a01b038516600090815260066020526040812055600b5461352090826136c0565b600b5560035460009061353c90612710906111c9908590612b07565b9050600061354a8383612b93565b60025490915061357990735cc61a78f164885776aa610fb0fe1257df78e59b906001600160a01b0316846137a0565b613598735cc61a78f164885776aa610fb0fe1257df78e59b87836137a0565b856001600160a01b03166365d4195f735cc61a78f164885776aa610fb0fe1257df78e59b8333896040518563ffffffff1660e01b815260040180856001600160a01b03168152602001848152602001836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561363257818101518382015260200161361a565b5050505090500195505050505050600060405180830381600087803b15801561365a57600080fd5b505af115801561366e573d6000803e3d6000fd5b50506040805184815290516001600160a01b038b1693507fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048692509081900360200190a250505b50506001600055505050565b600082820183811015612b5f576040805162461bcd60e51b81526020600482015260066024820152656164643a202b60d01b604482015290519081900360640190fd5b600061370e8261394e565b6001600160a01b03841660009081526006602052604081205491925061373485846139ec565b6001600160a01b038616600081815260066020908152604080832085905560058252918290208790558151868152908101849052815193945091927fa011654d7e92938f3697b7b2bda08ac26f8694d916e1d8454a2e845a1f90502a9281900390910190a25050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526114e2908490613a32565b6000818361387e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561384357818101518382015260200161382b565b50505050905090810190601f1680156138705780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161388a57fe5b0495945050505050565b600081848411156138e65760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561384357818101518382015260200161382b565b505050900390565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052613948908590613a32565b50505050565b60095460009080158061395f575082155b1561396e575050600854610d7c565b600854600061398c6119cc846111c988670de0b6b3a7640000612b07565b600a5490915061399c90866136c0565b600a556008819055604080518381526020810183905280820187905290517f413e73e2d3f6a398a619d92d5897e51b940b13a203152d54d3b3985393bd133f9181900360600190a1949350505050565b6001600160a01b0382166000908152600660209081526040808320546005909252822054612b5f9190611a4890670de0b6b3a7640000906111c990611a29908890612b93565b613a44826001600160a01b0316613bea565b613a95576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310613ad35780518252601f199092019160209182019101613ab4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613b35576040519150601f19603f3d011682016040523d82523d6000602084013e613b3a565b606091505b509150915081613b91576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b80511561394857808060200190516020811015613bad57600080fd5b50516139485760405162461bcd60e51b815260040180806020018281038252602a815260200180613cac602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708115801590613c1e5750808214155b94935050505056fe000000000000000000000000099ea71e5b0c7e350dee2f5ea397ab4e7c4895805265656e7472616e637947756172643a207265656e7472616e742063616c6c007265776172647348616e646c657220616c72656164792077686974656c697374656472657761726473436c6161696d657220616c72656164792077686974656c69737465645361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656443616e2774207061727469616c207769746864726177207768656e2072657469726564a26469706673582212201ec1f84dc1ccb49474cf200202041a99f3bebf640dbb8b7a588af1103938251364736f6c634300060c0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ 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.