Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xAf824c80aA77Ae7F379DA3Dc05fea0dC1941c200
Balance 0 ETH
Nonce 1
Code Size 2081 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

2081 bytes
0x608060405234801561001057600080fd5b50600436106100675760003560e01c80638f052d4d116100505780638f052d4d146100de578063c6def076146100f3578063d6a0f5301461011a57600080fd5b80630d3158411461006c5780631ba980b31461009f575b600080fd5b61008c61007a3660046105da565b60006020819052908152604090205481565b6040519081526020015b60405180910390f35b6100c67f000000000000000000000000af52695e1bb01a16d33d7194c28c42b10e0dbec281565b6040516001600160a01b039091168152602001610096565b6100f16100ec366004610645565b61012d565b005b6100c67f000000000000000000000000a57b8d98dae62b26ec3bcc4a365338157060b23481565b6001546100c6906001600160a01b031681565b8151806101815760405162461bcd60e51b815260206004820152600860248201527f215f746f6b656e7300000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60005b8281101561021e57600154604051630290cdc160e31b81526001600160a01b037f000000000000000000000000af52695e1bb01a16d33d7194c28c42b10e0dbec281166004830152909116906314866e0890602401600060405180830381600087803b1580156101f357600080fd5b505af1158015610207573d6000803e3d6000fd5b50505050808061021690610713565b915050610184565b5060005b818110156105bc57600084828151811061023e5761023e61072e565b6020908102919091010151600154604051631597828560e31b81526001600160a01b0380841660048301529293506000929091169063acbc142890602401602060405180830381865afa158015610299573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102bd9190610744565b6001600160a01b03831660009081526020819052604090205490915081116103275760405162461bcd60e51b815260206004820152600c60248201527f6e6f742074696d652079657400000000000000000000000000000000000000006044820152606401610178565b6040516316605a0d60e01b81526001600160a01b0383811660048301526000917f000000000000000000000000a57b8d98dae62b26ec3bcc4a365338157060b234909116906316605a0d906024016060604051808303816000875af1158015610394573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b89190610772565b60208101516040516370a0823160e01b81526001600160a01b039182166004820152919250600091908516906370a0823190602401602060405180830381865afa15801561040a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042e9190610744565b60405163a0e0c54d60e01b81526001600160a01b0386811660048301529192507f000000000000000000000000a57b8d98dae62b26ec3bcc4a365338157060b2349091169063a0e0c54d906024016020604051808303816000875af115801561049b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bf91906107e2565b5060208201516040516370a0823160e01b81526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561050e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105329190610744565b9050600061054083836107fd565b1161058d5760405162461bcd60e51b815260206004820152600f60248201527f6e6f7468696e6720636c61696d656400000000000000000000000000000000006044820152606401610178565b5050506001600160a01b03909116600090815260208190526040902055806105b481610713565b915050610222565b50505050565b6001600160a01b03811681146105d757600080fd5b50565b6000602082840312156105ec57600080fd5b81356105f7816105c2565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561063d5761063d6105fe565b604052919050565b6000806040838503121561065857600080fd5b823567ffffffffffffffff8082111561067057600080fd5b818501915085601f83011261068457600080fd5b8135602082821115610698576106986105fe565b8160051b92506106a9818401610614565b82815292840181019281810190898511156106c357600080fd5b948201945b848610156106ed57853593506106dd846105c2565b83825294820194908201906106c8565b9997909101359750505050505050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415610727576107276106fd565b5060010190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561075657600080fd5b5051919050565b8051801515811461076d57600080fd5b919050565b60006060828403121561078457600080fd5b6040516060810181811067ffffffffffffffff821117156107a7576107a76105fe565b60405282516107b5816105c2565b815260208301516107c5816105c2565b60208201526107d66040840161075d565b60408201529392505050565b6000602082840312156107f457600080fd5b6105f78261075d565b60008282101561080f5761080f6106fd565b50039056fea164736f6c634300080b000a

Verified Source Code Partial Match

Compiler: v0.8.11+commit.d7f03943 EVM: london Optimization: Yes (800 runs)
ClaimFeesHelper.sol 79 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;

import { IERC20 } from "@openzeppelin/contracts-0.8/token/ERC20/IERC20.sol";
import { IFeeDistributor } from "./mocks/balancer/MockFeeDistro.sol";

interface IBooster {
    struct FeeDistro {
        address distro;
        address rewards;
        bool active;
    }

    function earmarkFees(address _feeDistro) external returns (bool);

    function feeTokens(address _token) external returns (FeeDistro memory);
}

/**
 * @title   ClaimFeesHelper
 * @author  ConvexFinance
 * @notice  Claim vecrv fees and distribute
 * @dev     Allows anyone to call `claimFees` that will basically collect any 3crv and distribute to cvxCrv
 *          via the booster.
 */
contract ClaimFeesHelper {
    IBooster public immutable booster;
    address public immutable voterProxy;

    mapping(address => uint256) public lastTokenTimes;
    IFeeDistributor public feeDistro;

    /**
     * @param _booster      Booster.sol, e.g. 0xF403C135812408BFbE8713b5A23a04b3D48AAE31
     * @param _voterProxy   CVX VoterProxy e.g. 0x989AEb4d175e16225E39E87d0D97A3360524AD80
     * @param _feeDistro    FeeDistro e.g. 0xD3cf852898b21fc233251427c2DC93d3d604F3BB
     */
    constructor(
        address _booster,
        address _voterProxy,
        address _feeDistro
    ) {
        booster = IBooster(_booster);
        voterProxy = _voterProxy;
        feeDistro = IFeeDistributor(_feeDistro);
    }

    /**
     * @dev Claims fees from fee claimer, and pings the booster to distribute.
     * @param _tokens Token address to claim fees for.
     * @param _checkpoints Number of checkpoints required previous to claim fees.
     */
    function claimFees(IERC20[] memory _tokens, uint256 _checkpoints) external {
        uint256 len = _tokens.length;
        require(len > 0, "!_tokens");

        // Checkpoint user n times before claiming fees
        for (uint256 i = 0; i < _checkpoints; i++) {
            feeDistro.checkpointUser(voterProxy);
        }

        for (uint256 i = 0; i < len; i++) {
            // Validate if the token should be claimed
            IERC20 token = _tokens[i];
            uint256 tokenTime = feeDistro.getTokenTimeCursor(token);
            require(tokenTime > lastTokenTimes[address(token)], "not time yet");

            IBooster.FeeDistro memory feeDist = booster.feeTokens(address(token));
            uint256 balanceBefore = token.balanceOf(feeDist.rewards);

            booster.earmarkFees(address(token));

            uint256 balanceAfter = token.balanceOf(feeDist.rewards);
            require((balanceAfter - balanceBefore) > 0, "nothing claimed");

            lastTokenTimes[address(token)] = tokenTime;
        }
    }
}
MockFeeDistro.sol 89 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;

import { IERC20 } from "@openzeppelin/contracts-0.8/token/ERC20/IERC20.sol";

interface IFeeDistributor {
    function claimToken(address user, IERC20 token) external returns (uint256);

    function claimTokens(address user, IERC20[] calldata tokens) external returns (uint256[] memory);

    function getTokenTimeCursor(IERC20 token) external view returns (uint256);

    function checkpointUser(address user) external;

    function getUserTimeCursor(address user) external view returns (uint256);

    function getTimeCursor() external view returns (uint256);

    function depositToken(IERC20 token, uint256 amount) external;

    function getNextNonce(address) external view returns (uint256);

    function setOnlyCallerCheckWithSignature(
        address,
        bool,
        bytes memory
    ) external;
}

// @dev - Must be funded by transferring crv to this contract post deployment, as opposed to minting directly
contract MockFeeDistributor is IFeeDistributor {
    mapping(address => uint256) private tokenRates;

    constructor(address[] memory _tokens, uint256[] memory _rates) {
        for (uint256 i = 0; i < _tokens.length; i++) {
            tokenRates[_tokens[i]] = _rates[i];
        }
    }

    function claimToken(address user, IERC20 token) external returns (uint256) {
        return _claimToken(user, token);
    }

    function _claimToken(address user, IERC20 token) internal returns (uint256) {
        uint256 rate = tokenRates[address(token)];
        if (rate > 0) {
            token.transfer(user, rate);
        }
        return rate;
    }

    function claimTokens(address user, IERC20[] calldata tokens) external returns (uint256[] memory) {
        uint256[] memory rates = new uint256[](tokens.length);
        for (uint256 i = 0; i < tokens.length; i++) {
            rates[i] = _claimToken(user, tokens[i]);
        }
        return rates;
    }

    function getTokenTimeCursor(
        IERC20 /* token */
    ) external pure returns (uint256) {
        return 1;
    }

    function checkpointUser(address user) external {
        /* do nothing */
    }

    function getUserTimeCursor(address user) external view returns (uint256) {
        /* do nothing */
    }

    function getTimeCursor() external view returns (uint256) {
        /* do nothing */
    }

    function depositToken(IERC20 token, uint256 amount) external {}

    function getNextNonce(address) external view returns (uint256) {
        return 0;
    }

    function setOnlyCallerCheckWithSignature(
        address,
        bool,
        bytes memory
    ) external {}
}
ClaimFeesHelper.sol 68 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;

import { IERC20 } from "@openzeppelin/contracts-0.8/token/ERC20/IERC20.sol";
import { IBooster } from "../interfaces/IBooster.sol";
import { IFeeDistributor } from "../interfaces/balancer/IFeeDistributor.sol";

/**
 * @title   ClaimFeesHelper
 * @author  ConvexFinance
 * @notice  Claim vecrv fees and distribute
 * @dev     Allows anyone to call `claimFees` that will basically collect any 3crv and distribute to cvxCrv
 *          via the booster.
 */
contract ClaimFeesHelper {
    IBooster public immutable booster;
    address public immutable voterProxy;

    mapping(address => uint256) public lastTokenTimes;
    IFeeDistributor public feeDistro;

    /**
     * @param _booster      Booster.sol, e.g. 0xF403C135812408BFbE8713b5A23a04b3D48AAE31
     * @param _voterProxy   CVX VoterProxy e.g. 0x989AEb4d175e16225E39E87d0D97A3360524AD80
     * @param _feeDistro    FeeDistro e.g. 0xD3cf852898b21fc233251427c2DC93d3d604F3BB
     */
    constructor(
        address _booster,
        address _voterProxy,
        address _feeDistro
    ) {
        booster = IBooster(_booster);
        voterProxy = _voterProxy;
        feeDistro = IFeeDistributor(_feeDistro);
    }

    /**
     * @dev Claims fees from fee claimer, and pings the booster to distribute.
     * @param _tokens Token address to claim fees for.
     * @param _checkpoints Number of checkpoints required previous to claim fees.
     */
    function claimFees(IERC20[] memory _tokens, uint256 _checkpoints) external {
        uint256 len = _tokens.length;
        require(len > 0, "!_tokens");

        // Checkpoint user n times before claiming fees
        for (uint256 i = 0; i < _checkpoints; i++) {
            feeDistro.checkpointUser(voterProxy);
        }

        for (uint256 i = 0; i < len; i++) {
            // Validate if the token should be claimed
            IERC20 token = _tokens[i];
            uint256 tokenTime = feeDistro.getTokenTimeCursor(token);
            require(tokenTime > lastTokenTimes[address(token)], "not time yet");

            IBooster.FeeDistro memory feeDist = booster.feeTokens(address(token));
            uint256 balanceBefore = token.balanceOf(feeDist.rewards);

            booster.earmarkFees(address(token));

            uint256 balanceAfter = token.balanceOf(feeDist.rewards);
            require((balanceAfter - balanceBefore) > 0, "nothing claimed");

            lastTokenTimes[address(token)] = tokenTime;
        }
    }
}
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^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);
}
IBooster.sol 27 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;

interface IBooster {
    struct FeeDistro {
        address distro;
        address rewards;
        bool active;
    }

    function feeTokens(address _token) external returns (FeeDistro memory);

    function earmarkFees(address _feeToken) external returns (bool);

    struct PoolInfo {
        address lptoken;
        address token;
        address gauge;
        address crvRewards;
        address stash;
        bool shutdown;
    }

    function earmarkRewards(uint256 _pid) external returns (bool);

    function poolInfo(uint256 _pid) external returns (PoolInfo memory poolInfo);
}
IFeeDistributor.sol 28 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;

import { IERC20 } from "@openzeppelin/contracts-0.8/token/ERC20/IERC20.sol";

interface IFeeDistributor {
    function claimToken(address user, IERC20 token) external returns (uint256);

    function claimTokens(address user, IERC20[] calldata tokens) external returns (uint256[] memory);

    function getTokenTimeCursor(IERC20 token) external view returns (uint256);

    function checkpointUser(address user) external;

    function getUserTimeCursor(address user) external view returns (uint256);

    function getTimeCursor() external view returns (uint256);

    function depositToken(IERC20 token, uint256 amount) external;

    function getNextNonce(address) external view returns (uint256);

    function setOnlyCallerCheckWithSignature(
        address,
        bool,
        bytes memory
    ) external;
}

Read Contract

booster 0xc6def076 → address
feeDistro 0xd6a0f530 → address
lastTokenTimes 0x0d315841 → uint256
voterProxy 0x1ba980b3 → address

Write Contract 1 functions

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

claimFees 0x8f052d4d
address[] _tokens
uint256 _checkpoints

Recent Transactions

No transactions found for this address