账户
0xc3...6b9c
0xC3...6B9C

0xC3...6B9C

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.17+commit.8df45f5f
语言
Solidity
合同源代码
文件 1 的 29:Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}
合同源代码
文件 2 的 29:Bonding.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "IERC20.sol";
import "SafeERC20.sol";
import "Ownable.sol";

import "IBonding.sol";
import "ICNCLockerV3.sol";
import "IRewardManager.sol";
import "ILpTokenStaker.sol";
import "IController.sol";
import "IOracle.sol";
import "IConicPool.sol";

import "ScaledMath.sol";

contract Bonding is IBonding, Ownable {
    using ScaledMath for uint256;
    using SafeERC20 for IERC20;

    IERC20 public constant CVX = IERC20(0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B);
    IERC20 public constant CRV = IERC20(0xD533a949740bb3306d119CC777fa900bA034cd52);
    IERC20 public constant CNC = IERC20(0x9aE380F0272E2162340a5bB646c354271c0F5cFC);

    // The price is set in terms of LP tokens, not USD
    uint256 public constant MAX_CNC_START_PRICE = 20e18;
    uint256 public constant MIN_CNC_START_PRICE = 1e18;
    uint256 public constant MIN_PRICE_INCREASE_FACTOR = 1e18;
    uint256 public constant MAX_MIN_BONDING_AMOUNT = 1_000e18;
    uint256 public constant INITIAL_MIN_BONDING_AMOUNT = 1_000e18;

    ICNCLockerV3 public immutable cncLocker;
    IController public immutable controller;
    IConicPool public immutable crvUsdPool;
    IERC20 public immutable underlying;
    address public immutable treasury;

    address public debtPool;

    uint256 public immutable totalNumberEpochs;
    uint256 public immutable epochDuration;
    uint256 public cncPerEpoch;
    bool public bondingStarted;
    uint256 public bondingEndTime;

    uint256 public cncStartPrice;
    uint256 public cncAvailableCache;
    uint256 public cncDistributed;
    uint256 public epochStartTime; // start time of the current epoch
    uint256 public lastCncPrice;
    uint256 public epochPriceIncreaseFactor;
    uint256 public minBondingAmount;

    mapping(uint256 => uint256) public assetsInEpoch;
    uint256 public lastStreamUpdate; // last update for asset streaming
    uint256 public lastStreamEpochStartTime;

    mapping(address => uint256) public perAccountStreamIntegral;
    mapping(address => uint256) public perAccountStreamAccrued;
    uint256 public streamIntegral;

    constructor(
        address _cncLocker,
        address _controller,
        address _treasury,
        address _crvUsdPool,
        uint256 _epochDuration,
        uint256 _totalNumberEpochs
    ) {
        require(_totalNumberEpochs > 0, "total number of epochs must be positive");
        require(_epochDuration > 0, "epoch duration must be positive");

        cncLocker = ICNCLockerV3(_cncLocker);
        controller = IController(_controller);
        treasury = _treasury;
        crvUsdPool = IConicPool(_crvUsdPool);
        underlying = crvUsdPool.underlying();
        totalNumberEpochs = _totalNumberEpochs;
        epochDuration = _epochDuration;
        minBondingAmount = INITIAL_MIN_BONDING_AMOUNT;
    }

    function startBonding() external override onlyOwner {
        require(!bondingStarted, "bonding already started");
        require(epochPriceIncreaseFactor > 0, "Epoch price increase factor has not been set");
        require(cncStartPrice > 0, "CNC start price not set");
        uint256 cncBalance = CNC.balanceOf(address(this));
        require(cncBalance > 0, "no CNC balance to bond with");

        cncPerEpoch = cncBalance / totalNumberEpochs;

        lastStreamEpochStartTime = block.timestamp;
        lastStreamUpdate = block.timestamp;
        epochStartTime = block.timestamp;
        bondingEndTime = block.timestamp + epochDuration * totalNumberEpochs;

        bondingStarted = true;
        cncAvailableCache = cncPerEpoch;
        emit BondingStarted(cncBalance, totalNumberEpochs);
    }

    function setCncStartPrice(uint256 _cncStartPrice) external override onlyOwner {
        require(
            _cncStartPrice >= MIN_CNC_START_PRICE && _cncStartPrice <= MAX_CNC_START_PRICE,
            "CNC start price not within permitted range"
        );
        cncStartPrice = _cncStartPrice;
        lastCncPrice = _cncStartPrice;
        emit CncStartPriceSet(_cncStartPrice);
    }

    function setCncPriceIncreaseFactor(uint256 _priceIncreaseFactor) external override onlyOwner {
        require(_priceIncreaseFactor >= MIN_PRICE_INCREASE_FACTOR, "Increase factor too low.");
        epochPriceIncreaseFactor = _priceIncreaseFactor;
        emit PriceIncreaseFactorSet(_priceIncreaseFactor);
    }

    function setMinBondingAmount(uint256 _minBondingAmount) external override onlyOwner {
        require(_minBondingAmount <= MAX_MIN_BONDING_AMOUNT, "Min. bonding amount is too high");
        minBondingAmount = _minBondingAmount;
        emit MinBondingAmountSet(_minBondingAmount);
    }

    function setDebtPool(address _debtPool) external override onlyOwner {
        debtPool = _debtPool;
        emit DebtPoolSet(_debtPool);
    }

    function bondCncCrvUsd(
        uint256 lpTokenAmount,
        uint256 minCncReceived,
        uint64 cncLockTime
    ) external override returns (uint256) {
        return bondCncCrvUsdFor(lpTokenAmount, minCncReceived, cncLockTime, msg.sender);
    }

    function bondCncCrvUsdFor(
        uint256 lpTokenAmount,
        uint256 minCncReceived,
        uint64 cncLockTime,
        address recipient
    ) public override returns (uint256) {
        if (!bondingStarted) return 0;
        require(block.timestamp <= bondingEndTime, "Bonding has ended");
        require(lpTokenAmount >= minBondingAmount, "Min. bonding amount not reached");
        _updateAvailableCncAndStartPrice();
        uint256 currentCncBondPrice = computeCurrentCncBondPrice();
        uint256 cncToReceive = lpTokenAmount.divDown(currentCncBondPrice);

        require(
            cncToReceive + cncDistributed <= cncAvailableCache,
            "Not enough CNC currently available"
        );
        require(cncToReceive >= minCncReceived, "Insufficient CNC received");

        // Checkpoint to set user integrals etc.
        _accountCheckpoint(recipient);

        IERC20 lpToken = IERC20(crvUsdPool.lpToken());
        lpToken.safeTransferFrom(msg.sender, address(this), lpTokenAmount);
        ILpTokenStaker lpTokenStaker = controller.lpTokenStaker();
        lpToken.approve(address(lpTokenStaker), lpTokenAmount);
        lpTokenStaker.stake(lpTokenAmount, address(crvUsdPool));

        // Schedule assets for streaming in the next epoch
        assetsInEpoch[epochStartTime + epochDuration] += lpTokenAmount;
        cncDistributed += cncToReceive;
        CNC.approve(address(cncLocker), cncToReceive);
        cncLocker.lockFor(cncToReceive, cncLockTime, false, recipient);

        lastCncPrice = currentCncBondPrice < MIN_CNC_START_PRICE
            ? MIN_CNC_START_PRICE
            : currentCncBondPrice;

        emit Bonded(msg.sender, recipient, lpTokenAmount, cncToReceive, cncLockTime);
        return cncToReceive;
    }

    function claimStream() external override {
        if (!bondingStarted) return;
        _accountCheckpoint(msg.sender);
        IERC20 lpToken = IERC20(crvUsdPool.lpToken());
        uint256 amount = perAccountStreamAccrued[msg.sender];
        require(amount > 0, "no balance");
        ILpTokenStaker lpTokenStaker = controller.lpTokenStaker();
        lpTokenStaker.unstake(amount, address(crvUsdPool));
        lpToken.safeTransfer(msg.sender, amount);
        perAccountStreamAccrued[msg.sender] = 0;
        emit StreamClaimed(msg.sender, amount);
    }

    function claimFeesForDebtPool() external override {
        require(address(debtPool) != address(0), "No debt pool set");
        uint256 cncBefore = CNC.balanceOf(address(this));
        crvUsdPool.rewardManager().claimEarnings();
        uint256 cncAmount = CNC.balanceOf(address(this)) - cncBefore;
        uint256 crvAmount = CRV.balanceOf(address(this));
        uint256 cvxAmount = CVX.balanceOf(address(this));
        CRV.safeTransfer(address(debtPool), crvAmount);
        CVX.safeTransfer(address(debtPool), cvxAmount);
        CNC.safeTransfer(address(debtPool), cncAmount);
        emit DebtPoolFeesClaimed(crvAmount, cvxAmount, cncAmount);
    }

    function recoverRemainingCNC() external override onlyOwner {
        require(block.timestamp > bondingEndTime, "Bonding has not yet ended");
        uint256 amount = CNC.balanceOf(address(this));
        CNC.safeTransfer(treasury, amount);
        emit RemainingCNCRecovered(amount);
    }

    function streamCheckpoint() public override {
        if (!bondingStarted) return;
        _streamCheckpoint();
    }

    function accountCheckpoint(address account) public override {
        if (!bondingStarted) return;
        _accountCheckpoint(account);
    }

    function computeCurrentCncBondPrice() public view override returns (uint256) {
        uint256 discountFactor = ScaledMath.ONE -
            (block.timestamp - epochStartTime).divDown(epochDuration);
        return cncStartPrice.mulDown(discountFactor);
    }

    function cncBondPrice() external view override returns (uint256) {
        uint256 cncStartPrice_ = cncStartPrice;
        uint256 epochStartTime_ = epochStartTime;

        bool priceUpdated;
        while (block.timestamp >= epochStartTime_ + epochDuration) {
            epochStartTime_ += epochDuration;
            if (!priceUpdated) {
                cncStartPrice_ = epochPriceIncreaseFactor.mulDown(lastCncPrice);
                priceUpdated = true;
            }
        }

        uint256 discountFactor = ScaledMath.ONE -
            (block.timestamp - epochStartTime_).divDown(epochDuration);
        return cncStartPrice_.mulDown(discountFactor);
    }

    function cncAvailable() external view override returns (uint256) {
        uint256 cncAvailable_ = cncAvailableCache;
        uint256 epochStartTime_ = epochStartTime;
        while (block.timestamp >= epochStartTime_ + epochDuration) {
            cncAvailable_ += cncPerEpoch;
            epochStartTime_ += epochDuration;
        }
        return cncAvailable_;
    }

    function _accountCheckpoint(address account) internal {
        _streamCheckpoint();
        uint256 accountBoostedBalance = cncLocker.totalStreamBoost(account);
        perAccountStreamAccrued[account] += accountBoostedBalance.mulDown(
            streamIntegral - perAccountStreamIntegral[account]
        );
        perAccountStreamIntegral[account] = streamIntegral;
    }

    function _streamCheckpoint() internal {
        uint256 streamed = _updateStreamed();
        uint256 totalBoosted = cncLocker.totalBoosted();
        if (totalBoosted > 0) {
            streamIntegral += streamed.divDown(totalBoosted);
        }
    }

    function _updateStreamed() internal returns (uint256) {
        uint256 streamed;
        uint256 streamedInEpoch;
        while (
            (block.timestamp >= lastStreamEpochStartTime + epochDuration) &&
            (lastStreamEpochStartTime < bondingEndTime + epochDuration)
        ) {
            streamedInEpoch = (lastStreamEpochStartTime + epochDuration - lastStreamUpdate)
                .divDown(epochDuration)
                .mulDown(assetsInEpoch[lastStreamEpochStartTime]);
            lastStreamEpochStartTime += epochDuration;
            lastStreamUpdate = lastStreamEpochStartTime;
            streamed += streamedInEpoch;
        }
        streamed += (block.timestamp - lastStreamUpdate).divDown(epochDuration).mulDown(
            assetsInEpoch[lastStreamEpochStartTime]
        );
        lastStreamUpdate = block.timestamp;
        return streamed;
    }

    function _updateAvailableCncAndStartPrice() internal {
        bool priceUpdated;
        while (block.timestamp >= epochStartTime + epochDuration) {
            cncAvailableCache += cncPerEpoch;
            epochStartTime += epochDuration;
            if (!priceUpdated) {
                cncStartPrice = epochPriceIncreaseFactor.mulDown(lastCncPrice);
                priceUpdated = true;
            }
        }
    }
}
合同源代码
文件 3 的 29:Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
合同源代码
文件 4 的 29:CurvePoolUtils.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "ICurvePoolV2.sol";
import "ICurvePoolV1.sol";
import "ScaledMath.sol";

library CurvePoolUtils {
    using ScaledMath for uint256;

    error NotWithinThreshold(address pool, uint256 assetA, uint256 assetB);

    /// @dev by default, allow for 30 bps deviation regardless of pool fees
    uint256 internal constant _DEFAULT_IMBALANCE_BUFFER = 30e14;

    /// @dev Curve scales the `fee` by 1e10
    uint8 internal constant _CURVE_POOL_FEE_DECIMALS = 10;

    /// @dev allow imbalance to be buffer + 3x the fee, e.g. if fee is 3.6 bps and buffer is 30 bps, allow 40.8 bps
    uint256 internal constant _FEE_IMBALANCE_MULTIPLIER = 3;

    enum AssetType {
        USD,
        ETH,
        BTC,
        OTHER,
        CRYPTO
    }

    struct PoolMeta {
        address pool;
        uint256 numberOfCoins;
        AssetType assetType;
        uint256[] decimals;
        uint256[] prices;
        uint256[] imbalanceBuffers;
    }

    function ensurePoolBalanced(PoolMeta memory poolMeta) internal view {
        uint256 poolFee = ICurvePoolV1(poolMeta.pool).fee().convertScale(
            _CURVE_POOL_FEE_DECIMALS,
            18
        );

        for (uint256 i = 0; i < poolMeta.numberOfCoins - 1; i++) {
            uint256 fromDecimals = poolMeta.decimals[i];
            uint256 fromBalance = 10 ** fromDecimals;
            uint256 fromPrice = poolMeta.prices[i];

            for (uint256 j = i + 1; j < poolMeta.numberOfCoins; j++) {
                uint256 toDecimals = poolMeta.decimals[j];
                uint256 toPrice = poolMeta.prices[j];
                uint256 toExpectedUnscaled = (fromBalance * fromPrice) / toPrice;
                uint256 toExpected = toExpectedUnscaled.convertScale(
                    uint8(fromDecimals),
                    uint8(toDecimals)
                );

                uint256 toActual;

                if (poolMeta.assetType == AssetType.CRYPTO) {
                    // Handling crypto pools
                    toActual = ICurvePoolV2(poolMeta.pool).get_dy(i, j, fromBalance);
                } else {
                    // Handling other pools
                    toActual = ICurvePoolV1(poolMeta.pool).get_dy(
                        int128(uint128(i)),
                        int128(uint128(j)),
                        fromBalance
                    );
                }
                uint256 _maxImbalanceBuffer = poolMeta.imbalanceBuffers[i].max(
                    poolMeta.imbalanceBuffers[j]
                );

                if (!_isWithinThreshold(toExpected, toActual, poolFee, _maxImbalanceBuffer))
                    revert NotWithinThreshold(poolMeta.pool, i, j);
            }
        }
    }

    function _isWithinThreshold(
        uint256 a,
        uint256 b,
        uint256 poolFee,
        uint256 imbalanceBuffer
    ) internal pure returns (bool) {
        if (imbalanceBuffer == 0) imbalanceBuffer = _DEFAULT_IMBALANCE_BUFFER;
        uint256 imbalanceTreshold = imbalanceBuffer + poolFee * _FEE_IMBALANCE_MULTIPLIER;
        if (a > b) return (a - b).divDown(a) <= imbalanceTreshold;
        return (b - a).divDown(b) <= imbalanceTreshold;
    }
}
合同源代码
文件 5 的 29:IBonding.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

interface IBonding {
    event CncStartPriceSet(uint256 startPrice);
    event PriceIncreaseFactorSet(uint256 factor);
    event MinBondingAmountSet(uint256 amount);
    event Bonded(
        address indexed account,
        address indexed recipient,
        uint256 lpTokenAmount,
        uint256 cncReceived,
        uint256 lockTime
    );
    event DebtPoolSet(address indexed pool);
    event DebtPoolFeesClaimed(uint256 crvAmount, uint256 cvxAmount, uint256 cncAmount);
    event StreamClaimed(address indexed account, uint256 amount);
    event BondingStarted(uint256 amount, uint256 epochs);
    event RemainingCNCRecovered(uint256 amount);

    function startBonding() external;

    function setCncStartPrice(uint256 _cncStartPrice) external;

    function setCncPriceIncreaseFactor(uint256 _priceIncreaseFactor) external;

    function setMinBondingAmount(uint256 _minBondingAmount) external;

    function setDebtPool(address _debtPool) external;

    function bondCncCrvUsd(
        uint256 lpTokenAmount,
        uint256 minCncReceived,
        uint64 cncLockTime
    ) external returns (uint256);

    function recoverRemainingCNC() external;

    function claimStream() external;

    function claimFeesForDebtPool() external;

    function streamCheckpoint() external;

    function accountCheckpoint(address account) external;

    function computeCurrentCncBondPrice() external view returns (uint256);

    function cncAvailable() external view returns (uint256);

    function cncBondPrice() external view returns (uint256);

    function bondCncCrvUsdFor(
        uint256 lpTokenAmount,
        uint256 minCncReceived,
        uint64 cncLockTime,
        address recipient
    ) external returns (uint256);
}
合同源代码
文件 6 的 29:IBooster.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;

interface IBooster {
    function poolInfo(
        uint256 pid
    )
        external
        view
        returns (
            address lpToken,
            address token,
            address gauge,
            address crvRewards,
            address stash,
            bool shutdown
        );

    function poolLength() external view returns (uint256);

    function deposit(uint256 _pid, uint256 _amount, bool _stake) external returns (bool);

    function withdraw(uint256 _pid, uint256 _amount) external returns (bool);

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

    function depositAll(uint256 _pid, bool _stake) external returns (bool);

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

    function isShutdown() external view returns (bool);
}
合同源代码
文件 7 的 29:ICNCLockerV3.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "MerkleProof.sol";
import "IFeeRecipient.sol";

interface ICNCLockerV3 is IFeeRecipient {
    event Locked(address indexed account, uint256 amount, uint256 unlockTime, bool relocked);
    event UnlockExecuted(address indexed account, uint256 amount);
    event Relocked(address indexed account, uint256 amount);
    event KickExecuted(address indexed account, address indexed kicker, uint256 amount);
    event FeesClaimed(address indexed claimer, uint256 crvAmount, uint256 cvxAmount);
    event AirdropBoostClaimed(address indexed claimer, uint256 amount);
    event Shutdown();
    event TokenRecovered(address indexed token);

    struct VoteLock {
        uint256 amount;
        uint64 unlockTime;
        uint128 boost;
        uint64 id;
    }

    struct LockId {
        address user;
        uint64 id;
    }

    function lock(uint256 amount, uint64 lockTime) external;

    function lock(uint256 amount, uint64 lockTime, bool relock) external;

    function lockFor(uint256 amount, uint64 lockTime, bool relock, address account) external;

    function relock(uint64 lockId, uint64 lockTime) external;

    function relock(uint64 lockTime) external;

    function relockMultiple(uint64[] calldata lockIds, uint64 lockTime) external;

    function totalBoosted() external view returns (uint256);

    function shutDown() external;

    function recoverToken(address token) external;

    function executeAvailableUnlocks() external returns (uint256);

    function executeAvailableUnlocksFor(address dst) external returns (uint256);

    function executeUnlocks(address dst, uint64[] calldata lockIds) external returns (uint256);

    function claimAirdropBoost(uint256 amount, MerkleProof.Proof calldata proof) external;

    // This will need to include the boosts etc.
    function balanceOf(address user) external view returns (uint256);

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

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

    function kick(address user, uint64 lockId) external;

    function batchKick(LockId[] memory locks) external;

    function claimableFees(
        address account
    ) external view returns (uint256 claimableCrv, uint256 claimableCvx);

    function claimFees() external returns (uint256 crvAmount, uint256 cvxAmount);

    function computeBoost(uint128 lockTime) external view returns (uint128);

    function airdropBoost(address account) external view returns (uint256);

    function claimedAirdrop(address account) external view returns (bool);

    function totalVoteBoost(address account) external view returns (uint256);

    function totalStreamBoost(address account) external view returns (uint256);

    function totalRewardsBoost(address account) external view returns (uint256);

    function userLocks(address account) external view returns (VoteLock[] memory);
}
合同源代码
文件 8 的 29:IConicPool.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "ILpToken.sol";
import "IRewardManager.sol";
import "IOracle.sol";
import "IController.sol";
import "IPausable.sol";
import "IConicPoolWeightManagement.sol";

interface IConicPool is IConicPoolWeightManagement, IPausable {
    event Deposit(
        address indexed sender,
        address indexed receiver,
        uint256 depositedAmount,
        uint256 lpReceived
    );
    event Withdraw(address indexed account, uint256 amount);
    event NewWeight(address indexed curvePool, uint256 newWeight);
    event NewMaxIdleCurveLpRatio(uint256 newRatio);
    event ClaimedRewards(uint256 claimedCrv, uint256 claimedCvx);
    event HandledDepeggedCurvePool(address curvePool_);
    event HandledInvalidConvexPid(address curvePool_, uint256 pid_);
    event CurvePoolAdded(address curvePool_);
    event CurvePoolRemoved(address curvePool_);
    event Shutdown();
    event DepegThresholdUpdated(uint256 newThreshold);
    event MaxDeviationUpdated(uint256 newMaxDeviation);
    event RebalancingRewardsEnabledSet(bool enabled);
    event EmergencyRebalancingRewardFactorUpdated(uint256 factor);

    struct PoolWithAmount {
        address poolAddress;
        uint256 amount;
    }

    function underlying() external view returns (IERC20Metadata);

    function lpToken() external view returns (ILpToken);

    function rewardManager() external view returns (IRewardManager);

    function depegThreshold() external view returns (uint256);

    function maxIdleCurveLpRatio() external view returns (uint256);

    function setMaxIdleCurveLpRatio(uint256 value) external;

    function setMaxDeviation(uint256 maxDeviation_) external;

    function updateDepegThreshold(uint256 value) external;

    function depositFor(
        address _account,
        uint256 _amount,
        uint256 _minLpReceived,
        bool stake
    ) external returns (uint256);

    function deposit(uint256 _amount, uint256 _minLpReceived) external returns (uint256);

    function deposit(
        uint256 _amount,
        uint256 _minLpReceived,
        bool stake
    ) external returns (uint256);

    function exchangeRate() external view returns (uint256);

    function usdExchangeRate() external view returns (uint256);

    function unstakeAndWithdraw(uint256 _amount, uint256 _minAmount) external returns (uint256);

    function unstakeAndWithdraw(
        uint256 _amount,
        uint256 _minAmount,
        address _to
    ) external returns (uint256);

    function withdraw(uint256 _amount, uint256 _minAmount) external returns (uint256);

    function withdraw(uint256 _amount, uint256 _minAmount, address _to) external returns (uint256);

    function getAllocatedUnderlying() external view returns (PoolWithAmount[] memory);

    function rebalancingRewardActive() external view returns (bool);

    function totalDeviationAfterWeightUpdate() external view returns (uint256);

    function computeTotalDeviation() external view returns (uint256);

    /// @notice returns the total amount of funds held by this pool in terms of underlying
    function totalUnderlying() external view returns (uint256);

    function getTotalAndPerPoolUnderlying()
        external
        view
        returns (
            uint256 totalUnderlying_,
            uint256 totalAllocated_,
            uint256[] memory perPoolUnderlying_
        );

    /// @notice same as `totalUnderlying` but returns a cached version
    /// that might be slightly outdated if oracle prices have changed
    /// @dev this is useful in cases where we want to reduce gas usage and do
    /// not need a precise value
    function cachedTotalUnderlying() external view returns (uint256);

    function updateRewardSpendingApproval(address token, bool approved) external;

    function shutdownPool() external;

    function isShutdown() external view returns (bool);

    function isBalanced() external view returns (bool);

    function rebalancingRewardsEnabled() external view returns (bool);

    function setRebalancingRewardsEnabled(bool enabled) external;

    function getAllUnderlyingCoins() external view returns (address[] memory result);

    function rebalancingRewardsFactor() external view returns (uint256);

    function rebalancingRewardsActivatedAt() external view returns (uint64);

    function getWeights() external view returns (PoolWeight[] memory);

    function runSanityChecks() external;
}
合同源代码
文件 9 的 29:IConicPoolWeightManagement.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

interface IConicPoolWeightManagement {
    struct PoolWeight {
        address poolAddress;
        uint256 weight;
    }

    function addPool(address pool) external;

    function removePool(address pool) external;

    function updateWeights(PoolWeight[] memory poolWeights) external;

    function handleDepeggedCurvePool(address curvePool_) external;

    function handleInvalidConvexPid(address pool) external returns (uint256);

    function allPools() external view returns (address[] memory);

    function poolsCount() external view returns (uint256);

    function getPoolAtIndex(uint256 _index) external view returns (address);

    function getWeight(address curvePool) external view returns (uint256);

    function getWeights() external view returns (PoolWeight[] memory);

    function isRegisteredPool(address _pool) external view returns (bool);
}
合同源代码
文件 10 的 29:IController.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "IConicPoolWeightManagement.sol";
import "IConicPool.sol";
import "IGenericOracle.sol";
import "IInflationManager.sol";
import "ILpTokenStaker.sol";
import "IBonding.sol";
import "IPoolAdapter.sol";
import "IFeeRecipient.sol";
import "ICurveRegistryCache.sol";

interface IController {
    event PoolAdded(address indexed pool);
    event PoolRemoved(address indexed pool);
    event PoolShutdown(address indexed pool);
    event ConvexBoosterSet(address convexBooster);
    event CurveHandlerSet(address curveHandler);
    event ConvexHandlerSet(address convexHandler);
    event CurveRegistryCacheSet(address curveRegistryCache);
    event InflationManagerSet(address inflationManager);
    event BondingSet(address bonding);
    event FeeRecipientSet(address feeRecipient);
    event PriceOracleSet(address priceOracle);
    event WeightUpdateMinDelaySet(uint256 weightUpdateMinDelay);
    event PauseManagerSet(address indexed manager, bool isManager);
    event MultiDepositsWithdrawsWhitelistSet(address pool, bool allowed);
    event MinimumTaintedTransferAmountSet(address indexed token, uint256 amount);
    event DefaultPoolAdapterSet(address poolAdapter);
    event CustomPoolAdapterSet(address indexed pool, address poolAdapter);

    struct WeightUpdate {
        address conicPoolAddress;
        IConicPoolWeightManagement.PoolWeight[] weights;
    }

    function initialize(address _lpTokenStaker) external;

    // inflation manager

    function inflationManager() external view returns (IInflationManager);

    function setInflationManager(address manager) external;

    // views
    function curveRegistryCache() external view returns (ICurveRegistryCache);

    // pool adapter
    function poolAdapterFor(address pool) external view returns (IPoolAdapter);

    function defaultPoolAdapter() external view returns (IPoolAdapter);

    function setDefaultPoolAdapter(address poolAdapter) external;

    function setCustomPoolAdapter(address pool, address poolAdapter) external;

    /// lp token staker
    function switchLpTokenStaker(address _lpTokenStaker) external;

    function lpTokenStaker() external view returns (ILpTokenStaker);

    // bonding
    function bonding() external view returns (IBonding);

    function setBonding(address _bonding) external;

    // fees
    function feeRecipient() external view returns (IFeeRecipient);

    function setFeeRecipient(address _feeRecipient) external;

    // oracle
    function priceOracle() external view returns (IGenericOracle);

    function setPriceOracle(address oracle) external;

    // pool functions

    function listPools() external view returns (address[] memory);

    function listActivePools() external view returns (address[] memory);

    function isPool(address poolAddress) external view returns (bool);

    function isActivePool(address poolAddress) external view returns (bool);

    function addPool(address poolAddress) external;

    function shutdownPool(address poolAddress) external;

    function removePool(address poolAddress) external;

    function cncToken() external view returns (address);

    function lastWeightUpdate(address poolAddress) external view returns (uint256);

    function updateWeights(WeightUpdate memory update) external;

    function updateAllWeights(WeightUpdate[] memory weights) external;

    // handler functions

    function convexBooster() external view returns (address);

    function curveHandler() external view returns (address);

    function convexHandler() external view returns (address);

    function setConvexBooster(address _convexBooster) external;

    function setCurveHandler(address _curveHandler) external;

    function setConvexHandler(address _convexHandler) external;

    function setCurveRegistryCache(address curveRegistryCache_) external;

    function setWeightUpdateMinDelay(uint256 delay) external;

    function isPauseManager(address account) external view returns (bool);

    function listPauseManagers() external view returns (address[] memory);

    function setPauseManager(address account, bool isManager) external;

    // deposit/withdrawal whitelist
    function isAllowedMultipleDepositsWithdraws(address poolAddress) external view returns (bool);

    function setAllowedMultipleDepositsWithdraws(address account, bool allowed) external;

    function getMultipleDepositsWithdrawsWhitelist() external view returns (address[] memory);

    // tainted transfer amount
    function setMinimumTaintedTransferAmount(address token, uint256 amount) external;

    function getMinimumTaintedTransferAmount(address token) external view returns (uint256);

    // constants

    function MAX_WEIGHT_UPDATE_MIN_DELAY() external view returns (uint256);

    function MIN_WEIGHT_UPDATE_MIN_DELAY() external view returns (uint256);
}
合同源代码
文件 11 的 29:ICurvePoolV1.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;

interface ICurvePoolV1 {
    function get_virtual_price() external view returns (uint256);

    function add_liquidity(uint256[8] calldata amounts, uint256 min_mint_amount) external;

    function add_liquidity(uint256[7] calldata amounts, uint256 min_mint_amount) external;

    function add_liquidity(uint256[6] calldata amounts, uint256 min_mint_amount) external;

    function add_liquidity(uint256[5] calldata amounts, uint256 min_mint_amount) external;

    function add_liquidity(uint256[4] calldata amounts, uint256 min_mint_amount) external;

    function add_liquidity(uint256[3] calldata amounts, uint256 min_mint_amount) external;

    function add_liquidity(uint256[2] calldata amounts, uint256 min_mint_amount) external;

    function remove_liquidity_imbalance(
        uint256[4] calldata amounts,
        uint256 max_burn_amount
    ) external;

    function remove_liquidity_imbalance(
        uint256[3] calldata amounts,
        uint256 max_burn_amount
    ) external;

    function remove_liquidity_imbalance(
        uint256[2] calldata amounts,
        uint256 max_burn_amount
    ) external;

    function lp_token() external view returns (address);

    function A_PRECISION() external view returns (uint256);

    function A_precise() external view returns (uint256);

    function remove_liquidity(uint256 _amount, uint256[3] calldata min_amounts) external;

    function exchange(
        int128 from,
        int128 to,
        uint256 _from_amount,
        uint256 _min_to_amount
    ) external;

    function coins(uint256 i) external view returns (address);

    function balances(uint256 i) external view returns (uint256);

    function get_dy(int128 i, int128 j, uint256 _dx) external view returns (uint256);

    function calc_token_amount(
        uint256[4] calldata amounts,
        bool deposit
    ) external view returns (uint256);

    function calc_token_amount(
        uint256[3] calldata amounts,
        bool deposit
    ) external view returns (uint256);

    function calc_token_amount(
        uint256[2] calldata amounts,
        bool deposit
    ) external view returns (uint256);

    function calc_withdraw_one_coin(
        uint256 _token_amount,
        int128 i
    ) external view returns (uint256);

    function remove_liquidity_one_coin(
        uint256 _token_amount,
        int128 i,
        uint256 min_amount
    ) external;

    function fee() external view returns (uint256);
}
合同源代码
文件 12 的 29:ICurvePoolV2.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;

interface ICurvePoolV2 {
    function token() external view returns (address);

    function coins(uint256 i) external view returns (address);

    function factory() external view returns (address);

    function exchange(
        uint256 i,
        uint256 j,
        uint256 dx,
        uint256 min_dy,
        bool use_eth,
        address receiver
    ) external returns (uint256);

    function exchange_underlying(
        uint256 i,
        uint256 j,
        uint256 dx,
        uint256 min_dy,
        address receiver
    ) external returns (uint256);

    function add_liquidity(
        uint256[2] memory amounts,
        uint256 min_mint_amount,
        bool use_eth,
        address receiver
    ) external returns (uint256);

    function add_liquidity(
        uint256[2] memory amounts,
        uint256 min_mint_amount
    ) external returns (uint256);

    function add_liquidity(
        uint256[3] memory amounts,
        uint256 min_mint_amount,
        bool use_eth,
        address receiver
    ) external returns (uint256);

    function add_liquidity(
        uint256[3] memory amounts,
        uint256 min_mint_amount
    ) external returns (uint256);

    function remove_liquidity(
        uint256 _amount,
        uint256[2] memory min_amounts,
        bool use_eth,
        address receiver
    ) external;

    function remove_liquidity(uint256 _amount, uint256[2] memory min_amounts) external;

    function remove_liquidity(
        uint256 _amount,
        uint256[3] memory min_amounts,
        bool use_eth,
        address receiver
    ) external;

    function remove_liquidity(uint256 _amount, uint256[3] memory min_amounts) external;

    function remove_liquidity_one_coin(
        uint256 token_amount,
        uint256 i,
        uint256 min_amount,
        bool use_eth,
        address receiver
    ) external returns (uint256);

    function get_dy(uint256 i, uint256 j, uint256 dx) external view returns (uint256);

    function calc_token_amount(uint256[] memory amounts) external view returns (uint256);

    function calc_withdraw_one_coin(
        uint256 token_amount,
        uint256 i
    ) external view returns (uint256);

    function get_virtual_price() external view returns (uint256);
}
合同源代码
文件 13 的 29:ICurveRegistryCache.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "IBooster.sol";
import "CurvePoolUtils.sol";

interface ICurveRegistryCache {
    event PoolInitialized(address indexed pool, uint256 indexed pid);

    function BOOSTER() external view returns (IBooster);

    function initPool(address pool_) external;

    function initPool(address pool_, uint256 pid_) external;

    function lpToken(address pool_) external view returns (address);

    function assetType(address pool_) external view returns (CurvePoolUtils.AssetType);

    function isRegistered(address pool_) external view returns (bool);

    function hasCoinDirectly(address pool_, address coin_) external view returns (bool);

    function hasCoinAnywhere(address pool_, address coin_) external view returns (bool);

    function basePool(address pool_) external view returns (address);

    function coinIndex(address pool_, address coin_) external view returns (int128);

    function nCoins(address pool_) external view returns (uint256);

    function coinIndices(
        address pool_,
        address from_,
        address to_
    ) external view returns (int128, int128, bool);

    function decimals(address pool_) external view returns (uint256[] memory);

    function interfaceVersion(address pool_) external view returns (uint256);

    function poolFromLpToken(address lpToken_) external view returns (address);

    function coins(address pool_) external view returns (address[] memory);

    function getPid(address _pool) external view returns (uint256);

    function getRewardPool(address _pool) external view returns (address);

    function isShutdownPid(uint256 pid_) external view returns (bool);

    /// @notice this returns the underlying coins of a pool, including the underlying of the base pool
    /// if the given pool is a meta pool
    /// This does not return the LP token of the base pool as an underlying
    /// e.g. if the pool is 3CrvFrax, this will return FRAX, DAI, USDC, USDT
    function getAllUnderlyingCoins(address pool) external view returns (address[] memory);
}
合同源代码
文件 14 的 29:IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

    /**
     * @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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}
合同源代码
文件 15 的 29:IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}
合同源代码
文件 16 的 29:IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}
合同源代码
文件 17 的 29:IFeeRecipient.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

interface IFeeRecipient {
    event FeesReceived(address indexed sender, uint256 crvAmount, uint256 cvxAmount);

    function receiveFees(uint256 amountCrv, uint256 amountCvx) external;
}
合同源代码
文件 18 的 29:IGenericOracle.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "IOracle.sol";

interface IGenericOracle is IOracle {
    /// @notice returns the oracle to be used to price `token`
    function getOracle(address token) external view returns (IOracle);

    /// @notice converts the price of an LP token to the given underlying
    function curveLpToUnderlying(
        address curveLpToken,
        address underlying,
        uint256 curveLpAmount
    ) external view returns (uint256);

    /// @notice same as above but avoids fetching the underlying price again
    function curveLpToUnderlying(
        address curveLpToken,
        address underlying,
        uint256 curveLpAmount,
        uint256 underlyingPrice
    ) external view returns (uint256);

    /// @notice converts the price an underlying asset to a given Curve LP token
    function underlyingToCurveLp(
        address underlying,
        address curveLpToken,
        uint256 underlyingAmount
    ) external view returns (uint256);
}
合同源代码
文件 19 的 29:IInflationManager.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

interface IInflationManager {
    event TokensClaimed(address indexed pool, uint256 cncAmount);
    event RebalancingRewardHandlerAdded(address indexed pool, address indexed handler);
    event RebalancingRewardHandlerRemoved(address indexed pool, address indexed handler);
    event PoolWeightsUpdated();

    function executeInflationRateUpdate() external;

    function updatePoolWeights() external;

    /// @notice returns the weights of the Conic pools to know how much inflation
    /// each of them will receive, as well as the total amount of USD value in all the pools
    function computePoolWeights()
        external
        view
        returns (address[] memory _pools, uint256[] memory poolWeights, uint256 totalUSDValue);

    function computePoolWeight(
        address pool
    ) external view returns (uint256 poolWeight, uint256 totalUSDValue);

    function currentInflationRate() external view returns (uint256);

    function getCurrentPoolInflationRate(address pool) external view returns (uint256);

    function handleRebalancingRewards(
        address account,
        uint256 deviationBefore,
        uint256 deviationAfter
    ) external;

    function addPoolRebalancingRewardHandler(
        address poolAddress,
        address rebalancingRewardHandler
    ) external;

    function removePoolRebalancingRewardHandler(
        address poolAddress,
        address rebalancingRewardHandler
    ) external;

    function rebalancingRewardHandlers(
        address poolAddress
    ) external view returns (address[] memory);

    function hasPoolRebalancingRewardHandler(
        address poolAddress,
        address handler
    ) external view returns (bool);
}
合同源代码
文件 20 的 29:ILpToken.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "IERC20Metadata.sol";

interface ILpToken is IERC20Metadata {
    function minter() external view returns (address);

    function mint(address account, uint256 amount, address ubo) external returns (uint256);

    function burn(address _owner, uint256 _amount, address ubo) external returns (uint256);

    function taint(address from, address to, uint256 amount) external;
}
合同源代码
文件 21 的 29:ILpTokenStaker.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

interface ILpTokenStaker {
    event LpTokenStaked(address indexed account, uint256 amount);
    event LpTokenUnstaked(address indexed account, uint256 amount);
    event TokensClaimed(address indexed pool, uint256 cncAmount);
    event Shutdown();

    function stake(uint256 amount, address conicPool) external;

    function unstake(uint256 amount, address conicPool) external;

    function stakeFor(uint256 amount, address conicPool, address account) external;

    function unstakeFor(uint256 amount, address conicPool, address account) external;

    function unstakeFrom(uint256 amount, address account) external;

    function getUserBalanceForPool(
        address conicPool,
        address account
    ) external view returns (uint256);

    function getBalanceForPool(address conicPool) external view returns (uint256);

    function updateBoost(address user) external;

    function claimCNCRewardsForPool(address pool) external;

    function claimableCnc(address pool) external view returns (uint256);

    function checkpoint(address pool) external returns (uint256);

    function shutdown() external;

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

    function isShutdown() external view returns (bool);
}
合同源代码
文件 22 的 29:IOracle.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

interface IOracle {
    event TokenUpdated(address indexed token, address feed, uint256 maxDelay, bool isEthPrice);

    /// @notice returns the price in USD of symbol.
    function getUSDPrice(address token) external view returns (uint256);

    /// @notice returns if the given token is supported for pricing.
    function isTokenSupported(address token) external view returns (bool);
}
合同源代码
文件 23 的 29:IPausable.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

import "Ownable.sol";

import "IController.sol";

interface IPausable {
    event Paused(uint256 pausedUntil);
    event PauseDurationSet(uint256 pauseDuration);

    function controller() external view returns (IController);

    function pausedUntil() external view returns (uint256);

    function pauseDuration() external view returns (uint256);

    function isPaused() external view returns (bool);

    function setPauseDuration(uint256 _pauseDuration) external;

    function pause() external;
}
合同源代码
文件 24 的 29:IPoolAdapter.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

interface IPoolAdapter {
    /// @notice This is to set which LP token price the value computation should use
    /// `Latest` uses a freshly computed price
    /// `Cached` uses the price in cache
    /// `Minimum` uses the minimum of these two
    enum PriceMode {
        Latest,
        Cached,
        Minimum
    }

    /// @notice Deposit `underlyingAmount` of `underlying` into `pool`
    /// @dev This function should be written with the assumption that it will be delegate-called into
    function deposit(address pool, address underlying, uint256 underlyingAmount) external;

    /// @notice Withdraw `underlyingAmount` of `underlying` from `pool`
    /// @dev This function should be written with the assumption that it will be delegate-called into
    function withdraw(address pool, address underlying, uint256 underlyingAmount) external;

    /// @notice Returns the amount of of assets that `conicPool` holds in `pool`, in terms of USD
    function computePoolValueInUSD(
        address conicPool,
        address pool
    ) external view returns (uint256 usdAmount);

    /// @notice Updates the price caches of the given pools
    function updatePriceCache(address pool) external;

    /// @notice Returns the amount of of assets that `conicPool` holds in `pool`, in terms of USD
    /// using the given price mode
    function computePoolValueInUSD(
        address conicPool,
        address pool,
        PriceMode priceMode
    ) external view returns (uint256 usdAmount);

    /// @notice Returns the amount of of assets that `conicPool` holds in `pool`, in terms of underlying
    function computePoolValueInUnderlying(
        address conicPool,
        address pool,
        address underlying,
        uint256 underlyingPrice
    ) external view returns (uint256 underlyingAmount);

    /// @notice Returns the amount of of assets that `conicPool` holds in `pool`, in terms of underlying
    /// using the given price mode
    function computePoolValueInUnderlying(
        address conicPool,
        address pool,
        address underlying,
        uint256 underlyingPrice,
        PriceMode priceMode
    ) external view returns (uint256 underlyingAmount);

    /// @notice Claim earnings of `conicPool` from `pool`
    function claimEarnings(address conicPool, address pool) external;

    /// @notice Returns the LP token of a given `pool`
    function lpToken(address pool) external view returns (address);

    /// @notice Returns true if `pool` supports `asset`
    function supportsAsset(address pool, address asset) external view returns (bool);

    /// @notice Returns the amount of CRV earned by `pool` on Convex
    function getCRVEarnedOnConvex(
        address account,
        address curvePool
    ) external view returns (uint256);

    /// @notice Executes a sanity check, e.g. checking for reentrancy
    function executeSanityCheck(address pool) external;

    /// @notice returns all the underlying coins of the pool
    function getAllUnderlyingCoins(address pool) external view returns (address[] memory);
}
合同源代码
文件 25 的 29:IRewardManager.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

interface IRewardManager {
    event ClaimedRewards(uint256 claimedCrv, uint256 claimedCvx);
    event SoldRewardTokens(uint256 targetTokenReceived);
    event ExtraRewardAdded(address reward);
    event ExtraRewardRemoved(address reward);
    event ExtraRewardsCurvePoolSet(address extraReward, address curvePool);
    event FeesSet(uint256 feePercentage);
    event FeesEnabled(uint256 feePercentage);
    event EarningsClaimed(
        address indexed claimedBy,
        uint256 cncEarned,
        uint256 crvEarned,
        uint256 cvxEarned
    );

    function accountCheckpoint(address account) external;

    function poolCheckpoint() external returns (bool);

    function addExtraReward(address reward) external returns (bool);

    function addBatchExtraRewards(address[] memory rewards) external;

    function conicPool() external view returns (address);

    function setFeePercentage(uint256 _feePercentage) external;

    function claimableRewards(
        address account
    ) external view returns (uint256 cncRewards, uint256 crvRewards, uint256 cvxRewards);

    function claimEarnings() external returns (uint256, uint256, uint256);

    function claimPoolEarningsAndSellRewardTokens() external;

    function feePercentage() external view returns (uint256);

    function feesEnabled() external view returns (bool);
}
合同源代码
文件 26 的 29:MerkleProof.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

library MerkleProof {
    struct Proof {
        uint16 nodeIndex;
        bytes32[] hashes;
    }

    function isValid(
        Proof memory proof,
        bytes32 node,
        bytes32 merkleRoot
    ) internal pure returns (bool) {
        uint256 length = proof.hashes.length;
        uint16 nodeIndex = proof.nodeIndex;
        for (uint256 i = 0; i < length; i++) {
            if (nodeIndex % 2 == 0) {
                node = keccak256(abi.encodePacked(node, proof.hashes[i]));
            } else {
                node = keccak256(abi.encodePacked(proof.hashes[i], node));
            }
            nodeIndex /= 2;
        }

        return node == merkleRoot;
    }
}
合同源代码
文件 27 的 29:Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
合同源代码
文件 28 的 29:SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "IERC20.sol";
import "IERC20Permit.sol";
import "Address.sol";

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

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        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));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}
合同源代码
文件 29 的 29:ScaledMath.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

library ScaledMath {
    uint256 internal constant DECIMALS = 18;
    uint256 internal constant ONE = 10 ** DECIMALS;

    function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {
        return (a * b) / ONE;
    }

    function mulDown(uint256 a, uint256 b, uint256 decimals) internal pure returns (uint256) {
        return (a * b) / (10 ** decimals);
    }

    function divDown(uint256 a, uint256 b) internal pure returns (uint256) {
        return (a * ONE) / b;
    }

    function divDown(uint256 a, uint256 b, uint256 decimals) internal pure returns (uint256) {
        return (a * 10 ** decimals) / b;
    }

    function divUp(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        return ((a * ONE) - 1) / b + 1;
    }

    function mulDown(int256 a, int256 b) internal pure returns (int256) {
        return (a * b) / int256(ONE);
    }

    function mulDownUint128(uint128 a, uint128 b) internal pure returns (uint128) {
        return (a * b) / uint128(ONE);
    }

    function mulDown(int256 a, int256 b, uint256 decimals) internal pure returns (int256) {
        return (a * b) / int256(10 ** decimals);
    }

    function divDown(int256 a, int256 b) internal pure returns (int256) {
        return (a * int256(ONE)) / b;
    }

    function divDownUint128(uint128 a, uint128 b) internal pure returns (uint128) {
        return (a * uint128(ONE)) / b;
    }

    function divDown(int256 a, int256 b, uint256 decimals) internal pure returns (int256) {
        return (a * int256(10 ** decimals)) / b;
    }

    function convertScale(
        uint256 a,
        uint8 fromDecimals,
        uint8 toDecimals
    ) internal pure returns (uint256) {
        if (fromDecimals == toDecimals) return a;
        if (fromDecimals > toDecimals) return downscale(a, fromDecimals, toDecimals);
        return upscale(a, fromDecimals, toDecimals);
    }

    function convertScale(
        int256 a,
        uint8 fromDecimals,
        uint8 toDecimals
    ) internal pure returns (int256) {
        if (fromDecimals == toDecimals) return a;
        if (fromDecimals > toDecimals) return downscale(a, fromDecimals, toDecimals);
        return upscale(a, fromDecimals, toDecimals);
    }

    function upscale(
        uint256 a,
        uint8 fromDecimals,
        uint8 toDecimals
    ) internal pure returns (uint256) {
        return a * (10 ** (toDecimals - fromDecimals));
    }

    function downscale(
        uint256 a,
        uint8 fromDecimals,
        uint8 toDecimals
    ) internal pure returns (uint256) {
        return a / (10 ** (fromDecimals - toDecimals));
    }

    function upscale(
        int256 a,
        uint8 fromDecimals,
        uint8 toDecimals
    ) internal pure returns (int256) {
        return a * int256(10 ** (toDecimals - fromDecimals));
    }

    function downscale(
        int256 a,
        uint8 fromDecimals,
        uint8 toDecimals
    ) internal pure returns (int256) {
        return a / int256(10 ** (fromDecimals - toDecimals));
    }

    function intPow(uint256 a, uint256 n) internal pure returns (uint256) {
        uint256 result = ONE;
        for (uint256 i; i < n; ) {
            result = mulDown(result, a);
            unchecked {
                ++i;
            }
        }
        return result;
    }

    function absSub(uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            return a >= b ? a - b : b - a;
        }
    }

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

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a <= b ? a : b;
    }
}
设置
{
  "compilationTarget": {
    "Bonding.sol": "Bonding"
  },
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"address","name":"_cncLocker","type":"address"},{"internalType":"address","name":"_controller","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_crvUsdPool","type":"address"},{"internalType":"uint256","name":"_epochDuration","type":"uint256"},{"internalType":"uint256","name":"_totalNumberEpochs","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"lpTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cncReceived","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockTime","type":"uint256"}],"name":"Bonded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epochs","type":"uint256"}],"name":"BondingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startPrice","type":"uint256"}],"name":"CncStartPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"crvAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cvxAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cncAmount","type":"uint256"}],"name":"DebtPoolFeesClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"DebtPoolSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MinBondingAmountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"factor","type":"uint256"}],"name":"PriceIncreaseFactorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RemainingCNCRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StreamClaimed","type":"event"},{"inputs":[],"name":"CNC","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRV","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CVX","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_MIN_BONDING_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_CNC_START_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MIN_BONDING_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_CNC_START_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_PRICE_INCREASE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"accountCheckpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"assetsInEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lpTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minCncReceived","type":"uint256"},{"internalType":"uint64","name":"cncLockTime","type":"uint64"}],"name":"bondCncCrvUsd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lpTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minCncReceived","type":"uint256"},{"internalType":"uint64","name":"cncLockTime","type":"uint64"},{"internalType":"address","name":"recipient","type":"address"}],"name":"bondCncCrvUsdFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bondingEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondingStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFeesForDebtPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimStream","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cncAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cncAvailableCache","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cncBondPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cncDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cncLocker","outputs":[{"internalType":"contract ICNCLockerV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cncPerEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cncStartPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"computeCurrentCncBondPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crvUsdPool","outputs":[{"internalType":"contract IConicPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochPriceIncreaseFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastCncPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastStreamEpochStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastStreamUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minBondingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"perAccountStreamAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"perAccountStreamIntegral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recoverRemainingCNC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_priceIncreaseFactor","type":"uint256"}],"name":"setCncPriceIncreaseFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cncStartPrice","type":"uint256"}],"name":"setCncStartPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_debtPool","type":"address"}],"name":"setDebtPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minBondingAmount","type":"uint256"}],"name":"setMinBondingAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startBonding","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"streamCheckpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"streamIntegral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNumberEpochs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]