Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xE4D89e8267D2e8f03f751fa807B3bBdB36729F9A
Balance 0 ETH
Nonce 1
Code Size 4112 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

4112 bytes
0x608060405234801561001057600080fd5b50600436106101215760003560e01c80637532ed2b116100ad578063c00007b011610071578063c00007b014610290578063c6def076146102b6578063c745ccbf146102be578063cc956f3f1461032e578063dc4c90d31461034b57610121565b80637532ed2b146102415780638da5cb5b14610249578063923c1d6114610251578063adc7ea3714610259578063b46b400d1461027657610121565b80633545c789116100f45780633545c7891461018f5780634a92b5fd146101b35780634b8843d5146101d95780635cfbfc6d1461020b5780636a4874a11461023957610121565b806313e7c9d8146101265780632663fcfc146101605780632e9e18541461016a5780632f2770db14610187575b600080fd5b61014c6004803603602081101561013c57600080fd5b50356001600160a01b0316610353565b604080519115158252519081900360200190f35b610168610368565b005b6101686004803603602081101561018057600080fd5b503561038c565b61016861044e565b6101976105cd565b604080516001600160a01b039092168252519081900360200190f35b610197600480360360208110156101c957600080fd5b50356001600160a01b03166105f1565b610168600480360360608110156101ef57600080fd5b506001600160a01b03813516906020810135906040013561060c565b6101686004803603604081101561022157600080fd5b506001600160a01b0381351690602001351515610762565b610197610826565b61019761083e565b610197610856565b61019761087a565b6101686004803603602081101561026f57600080fd5b5035610892565b61027e610933565b60408051918252519081900360200190f35b610168600480360360208110156102a657600080fd5b50356001600160a01b0316610939565b6101976109c5565b610168600480360360208110156102d457600080fd5b8101906020810181356401000000008111156102ef57600080fd5b82018360208201111561030157600080fd5b8035906020019184602083028401116401000000008311171561032357600080fd5b5090925090506109dd565b61014c6004803603602081101561034457600080fd5b5035610ac9565b610197610d6f565b60006020819052908152604090205460ff1681565b3360009081526001602052604090205461038a906001600160a01b0316610d93565b565b60008073f403c135812408bfbe8713b5a23a04b3d48aae316001600160a01b0316631526fe27846040518263ffffffff1660e01b81526004018082815260200191505060c06040518083038186803b1580156103e757600080fd5b505afa1580156103fb573d6000803e3d6000fd5b505050506040513d60c081101561041157600080fd5b5060608101516080909101516001600160a01b03908116600090815260016020526040902080546001600160a01b03191691909216179055505050565b7f000000000000000000000000a3c5a1e09150b75ff251c1a7815a07182c3de2fb6001600160a01b031633146104b4576040805162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b604482015290519081900360640190fd5b604080516370a0823160e01b8152306004820152905173d533a949740bb3306d119cc777fa900ba034cd529163a9059cbb91731389388d01708118b497f59521f6943be2541bb79184916370a0823191602480820192602092909190829003018186803b15801561052457600080fd5b505afa158015610538573d6000803e3d6000fd5b505050506040513d602081101561054e57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b15801561059f57600080fd5b505af11580156105b3573d6000803e3d6000fd5b505050506040513d60208110156105c957600080fd5b5050565b7f000000000000000000000000723f9aa67fdd9b0e375ef8553eb2afc28ecd4a9681565b6001602052600090815260409020546001600160a01b031681565b336001600160a01b037f0000000000000000000000006d3a388e310aaa498430d1fe541d6d64ddb423de1614610674576040805162461bcd60e51b815260206004820152600860248201526721706f6f6c4d6e6760c01b604482015290519081900360640190fd5b61067d8161038c565b600073256e1bba846611c37cf89844a02435e6c098b86d6001600160a01b03166304e020dd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106cc57600080fd5b505afa1580156106e0573d6000803e3d6000fd5b505050506040513d60208110156106f657600080fd5b5051604080516398881bc960e01b81526004810185905290519192506001600160a01b038316916398881bc99160248082019260009290919082900301818387803b15801561074457600080fd5b505af1158015610758573d6000803e3d6000fd5b5050505050505050565b7f000000000000000000000000a3c5a1e09150b75ff251c1a7815a07182c3de2fb6001600160a01b031633146107c8576040805162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b604482015290519081900360640190fd5b6001600160a01b03821660008181526020818152604091829020805460ff1916851515908117909155825190815291517fbadd5a134a60c76befc7e7d53706d47a82ac7037171f88c24a7f70faa2998ef19281900390910190a25050565b73d533a949740bb3306d119cc777fa900ba034cd5281565b73256e1bba846611c37cf89844a02435e6c098b86d81565b7f000000000000000000000000a3c5a1e09150b75ff251c1a7815a07182c3de2fb81565b734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b81565b7f000000000000000000000000a3c5a1e09150b75ff251c1a7815a07182c3de2fb6001600160a01b031633146108f8576040805162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b604482015290519081900360640190fd5b60028190556040805182815290517fb33211365ccf8563493d1b2ccf9a78aa626fb222777be9b474156c6fe18597f39181900360200190a150565b60025481565b336001600160a01b037f000000000000000000000000723f9aa67fdd9b0e375ef8553eb2afc28ecd4a96161461099e576040805162461bcd60e51b815260206004820152600560248201526421686f6f6b60d81b604482015290519081900360640190fd5b6001600160a01b038082166000908152600160205260409020546109c29116610d93565b50565b73f403c135812408bfbe8713b5a23a04b3d48aae3181565b8060005b81811015610ac35760008073f403c135812408bfbe8713b5a23a04b3d48aae31631526fe27878786818110610a1257fe5b905060200201356040518263ffffffff1660e01b81526004018082815260200191505060c06040518083038186803b158015610a4d57600080fd5b505afa158015610a61573d6000803e3d6000fd5b505050506040513d60c0811015610a7757600080fd5b5060608101516080909101516001600160a01b03908116600090815260016020819052604090912080546001600160a01b03191692909316919091179091559290920191506109e19050565b50505050565b3360009081526020819052604081205460ff1680610b0f57507f000000000000000000000000a3c5a1e09150b75ff251c1a7815a07182c3de2fb6001600160a01b031633145b610b46576040805162461bcd60e51b81526020600482015260036024820152620216f760ec1b604482015290519081900360640190fd5b604080516370a0823160e01b8152306004820152905160009173d533a949740bb3306d119cc777fa900ba034cd52916370a0823191602480820192602092909190829003018186803b158015610b9b57600080fd5b505afa158015610baf573d6000803e3d6000fd5b505050506040513d6020811015610bc557600080fd5b50516003805460ff191660011790556040805163cc956f3f60e01b815260048101869052905191925073f403c135812408bfbe8713b5a23a04b3d48aae319163cc956f3f916024808201926020929091908290030181600087803b158015610c2c57600080fd5b505af1158015610c40573d6000803e3d6000fd5b505050506040513d6020811015610c5657600080fd5b50506003805460ff19169055604080516370a0823160e01b8152306004820152905173d533a949740bb3306d119cc777fa900ba034cd529163a9059cbb913391859185916370a08231916024808301926020929190829003018186803b158015610cbf57600080fd5b505afa158015610cd3573d6000803e3d6000fd5b505050506040513d6020811015610ce957600080fd5b5051604080516001600160e01b031960e087901b1681526001600160a01b03909416600485015291900360248301525160448083019260209291908290030181600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b505050506040513d6020811015610d6457600080fd5b506001949350505050565b7f0000000000000000000000006d3a388e310aaa498430d1fe541d6d64ddb423de81565b6001600160a01b0381161580610dab575060035460ff165b15610db5576109c2565b600254816001600160a01b031663ebe2b12b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610df157600080fd5b505afa158015610e05573d6000803e3d6000fd5b505050506040513d6020811015610e1b57600080fd5b5051014210610e29576109c2565b6000816001600160a01b031663901a7d536040518163ffffffff1660e01b815260040160206040518083038186803b158015610e6457600080fd5b505afa158015610e78573d6000803e3d6000fd5b505050506040513d6020811015610e8e57600080fd5b5051604080516370a0823160e01b815273f403c135812408bfbe8713b5a23a04b3d48aae316004820152905191925060009173d533a949740bb3306d119cc777fa900ba034cd52916370a08231916024808301926020929190829003018186803b158015610efb57600080fd5b505afa158015610f0f573d6000803e3d6000fd5b505050506040513d6020811015610f2557600080fd5b5051905060028202811115610f3b5750506109c2565b6040805163a9059cbb60e01b815273f403c135812408bfbe8713b5a23a04b3d48aae31600482015260016024820152905173d533a949740bb3306d119cc777fa900ba034cd529163a9059cbb9160448083019260209291908290030181600087803b158015610fa957600080fd5b505af1158015610fbd573d6000803e3d6000fd5b505050506040513d6020811015610fd357600080fd5b505050505056fea264697066735822122009b0d975827601799a5e1845f97a07cc85caf0055a5053a626211681b47576fc64736f6c634300060c0033

Verified Source Code Partial Match

Compiler: v0.6.12+commit.27d51765 EVM: istanbul Optimization: Yes (200 runs)
PoolHarvestHook.sol 147 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;

import "./interfaces/IBooster.sol";
import "./interfaces/IBoosterAdmin.sol";
import "./interfaces/IBoosterRewardManager.sol";
import "./interfaces/IRewards.sol";
import "./interfaces/IRewardHook.sol";
import "./interfaces/IPoolAddHook.sol";
import "./interfaces/IRewardHookExtended.sol";
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';

/*
    A Hook that forces harvests to happen once period finish is complete
*/
contract PoolHarvestHook is IRewardHook, IPoolAddHook{

    address public constant booster = address(0xF403C135812408BFbE8713b5A23a04b3D48AAE31);
    address public constant boosterOwner = address(0x256e1bbA846611C37CF89844a02435E6C098b86D);
    address public constant cvx = address(0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B);
    address public constant crv = address(0xD533a949740bb3306d119CC777fa900bA034cd52);
    address public immutable poolManager;
    address public immutable poolHook;
    address public immutable owner;

    mapping(address => bool) public operators;
    mapping(address => address) public stashMap;
    uint256 public timebuffer;

    bool private isOperator;

    event AddOperator(address indexed _op, bool _valid);
    event ChangeBuffer(uint256 _buffer);

    constructor(address _owner, address _poolManager, address _poolHook) public {
        owner = _owner;
        poolManager = _poolManager;
        poolHook = _poolHook;
        operators[msg.sender] = true;
        timebuffer = 1 hours;
        emit AddOperator(msg.sender, true);
    }

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

    modifier onlyOperator() {
        require(operators[msg.sender] || owner == msg.sender, "!op");
        _;
    }

    //set operator
    function setOperators(address _op, bool _valid) external onlyOwner{
        operators[_op] = _valid;
        emit AddOperator(_op, _valid);
    }

    //set time buffer
    function setBuffer(uint256 _seconds) external onlyOwner{
        timebuffer = _seconds;
        emit ChangeBuffer(_seconds);
    }

    //disable hook by removing all crv on this address
    function disable() external onlyOwner{
        IERC20(crv).transfer(address(0x1389388d01708118b497f59521f6943Be2541bb7), IERC20(crv).balanceOf(address(this)));
    }

    function setStashMap(uint256 _pid) public{
        //get stash address and crvrewards address
        (,,,address crvRewards, address stash,) = IBooster(booster).poolInfo(_pid);

        //add mapping stash -> rewards
        stashMap[stash] = crvRewards;
    }

    function setMultiStashMap(uint256[] calldata _pids) public{
        uint256 l = _pids.length;
        for(uint256 p = 0; p < l; ++p){
            //get stash address and crvrewards address
            (,,,address crvRewards, address stash,) = IBooster(booster).poolInfo(_pids[p]);

            //add mapping stash -> rewards
            stashMap[stash] = crvRewards;
        }
    }

    function poolAdded(address /*_gauge*/, uint256 /*_stashVersion*/, uint256 _poolId) external override{
        //require called from pool manager
        require(msg.sender == poolManager, "!poolMng");

        // set stash map
        setStashMap(_poolId);

        // tell booster owner reward manager to initialize pool (add cvx reward and stash hook)
        address rewardmanager = IBoosterAdmin(boosterOwner).stashRewardManager();
        IBoosterRewardManager(rewardmanager).initializePool(_poolId);
    }

    function earmarkRewards(uint256 _pid) external onlyOperator returns(bool){
        uint256 crvb = IERC20(crv).balanceOf(address(this));
        isOperator = true;
        IBooster(booster).earmarkRewards(_pid);
        isOperator = false;
        IERC20(crv).transfer(msg.sender, IERC20(crv).balanceOf(address(this))-crvb);
        return true;
    }

    //hook from stash
    function onRewardClaim() external override{
        //msg.sender is a proper stash if in the stash map
        _onHarvest(stashMap[msg.sender]);
    }

    //hook from PoolRewardHook
    function getReward(address _stash) public{
        require(msg.sender == poolHook, "!hook");
        //can trust the stash address given by PoolRewardHook
        _onHarvest(stashMap[_stash]);
    }

    function _onHarvest(address _crvRewards) internal{

        //if not set or operator, return
        if(_crvRewards == address(0) || isOperator){
            return;
        }

        //check period finish on crvrewards
        if (block.timestamp >= IRewards(_crvRewards).periodFinish()+timebuffer) {
            return;
        }

        // //check if there is more crv rewards waiting to be claimed than the current reward epoch
        uint256 currentRewards = IRewards(_crvRewards).currentRewards();
        uint256 balanceOnBooster = IERC20(crv).balanceOf(booster);
        if(balanceOnBooster > currentRewards * 2){
            return;
        }

        //if fail, send 1 wei of crv to booster
        IERC20(crv).transfer(booster, 1);
    }

}
IBooster.sol 19 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;

interface IBooster {
    function owner() external view returns(address);
    function feeToken() external view returns(address);
    function feeDistro() external view returns(address);
    function lockFees() external view returns(address);
    function stakerRewards() external view returns(address);
    function lockRewards() external view returns(address);
    function setVoteDelegate(address _voteDelegate) external;
    function vote(uint256 _voteId, address _votingAddress, bool _support) external returns(bool);
    function voteGaugeWeight(address[] calldata _gauge, uint256[] calldata _weight ) external returns(bool);
    function poolInfo(uint256 _pid) external view returns(address _lptoken, address _token, address _gauge, address _crvRewards, address _stash, bool _shutdown);
    function earmarkRewards(uint256 _pid) external returns(bool);
    function earmarkFees() external returns(bool);
    function isShutdown() external view returns(bool);
    function poolLength() external view returns (uint256);
}
IRewards.sol 21 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;

interface IRewards{
    function stake(address, uint256) external;
    function stakeFor(address, uint256) external;
    function withdraw(address, uint256) external;
    function setWeight(address _pool, uint256 _amount) external returns(bool);
    function setWeights(address[] calldata _account, uint256[] calldata _amount) external;
    function setDistributor(address _distro, bool _valid) external;
    function getReward(address) external;
    function queueNewRewards(uint256) external;
    function addExtraReward(address) external;
    function setRewardHook(address) external;
    function user_checkpoint(address _account) external returns(bool);
    function periodFinish() external view returns(uint256);
    function currentRewards() external view returns(uint256);
    function rewardToken() external view returns(address);
    function rewardMap(address) external view returns(bool);
    function earned(address account) external view returns (uint256);
}
IRewardHook.sol 7 lines
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

interface IRewardHook {
    function onRewardClaim() external;
}
IPoolAddHook.sol 7 lines
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

interface IPoolAddHook {
    function poolAdded(address _gauge, uint256 _stashVersion, uint256 _poolId) external;
}
IBoosterAdmin.sol 12 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;

interface IBoosterAdmin {
    function owner() external view returns(address);
    function stashRewardManager() external view returns(address);
    function setStashRewardManager(address _mng) external;
    function acceptStashRewardManager() external;
    function setStashExtraReward(uint256 _pid, address _token) external;
    function setStashRewardHook(uint256 _pid, address _hook) external;
    function setStashTokenIsValid(address stashToken, bool isValid) external;
}
IRewardHookExtended.sol 10 lines
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

interface IRewardHookExtended {
    function onRewardClaim() external;
    function poolRewardLength(address _pool) external view returns(uint256);
    function poolRewardList(address _pool, uint256 _index) external view returns(address _rewardContract);
    function addPoolReward(address _pool, address _rewardContract) external;
}
IERC20.sol 77 lines
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

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

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}
IBoosterRewardManager.sol 12 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;

interface IBoosterRewardManager {
    function defaultHook() external view returns(address);
    function initializePool(uint256 _pid) external;
    function setStashRewardManager(address _mng) external;
    function setStashExtraReward(uint256 _pid, address _token) external;
    function setStashRewardHook(uint256 _pid, address _hook) external;
    function setMultiStashRewardHook(uint256[] calldata _pids, address _hook) external;
    function setStashTokenIsValid(address stashToken, bool isValid) external;
}

Read Contract

booster 0xc6def076 → address
boosterOwner 0x7532ed2b → address
crv 0x6a4874a1 → address
cvx 0x923c1d61 → address
operators 0x13e7c9d8 → bool
owner 0x8da5cb5b → address
poolHook 0x3545c789 → address
poolManager 0xdc4c90d3 → address
stashMap 0x4a92b5fd → address
timebuffer 0xb46b400d → uint256

Write Contract 9 functions

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

disable 0x2f2770db
No parameters
earmarkRewards 0xcc956f3f
uint256 _pid
returns: bool
getReward 0xc00007b0
address _stash
onRewardClaim 0x2663fcfc
No parameters
poolAdded 0x4b8843d5
address
uint256
uint256 _poolId
setBuffer 0xadc7ea37
uint256 _seconds
setMultiStashMap 0xc745ccbf
uint256[] _pids
setOperators 0x5cfbfc6d
address _op
bool _valid
setStashMap 0x2e9e1854
uint256 _pid

Recent Transactions

No transactions found for this address