编译器
0.8.17+commit.8df45f5f
文件 1 的 41:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
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");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
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");
}
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);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
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);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
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);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
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 {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 41:ArrayExtensions.sol
pragma solidity 0.8.17;
library ArrayExtensions {
function copy(uint256[] memory array) internal pure returns (uint256[] memory) {
uint256[] memory copy_ = new uint256[](array.length);
for (uint256 i = 0; i < array.length; i++) {
copy_[i] = array[i];
}
return copy_;
}
function concat(
address[] memory a,
address[] memory b
) internal pure returns (address[] memory result) {
result = new address[](a.length + b.length);
for (uint256 i; i < a.length; i++) result[i] = a[i];
for (uint256 i; i < b.length; i++) result[i + a.length] = b[i];
}
function includes(address[] memory array, address element) internal pure returns (bool) {
return _includes(array, element, array.length);
}
function _includes(
address[] memory array,
address element,
uint256 until
) internal pure returns (bool) {
for (uint256 i; i < until; i++) {
if (array[i] == element) return true;
}
return false;
}
function removeDuplicates(address[] memory array) internal pure returns (address[] memory) {
address[] memory unique = new address[](array.length);
uint256 j;
for (uint256 i; i < array.length; i++) {
if (!_includes(unique, array[i], j)) {
unique[j++] = array[i];
}
}
return trim(unique, j);
}
function trim(
address[] memory array,
uint256 length
) internal pure returns (address[] memory trimmed) {
trimmed = new address[](length);
for (uint256 i; i < length; i++) trimmed[i] = array[i];
}
}
文件 3 的 41:BaseConicPool.sol
pragma solidity 0.8.17;
import "contracts/access/Ownable.sol";
import "contracts/token/ERC20/ERC20.sol";
import "contracts/utils/Address.sol";
import "contracts/utils/structs/EnumerableSet.sol";
import "contracts/utils/structs/EnumerableMap.sol";
import "contracts/token/ERC20/IERC20.sol";
import "contracts/token/ERC20/utils/SafeERC20.sol";
import "contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "contracts/utils/introspection/ERC165Checker.sol";
import "interfaces/pools/IConicPool.sol";
import "interfaces/pools/IRewardManager.sol";
import "interfaces/pools/IWithdrawalProcessor.sol";
import "interfaces/ICurveRegistryCache.sol";
import "interfaces/tokenomics/IInflationManager.sol";
import "interfaces/tokenomics/ILpTokenStaker.sol";
import "interfaces/IOracle.sol";
import "interfaces/vendor/IBaseRewardPool.sol";
import "contracts/LpToken.sol";
import "contracts/Pausable.sol";
import "contracts/ConicPoolWeightManager.sol";
import "libraries/ScaledMath.sol";
import "libraries/ArrayExtensions.sol";
abstract contract BaseConicPool is IConicPool, Pausable {
using ArrayExtensions for uint256[];
using ArrayExtensions for address[];
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableMap for EnumerableMap.AddressToUintMap;
using SafeERC20 for IERC20;
using SafeERC20 for IERC20Metadata;
using SafeERC20 for ILpToken;
using ScaledMath for uint256;
using Address for address;
using ERC165Checker for address;
struct DepositVars {
uint256 exchangeRate;
uint256 underlyingBalanceIncrease;
uint256 mintableUnderlyingAmount;
uint256 lpReceived;
uint256 underlyingBalanceBefore;
uint256 allocatedBalanceBefore;
uint256[] allocatedPerPoolBefore;
uint256 underlyingBalanceAfter;
uint256 allocatedBalanceAfter;
uint256[] allocatedPerPoolAfter;
}
uint256 internal constant _IDLE_RATIO_UPPER_BOUND = 0.2e18;
uint256 internal constant _MIN_DEPEG_THRESHOLD = 0.01e18;
uint256 internal constant _MAX_DEPEG_THRESHOLD = 0.1e18;
uint256 internal constant _MAX_DEVIATION_UPPER_BOUND = 0.2e18;
uint256 internal constant _TOTAL_UNDERLYING_CACHE_EXPIRY = 3 days;
uint256 internal constant _MAX_USD_VALUE_FOR_REMOVING_POOL = 100e18;
uint256 internal constant _MIN_EMERGENCY_REBALANCING_REWARD_FACTOR = 1e18;
uint256 internal constant _MAX_EMERGENCY_REBALANCING_REWARD_FACTOR = 100e18;
IERC20 internal immutable CVX;
IERC20 internal immutable CRV;
IERC20 internal constant CNC = IERC20(0x9aE380F0272E2162340a5bB646c354271c0F5cFC);
address internal constant _WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
IERC20Metadata public immutable override underlying;
ILpToken public immutable override lpToken;
IRewardManager public immutable rewardManager;
IConicPoolWeightManager public immutable weightManager;
uint256 public maxDeviation = 0.02e18;
uint256 public maxIdleCurveLpRatio = 0.05e18;
bool public isShutdown;
uint256 public depegThreshold = 0.03e18;
uint256 internal _cacheUpdatedTimestamp;
uint256 internal _cachedTotalUnderlying;
bool public rebalancingRewardsEnabled;
bool public rebalancingRewardActive;
uint64 public rebalancingRewardsActivatedAt;
uint256 public emergencyRebalancingRewardsFactor = 10e18;
uint256 public rebalancingRewardsFactor;
uint256 public totalDeviationAfterWeightUpdate;
mapping(address => uint256) _cachedPrices;
modifier onlyController() {
require(msg.sender == address(controller), "not authorized");
_;
}
constructor(
address _underlying,
IRewardManager _rewardManager,
address _controller,
string memory _lpTokenName,
string memory _symbol,
address _cvx,
address _crv
) Pausable(IController(_controller)) {
require(
_underlying != _cvx && _underlying != _crv && _underlying != address(CNC),
"invalid underlying"
);
underlying = IERC20Metadata(_underlying);
uint8 decimals = IERC20Metadata(_underlying).decimals();
lpToken = new LpToken(_controller, address(this), decimals, _lpTokenName, _symbol);
rewardManager = _rewardManager;
weightManager = new ConicPoolWeightManager(
IController(_controller),
IERC20Metadata(_underlying)
);
CVX = IERC20(_cvx);
CRV = IERC20(_crv);
CVX.safeApprove(address(_rewardManager), type(uint256).max);
CRV.safeApprove(address(_rewardManager), type(uint256).max);
CNC.safeApprove(address(_rewardManager), type(uint256).max);
}
receive() external payable {
require(address(underlying) == _WETH_ADDRESS, "not WETH pool");
}
function depositFor(
address account,
uint256 underlyingAmount,
uint256 minLpReceived,
bool stake
) public override notPaused returns (uint256) {
runSanityChecks();
DepositVars memory vars;
require(!isShutdown, "pool is shut down");
require(underlyingAmount > 0, "deposit amount cannot be zero");
_updateAdapterCachedPrices();
uint256 underlyingPrice_ = controller.priceOracle().getUSDPrice(address(underlying));
(
vars.underlyingBalanceBefore,
vars.allocatedBalanceBefore,
vars.allocatedPerPoolBefore
) = _getTotalAndPerPoolUnderlying(underlyingPrice_, IPoolAdapter.PriceMode.Cached);
vars.exchangeRate = _exchangeRate(vars.underlyingBalanceBefore);
underlying.safeTransferFrom(msg.sender, address(this), underlyingAmount);
_depositToCurve(
vars.allocatedBalanceBefore,
vars.allocatedPerPoolBefore,
underlying.balanceOf(address(this))
);
(
vars.underlyingBalanceAfter,
vars.allocatedBalanceAfter,
vars.allocatedPerPoolAfter
) = _getTotalAndPerPoolUnderlying(underlyingPrice_, IPoolAdapter.PriceMode.Minimum);
vars.underlyingBalanceIncrease = vars.underlyingBalanceAfter - vars.underlyingBalanceBefore;
vars.mintableUnderlyingAmount = _min(underlyingAmount, vars.underlyingBalanceIncrease);
vars.lpReceived = vars.mintableUnderlyingAmount.divDown(vars.exchangeRate);
require(vars.lpReceived >= minLpReceived, "too much slippage");
_cachedTotalUnderlying = vars.underlyingBalanceAfter;
_cacheUpdatedTimestamp = block.timestamp;
if (stake) {
lpToken.mint(address(this), vars.lpReceived, account);
ILpTokenStaker lpTokenStaker = controller.lpTokenStaker();
lpToken.forceApprove(address(lpTokenStaker), vars.lpReceived);
lpTokenStaker.stakeFor(vars.lpReceived, address(this), account);
} else {
lpToken.mint(account, vars.lpReceived, account);
}
_handleRebalancingRewards(
account,
vars.allocatedBalanceBefore,
vars.allocatedPerPoolBefore,
vars.allocatedBalanceAfter,
vars.allocatedPerPoolAfter
);
emit Deposit(msg.sender, account, underlyingAmount, vars.lpReceived);
return vars.lpReceived;
}
function deposit(
uint256 underlyingAmount,
uint256 minLpReceived
) external override returns (uint256) {
return depositFor(msg.sender, underlyingAmount, minLpReceived, true);
}
function deposit(
uint256 underlyingAmount,
uint256 minLpReceived,
bool stake
) external override returns (uint256) {
return depositFor(msg.sender, underlyingAmount, minLpReceived, stake);
}
function _depositToCurve(
uint256 totalUnderlying_,
uint256[] memory allocatedPerPool,
uint256 underlyingAmount_
) internal {
uint256 depositsRemaining_ = underlyingAmount_;
uint256 totalAfterDeposit_ = totalUnderlying_ + underlyingAmount_;
uint256[] memory allocatedPerPoolCopy = allocatedPerPool.copy();
while (depositsRemaining_ > 0) {
(uint256 poolIndex_, uint256 maxDeposit_) = weightManager.getDepositPool(
totalAfterDeposit_,
allocatedPerPoolCopy,
_getMaxDeviation()
);
if (depositsRemaining_ < maxDeposit_ + 1e2) {
maxDeposit_ = depositsRemaining_;
}
address pool_ = weightManager.getPoolAtIndex(poolIndex_);
uint256 toDeposit_ = _min(depositsRemaining_, maxDeposit_);
address poolAdapter = address(controller.poolAdapterFor(pool_));
poolAdapter.functionDelegateCall(
abi.encodeWithSignature(
"deposit(address,address,uint256)",
pool_,
address(underlying),
toDeposit_
)
);
depositsRemaining_ -= toDeposit_;
allocatedPerPoolCopy[poolIndex_] += toDeposit_;
}
}
function totalUnderlying() public view virtual returns (uint256) {
(uint256 totalUnderlying_, , ) = getTotalAndPerPoolUnderlying();
return totalUnderlying_;
}
function updateRewardSpendingApproval(address token, bool approved) external {
require(msg.sender == address(rewardManager), "not authorized");
uint256 amount = approved ? type(uint256).max : 0;
IERC20(token).safeApprove(address(rewardManager), amount);
}
function _exchangeRate(uint256 totalUnderlying_) internal view returns (uint256) {
uint256 lpSupply = lpToken.totalSupply();
if (lpSupply == 0 || totalUnderlying_ == 0) return ScaledMath.ONE;
return totalUnderlying_.divDown(lpSupply);
}
function exchangeRate() public view virtual override returns (uint256) {
return _exchangeRate(totalUnderlying());
}
function usdExchangeRate() external view virtual override returns (uint256) {
uint256 underlyingPrice = controller.priceOracle().getUSDPrice(address(underlying));
return _exchangeRate(cachedTotalUnderlying()).mulDown(underlyingPrice);
}
function unstakeAndWithdraw(
uint256 conicLpAmount,
uint256 minUnderlyingReceived,
address to
) public override returns (uint256) {
controller.lpTokenStaker().unstakeFrom(conicLpAmount, msg.sender);
return withdraw(conicLpAmount, minUnderlyingReceived, to);
}
function unstakeAndWithdraw(
uint256 conicLpAmount,
uint256 minUnderlyingReceived
) external returns (uint256) {
return unstakeAndWithdraw(conicLpAmount, minUnderlyingReceived, msg.sender);
}
function withdraw(
uint256 conicLpAmount,
uint256 minUnderlyingReceived
) public override returns (uint256) {
return withdraw(conicLpAmount, minUnderlyingReceived, msg.sender);
}
function withdraw(
uint256 conicLpAmount,
uint256 minUnderlyingReceived,
address to
) public override returns (uint256) {
runSanityChecks();
require(lpToken.balanceOf(msg.sender) >= conicLpAmount, "insufficient balance");
uint256 underlyingBalanceBefore_ = underlying.balanceOf(address(this));
(
uint256 totalUnderlying_,
uint256 allocatedUnderlying_,
uint256[] memory allocatedPerPool
) = getTotalAndPerPoolUnderlying();
uint256 underlyingToReceive_ = conicLpAmount.mulDown(_exchangeRate(totalUnderlying_));
{
if (underlyingBalanceBefore_ < underlyingToReceive_) {
uint256 underlyingToWithdraw_ = underlyingToReceive_ - underlyingBalanceBefore_;
_withdrawFromCurve(allocatedUnderlying_, allocatedPerPool, underlyingToWithdraw_);
}
}
uint256 underlyingWithdrawn_ = _min(
underlying.balanceOf(address(this)),
underlyingToReceive_
);
require(underlyingWithdrawn_ >= minUnderlyingReceived, "too much slippage");
lpToken.burn(msg.sender, conicLpAmount, msg.sender);
underlying.safeTransfer(to, underlyingWithdrawn_);
_cachedTotalUnderlying = totalUnderlying_ - underlyingWithdrawn_;
_cacheUpdatedTimestamp = block.timestamp;
if (to.supportsInterface(type(IWithdrawalProcessor).interfaceId)) {
IWithdrawalProcessor(to).processWithdrawal(msg.sender, underlyingWithdrawn_);
}
emit Withdraw(msg.sender, underlyingWithdrawn_);
return underlyingWithdrawn_;
}
function _withdrawFromCurve(
uint256 totalUnderlying_,
uint256[] memory allocatedPerPool,
uint256 amount_
) internal {
uint256 withdrawalsRemaining_ = amount_;
uint256 totalAfterWithdrawal_ = totalUnderlying_ - amount_;
uint256[] memory allocatedPerPoolCopy = allocatedPerPool.copy();
while (withdrawalsRemaining_ > 0) {
(uint256 poolIndex_, uint256 maxWithdrawal_) = weightManager.getWithdrawPool(
totalAfterWithdrawal_,
allocatedPerPoolCopy,
_getMaxDeviation()
);
address pool_ = weightManager.getPoolAtIndex(poolIndex_);
uint256 toWithdraw_ = _min(withdrawalsRemaining_, maxWithdrawal_);
address poolAdapter = address(controller.poolAdapterFor(pool_));
poolAdapter.functionDelegateCall(
abi.encodeWithSignature(
"withdraw(address,address,uint256)",
pool_,
underlying,
toWithdraw_
)
);
withdrawalsRemaining_ -= toWithdraw_;
allocatedPerPoolCopy[poolIndex_] -= toWithdraw_;
}
}
function allPools() external view override returns (address[] memory) {
return weightManager.allPools();
}
function poolsCount() external view override returns (uint256) {
return weightManager.poolsCount();
}
function getPoolAtIndex(uint256 _index) external view override returns (address) {
return weightManager.getPoolAtIndex(_index);
}
function isRegisteredPool(address _pool) external view returns (bool) {
return weightManager.isRegisteredPool(_pool);
}
function addPool(address _pool) external override onlyOwner {
weightManager.addPool(_pool);
address booster = controller.convexBooster();
address lpToken_ = controller.poolAdapterFor(_pool).lpToken(_pool);
IERC20(lpToken_).safeApprove(booster, type(uint256).max);
}
function removePool(address _pool) external override onlyOwner {
weightManager.removePool(_pool);
address booster = controller.convexBooster();
address lpToken_ = controller.poolAdapterFor(_pool).lpToken(_pool);
IERC20(lpToken_).safeApprove(booster, 0);
}
function updateWeights(PoolWeight[] memory poolWeights) external onlyController {
runSanityChecks();
weightManager.updateWeights(poolWeights);
(
uint256 totalUnderlying_,
uint256 totalAllocated,
uint256[] memory allocatedPerPool
) = getTotalAndPerPoolUnderlying();
uint256 totalDeviation = weightManager.computeTotalDeviation(
totalUnderlying_,
allocatedPerPool
);
totalDeviationAfterWeightUpdate = totalDeviation;
rebalancingRewardActive =
rebalancingRewardsEnabled &&
!_isBalanced(allocatedPerPool, totalAllocated);
rebalancingRewardsFactor = ScaledMath.ONE;
rebalancingRewardsActivatedAt = uint64(block.timestamp);
_updatePriceCache();
}
function shutdownPool() external override onlyController {
require(!isShutdown, "pool already shut down");
isShutdown = true;
emit Shutdown();
}
function updateDepegThreshold(uint256 newDepegThreshold_) external onlyOwner {
require(newDepegThreshold_ >= _MIN_DEPEG_THRESHOLD, "invalid depeg threshold");
require(newDepegThreshold_ <= _MAX_DEPEG_THRESHOLD, "invalid depeg threshold");
require(newDepegThreshold_ != depegThreshold, "same as current");
depegThreshold = newDepegThreshold_;
emit DepegThresholdUpdated(newDepegThreshold_);
}
function handleDepeggedCurvePool(address curvePool_) external override {
runSanityChecks();
require(!_isAssetDepegged(address(underlying)), "underlying is depegged");
require(_isPoolDepegged(curvePool_), "pool is not depegged");
weightManager.handleDepeggedCurvePool(curvePool_);
(
uint256 totalUnderlying_,
,
uint256[] memory allocatedPerPool
) = getTotalAndPerPoolUnderlying();
uint256 totalDeviation = weightManager.computeTotalDeviation(
totalUnderlying_,
allocatedPerPool
);
totalDeviationAfterWeightUpdate = totalDeviation;
if (rebalancingRewardsEnabled) {
IPoolAdapter poolAdapter = controller.poolAdapterFor(curvePool_);
uint256 usdValue = poolAdapter.computePoolValueInUSD(address(this), curvePool_);
if (usdValue > _MAX_USD_VALUE_FOR_REMOVING_POOL) {
rebalancingRewardsActivatedAt = uint64(block.timestamp);
rebalancingRewardsFactor = emergencyRebalancingRewardsFactor;
rebalancingRewardActive = true;
}
}
emit HandledDepeggedCurvePool(curvePool_);
}
function handleInvalidConvexPid(address curvePool_) external override returns (uint256) {
runSanityChecks();
uint256 pid = weightManager.handleInvalidConvexPid(curvePool_);
emit HandledInvalidConvexPid(curvePool_, pid);
return pid;
}
function setMaxIdleCurveLpRatio(uint256 maxIdleCurveLpRatio_) external onlyOwner {
require(maxIdleCurveLpRatio != maxIdleCurveLpRatio_, "same as current");
require(maxIdleCurveLpRatio_ <= _IDLE_RATIO_UPPER_BOUND, "ratio exceeds upper bound");
maxIdleCurveLpRatio = maxIdleCurveLpRatio_;
emit NewMaxIdleCurveLpRatio(maxIdleCurveLpRatio_);
}
function setMaxDeviation(uint256 maxDeviation_) external override onlyOwner {
require(maxDeviation != maxDeviation_, "same as current");
require(maxDeviation_ <= _MAX_DEVIATION_UPPER_BOUND, "deviation exceeds upper bound");
maxDeviation = maxDeviation_;
emit MaxDeviationUpdated(maxDeviation_);
}
function getWeight(address curvePool) external view override returns (uint256) {
return weightManager.getWeight(curvePool);
}
function getWeights() external view override returns (PoolWeight[] memory) {
return weightManager.getWeights();
}
function getAllocatedUnderlying() external view override returns (PoolWithAmount[] memory) {
address[] memory pools = weightManager.allPools();
PoolWithAmount[] memory perPoolAllocated = new PoolWithAmount[](pools.length);
(, , uint256[] memory allocated) = getTotalAndPerPoolUnderlying();
for (uint256 i; i < perPoolAllocated.length; i++) {
perPoolAllocated[i] = PoolWithAmount(pools[i], allocated[i]);
}
return perPoolAllocated;
}
function computeTotalDeviation() external view override returns (uint256) {
(
,
uint256 allocatedUnderlying_,
uint256[] memory perPoolUnderlying
) = getTotalAndPerPoolUnderlying();
return weightManager.computeTotalDeviation(allocatedUnderlying_, perPoolUnderlying);
}
function cachedTotalUnderlying() public view virtual override returns (uint256) {
if (block.timestamp > _cacheUpdatedTimestamp + _TOTAL_UNDERLYING_CACHE_EXPIRY) {
return totalUnderlying();
}
return _cachedTotalUnderlying;
}
function getTotalAndPerPoolUnderlying()
public
view
returns (
uint256 totalUnderlying_,
uint256 totalAllocated_,
uint256[] memory perPoolUnderlying_
)
{
uint256 underlyingPrice_ = controller.priceOracle().getUSDPrice(address(underlying));
return _getTotalAndPerPoolUnderlying(underlyingPrice_, IPoolAdapter.PriceMode.Latest);
}
function isBalanced() external view override returns (bool) {
(
,
uint256 allocatedUnderlying_,
uint256[] memory allocatedPerPool_
) = getTotalAndPerPoolUnderlying();
return _isBalanced(allocatedPerPool_, allocatedUnderlying_);
}
function setRebalancingRewardsEnabled(bool enabled) external override onlyOwner {
require(rebalancingRewardsEnabled != enabled, "same as current");
rebalancingRewardsEnabled = enabled;
emit RebalancingRewardsEnabledSet(enabled);
}
function setEmergencyRebalancingRewardFactor(uint256 factor_) external onlyOwner {
require(factor_ >= _MIN_EMERGENCY_REBALANCING_REWARD_FACTOR, "factor below minimum");
require(factor_ <= _MAX_EMERGENCY_REBALANCING_REWARD_FACTOR, "factor above maximum");
require(factor_ != emergencyRebalancingRewardsFactor, "same as current");
emergencyRebalancingRewardsFactor = factor_;
emit EmergencyRebalancingRewardFactorUpdated(factor_);
}
function _updateAdapterCachedPrices() internal {
address[] memory pools = weightManager.allPools();
uint256 poolsLength_ = pools.length;
for (uint256 i; i < poolsLength_; i++) {
address pool_ = pools[i];
IPoolAdapter poolAdapter = controller.poolAdapterFor(pool_);
poolAdapter.updatePriceCache(pool_);
}
}
function _getTotalAndPerPoolUnderlying(
uint256 underlyingPrice_,
IPoolAdapter.PriceMode priceMode
)
internal
view
returns (
uint256 totalUnderlying_,
uint256 totalAllocated_,
uint256[] memory perPoolUnderlying_
)
{
address[] memory pools = weightManager.allPools();
uint256 poolsLength_ = pools.length;
perPoolUnderlying_ = new uint256[](poolsLength_);
for (uint256 i; i < poolsLength_; i++) {
address pool_ = pools[i];
uint256 poolUnderlying_ = controller.poolAdapterFor(pool_).computePoolValueInUnderlying(
address(this),
pool_,
address(underlying),
underlyingPrice_,
priceMode
);
perPoolUnderlying_[i] = poolUnderlying_;
totalAllocated_ += poolUnderlying_;
}
totalUnderlying_ = totalAllocated_ + underlying.balanceOf(address(this));
}
function _handleRebalancingRewards(
address account,
uint256 allocatedBalanceBefore_,
uint256[] memory allocatedPerPoolBefore,
uint256 allocatedBalanceAfter_,
uint256[] memory allocatedPerPoolAfter
) internal {
if (!rebalancingRewardActive) return;
uint256 deviationBefore = weightManager.computeTotalDeviation(
allocatedBalanceBefore_,
allocatedPerPoolBefore
);
uint256 deviationAfter = weightManager.computeTotalDeviation(
allocatedBalanceAfter_,
allocatedPerPoolAfter
);
controller.inflationManager().handleRebalancingRewards(
account,
deviationBefore,
deviationAfter
);
if (_isBalanced(allocatedPerPoolAfter, allocatedBalanceAfter_)) {
rebalancingRewardActive = false;
}
}
function _min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function _isBalanced(
uint256[] memory allocatedPerPool_,
uint256 totalAllocated_
) internal view returns (bool) {
return weightManager.isBalanced(allocatedPerPool_, totalAllocated_, maxDeviation);
}
function getAllUnderlyingCoins() public view returns (address[] memory) {
address[] memory pools = weightManager.allPools();
uint256 poolsLength_ = pools.length;
address[] memory underlyings_ = new address[](0);
for (uint256 i; i < poolsLength_; i++) {
address pool_ = pools[i];
address[] memory coins = controller.poolAdapterFor(pool_).getAllUnderlyingCoins(pool_);
underlyings_ = underlyings_.concat(coins);
}
return underlyings_.removeDuplicates();
}
function _isPoolDepegged(address pool_) internal view returns (bool) {
address[] memory coins = controller.poolAdapterFor(pool_).getAllUnderlyingCoins(pool_);
for (uint256 i; i < coins.length; i++) {
address coin = coins[i];
if (_isAssetDepegged(coin)) return true;
}
return false;
}
function runSanityChecks() public virtual {}
function _getMaxDeviation() internal view returns (uint256) {
return rebalancingRewardActive ? 0 : maxDeviation;
}
function _updatePriceCache() internal virtual;
function _isAssetDepegged(address asset_) internal view virtual returns (bool);
}
文件 4 的 41:ConicPool.sol
pragma solidity 0.8.17;
import "contracts/BaseConicPool.sol";
contract ConicPool is BaseConicPool {
using EnumerableSet for EnumerableSet.AddressSet;
using ScaledMath for uint256;
uint256 internal constant _DEPEG_UNDERLYING_MULTIPLIER = 2;
constructor(
address _underlying,
IRewardManager _rewardManager,
address _controller,
string memory _lpTokenName,
string memory _symbol,
address _cvx,
address _crv
) BaseConicPool(_underlying, _rewardManager, _controller, _lpTokenName, _symbol, _cvx, _crv) {}
function _updatePriceCache() internal override {
address[] memory underlyings = getAllUnderlyingCoins();
IOracle priceOracle_ = controller.priceOracle();
for (uint256 i; i < underlyings.length; i++) {
address coin = underlyings[i];
_cachedPrices[coin] = priceOracle_.getUSDPrice(coin);
}
}
function _isAssetDepegged(address asset_) internal view override returns (bool) {
uint256 depegThreshold_ = depegThreshold;
if (asset_ == address(underlying)) depegThreshold_ *= _DEPEG_UNDERLYING_MULTIPLIER;
uint256 cachedPrice_ = _cachedPrices[asset_];
uint256 currentPrice_ = controller.priceOracle().getUSDPrice(asset_);
uint256 priceDiff_ = cachedPrice_.absSub(currentPrice_);
uint256 priceDiffPercent_ = priceDiff_.divDown(cachedPrice_);
return priceDiffPercent_ > depegThreshold_;
}
}
文件 5 的 41:ConicPoolWeightManager.sol
pragma solidity 0.8.17;
import "contracts/utils/structs/EnumerableSet.sol";
import "contracts/utils/structs/EnumerableMap.sol";
import "contracts/token/ERC20/utils/SafeERC20.sol";
import "interfaces/pools/IConicPool.sol";
import "interfaces/pools/IConicPoolWeightManager.sol";
import "libraries/ScaledMath.sol";
contract ConicPoolWeightManager is IConicPoolWeightManager {
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableMap for EnumerableMap.AddressToUintMap;
using ScaledMath for uint256;
using SafeERC20 for IERC20;
event CurvePoolAdded(address curvePool_);
event CurvePoolRemoved(address curvePool_);
event NewWeight(address indexed curvePool, uint256 newWeight);
uint256 internal constant _MAX_USD_VALUE_FOR_REMOVING_POOL = 100e18;
uint256 internal constant _MAX_CURVE_POOLS = 10;
IConicPool public immutable conicPool;
IController public immutable controller;
IERC20Metadata public immutable underlying;
EnumerableSet.AddressSet internal _pools;
EnumerableMap.AddressToUintMap internal weights;
modifier onlyController() {
require(msg.sender == address(controller), "not authorized");
_;
}
modifier onlyConicPool() {
require(msg.sender == address(conicPool), "not authorized");
_;
}
constructor(IController _controller, IERC20Metadata _underlying) {
conicPool = IConicPool(msg.sender);
controller = _controller;
underlying = _underlying;
}
function addPool(address _pool) external onlyConicPool {
require(_pools.length() < _MAX_CURVE_POOLS, "max pools reached");
require(!_pools.contains(_pool), "pool already added");
IPoolAdapter poolAdapter = controller.poolAdapterFor(_pool);
bool supported_ = poolAdapter.supportsAsset(_pool, address(underlying));
require(supported_, "coin not in pool");
address lpToken_ = poolAdapter.lpToken(_pool);
require(controller.priceOracle().isTokenSupported(lpToken_), "cannot price LP Token");
if (!weights.contains(_pool)) weights.set(_pool, 0);
require(_pools.add(_pool), "failed to add pool");
emit CurvePoolAdded(_pool);
}
function removePool(address _pool) external onlyConicPool {
require(_pools.contains(_pool), "pool not added");
require(_pools.length() > 1, "cannot remove last pool");
IPoolAdapter poolAdapter = controller.poolAdapterFor(_pool);
uint256 usdValue = poolAdapter.computePoolValueInUSD(address(conicPool), _pool);
require(usdValue < _MAX_USD_VALUE_FOR_REMOVING_POOL, "pool has allocated funds");
uint256 weight = weights.get(_pool);
require(weight == 0, "pool has weight set");
require(_pools.remove(_pool), "pool not removed");
require(weights.remove(_pool), "weight not removed");
emit CurvePoolRemoved(_pool);
}
function updateWeights(PoolWeight[] memory poolWeights) external onlyConicPool {
require(poolWeights.length == _pools.length(), "invalid pool weights");
uint256 total;
address previousPool;
for (uint256 i; i < poolWeights.length; i++) {
address pool_ = poolWeights[i].poolAddress;
require(pool_ > previousPool, "pools not sorted");
require(isRegisteredPool(pool_), "pool is not registered");
uint256 newWeight = poolWeights[i].weight;
weights.set(pool_, newWeight);
emit NewWeight(pool_, newWeight);
total += newWeight;
previousPool = pool_;
}
require(total == ScaledMath.ONE, "weights do not sum to 1");
}
function handleDepeggedCurvePool(address curvePool_) external onlyConicPool {
require(isRegisteredPool(curvePool_), "pool is not registered");
require(weights.get(curvePool_) != 0, "pool weight already 0");
_setWeightToZero(curvePool_);
}
function handleInvalidConvexPid(address curvePool_) external onlyConicPool returns (uint256) {
require(isRegisteredPool(curvePool_), "curve pool not registered");
ICurveRegistryCache registryCache_ = controller.curveRegistryCache();
uint256 pid = registryCache_.getPid(curvePool_);
require(registryCache_.isShutdownPid(pid), "convex pool pid is not shut down");
_setWeightToZero(curvePool_);
return pid;
}
function getDepositPool(
uint256 totalUnderlying_,
uint256[] memory allocatedPerPool,
uint256 maxDeviation
) external view returns (uint256 poolIndex, uint256 maxDepositAmount) {
uint256 poolsCount_ = allocatedPerPool.length;
int256 iPoolIndex = -1;
for (uint256 i; i < poolsCount_; i++) {
address pool_ = _pools.at(i);
uint256 allocatedUnderlying_ = allocatedPerPool[i];
uint256 weight_ = weights.get(pool_);
uint256 targetAllocation_ = totalUnderlying_.mulDown(weight_);
if (allocatedUnderlying_ >= targetAllocation_) continue;
uint256 weightWithDeviation_ = weight_.mulDown(ScaledMath.ONE + maxDeviation);
weightWithDeviation_ = weightWithDeviation_ > ScaledMath.ONE
? ScaledMath.ONE
: weightWithDeviation_;
uint256 maxBalance_ = totalUnderlying_.mulDown(weightWithDeviation_);
uint256 maxDepositAmount_ = maxBalance_ - allocatedUnderlying_;
if (maxDepositAmount_ <= maxDepositAmount) continue;
maxDepositAmount = maxDepositAmount_;
iPoolIndex = int256(i);
}
require(iPoolIndex > -1, "error retrieving deposit pool");
poolIndex = uint256(iPoolIndex);
}
function getWithdrawPool(
uint256 totalUnderlying_,
uint256[] memory allocatedPerPool,
uint256 maxDeviation
) external view returns (uint256 withdrawPoolIndex, uint256 maxWithdrawalAmount) {
uint256 poolsCount_ = allocatedPerPool.length;
int256 iWithdrawPoolIndex = -1;
for (uint256 i; i < poolsCount_; i++) {
address curvePool_ = _pools.at(i);
uint256 weight_ = weights.get(curvePool_);
uint256 allocatedUnderlying_ = allocatedPerPool[i];
if (weight_ == 0) {
uint256 price_ = controller.priceOracle().getUSDPrice(address(underlying));
uint256 allocatedUsd = (price_ * allocatedUnderlying_) /
10 ** underlying.decimals();
if (allocatedUsd >= _MAX_USD_VALUE_FOR_REMOVING_POOL / 2) {
return (uint256(i), allocatedUnderlying_);
}
}
uint256 targetAllocation_ = totalUnderlying_.mulDown(weight_);
if (allocatedUnderlying_ <= targetAllocation_) continue;
uint256 minBalance_ = targetAllocation_ - targetAllocation_.mulDown(maxDeviation);
uint256 maxWithdrawalAmount_ = allocatedUnderlying_ - minBalance_;
if (maxWithdrawalAmount_ <= maxWithdrawalAmount) continue;
maxWithdrawalAmount = maxWithdrawalAmount_;
iWithdrawPoolIndex = int256(i);
}
require(iWithdrawPoolIndex > -1, "error retrieving withdraw pool");
withdrawPoolIndex = uint256(iWithdrawPoolIndex);
}
function allPools() external view returns (address[] memory) {
return _pools.values();
}
function poolsCount() external view returns (uint256) {
return _pools.length();
}
function getPoolAtIndex(uint256 _index) external view returns (address) {
return _pools.at(_index);
}
function isRegisteredPool(address _pool) public view returns (bool) {
return _pools.contains(_pool);
}
function getWeight(address pool) external view returns (uint256) {
return weights.get(pool);
}
function getWeights() external view returns (IConicPool.PoolWeight[] memory) {
uint256 length_ = _pools.length();
IConicPool.PoolWeight[] memory weights_ = new IConicPool.PoolWeight[](length_);
for (uint256 i; i < length_; i++) {
(address pool_, uint256 weight_) = weights.at(i);
weights_[i] = PoolWeight(pool_, weight_);
}
return weights_;
}
function computeTotalDeviation(
uint256 allocatedUnderlying_,
uint256[] memory perPoolAllocations_
) external view returns (uint256) {
uint256 totalDeviation;
for (uint256 i; i < perPoolAllocations_.length; i++) {
uint256 weight = weights.get(_pools.at(i));
uint256 targetAmount = allocatedUnderlying_.mulDown(weight);
totalDeviation += targetAmount.absSub(perPoolAllocations_[i]);
}
return totalDeviation;
}
function isBalanced(
uint256[] memory allocatedPerPool_,
uint256 totalAllocated_,
uint256 maxDeviation
) external view returns (bool) {
if (totalAllocated_ == 0) return true;
for (uint256 i; i < allocatedPerPool_.length; i++) {
uint256 weight_ = weights.get(_pools.at(i));
uint256 currentAllocated_ = allocatedPerPool_[i];
if (weight_ == 0) {
uint256 price_ = controller.priceOracle().getUSDPrice(address(underlying));
uint256 allocatedUsd_ = (price_ * currentAllocated_) / 10 ** underlying.decimals();
if (allocatedUsd_ >= _MAX_USD_VALUE_FOR_REMOVING_POOL / 2) {
return false;
}
continue;
}
uint256 targetAmount = totalAllocated_.mulDown(weight_);
uint256 deviation = targetAmount.absSub(currentAllocated_);
uint256 deviationRatio = deviation.divDown(targetAmount);
if (deviationRatio > maxDeviation) return false;
}
return true;
}
function _setWeightToZero(address zeroedPool) internal {
uint256 weight_ = weights.get(zeroedPool);
if (weight_ == 0) return;
require(weight_ != ScaledMath.ONE, "can't remove last pool");
uint256 scaleUp_ = ScaledMath.ONE.divDown(ScaledMath.ONE - weights.get(zeroedPool));
uint256 curvePoolLength_ = _pools.length();
weights.set(zeroedPool, 0);
emit NewWeight(zeroedPool, 0);
address[] memory nonZeroPools = new address[](curvePoolLength_ - 1);
uint256[] memory nonZeroWeights = new uint256[](curvePoolLength_ - 1);
uint256 nonZeroPoolsCount;
for (uint256 i; i < curvePoolLength_; i++) {
address pool_ = _pools.at(i);
uint256 currentWeight = weights.get(pool_);
if (currentWeight == 0) continue;
nonZeroPools[nonZeroPoolsCount] = pool_;
nonZeroWeights[nonZeroPoolsCount] = currentWeight;
nonZeroPoolsCount++;
}
uint256 totalWeight;
for (uint256 i; i < nonZeroPoolsCount; i++) {
address pool_ = nonZeroPools[i];
uint256 newWeight_ = nonZeroWeights[i].mulDown(scaleUp_);
if (i == nonZeroPoolsCount - 1) {
newWeight_ = ScaledMath.ONE - totalWeight;
}
totalWeight += newWeight_;
weights.set(pool_, newWeight_);
emit NewWeight(pool_, newWeight_);
}
}
}
文件 6 的 41:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 7 的 41:CurvePoolUtils.sol
pragma solidity 0.8.17;
import "interfaces/vendor/ICurvePoolV2.sol";
import "interfaces/vendor/ICurvePoolV1.sol";
import "libraries/ScaledMath.sol";
library CurvePoolUtils {
using ScaledMath for uint256;
error NotWithinThreshold(address pool, uint256 assetA, uint256 assetB);
uint256 internal constant _DEFAULT_IMBALANCE_BUFFER = 30e14;
uint8 internal constant _CURVE_POOL_FEE_DECIMALS = 10;
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) {
toActual = ICurvePoolV2(poolMeta.pool).get_dy(i, j, fromBalance);
} else {
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;
}
}
文件 8 的 41:ERC165Checker.sol
pragma solidity ^0.8.0;
import "contracts/utils/introspection/IERC165.sol";
library ERC165Checker {
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
function supportsERC165(address account) internal view returns (bool) {
return
supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&
!supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);
}
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);
}
function getSupportedInterfaces(
address account,
bytes4[] memory interfaceIds
) internal view returns (bool[] memory) {
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
if (supportsERC165(account)) {
for (uint256 i = 0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
if (!supportsERC165(account)) {
return false;
}
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
return false;
}
}
return true;
}
function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {
bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);
bool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
returnSize := returndatasize()
returnValue := mload(0x00)
}
return success && returnSize >= 0x20 && returnValue > 0;
}
}
文件 9 的 41:ERC20.sol
pragma solidity ^0.8.0;
import "contracts/token/ERC20/IERC20.sol";
import "contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "contracts/utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
文件 10 的 41:EnumerableMap.sol
pragma solidity ^0.8.0;
import "contracts/utils/structs/EnumerableSet.sol";
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
struct Bytes32ToBytes32Map {
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 => bytes32) _values;
}
function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return map._keys.contains(key);
}
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return map._keys.length();
}
function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
bytes32 key = map._keys.at(index);
return (key, map._values[key]);
}
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
bytes32 value = map._values[key];
if (value == bytes32(0)) {
return (contains(map, key), bytes32(0));
} else {
return (true, value);
}
}
function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
return value;
}
function get(
Bytes32ToBytes32Map storage map,
bytes32 key,
string memory errorMessage
) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), errorMessage);
return value;
}
function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
return map._keys.values();
}
struct UintToUintMap {
Bytes32ToBytes32Map _inner;
}
function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}
function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
function length(UintToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), uint256(value));
}
function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, uint256(value));
}
function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key)));
}
function get(UintToUintMap storage map, uint256 key, string memory errorMessage) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key), errorMessage));
}
function keys(UintToUintMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
struct UintToAddressMap {
Bytes32ToBytes32Map _inner;
}
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
function length(UintToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key)))));
}
function get(
UintToAddressMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
}
function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
struct AddressToUintMap {
Bytes32ToBytes32Map _inner;
}
function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
}
function remove(AddressToUintMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
function length(AddressToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (address(uint160(uint256(key))), uint256(value));
}
function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, uint256(value));
}
function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
}
function get(
AddressToUintMap storage map,
address key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
}
function keys(AddressToUintMap storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct Bytes32ToUintMap {
Bytes32ToBytes32Map _inner;
}
function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) {
return set(map._inner, key, bytes32(value));
}
function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (key, uint256(value));
}
function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, key);
return (success, uint256(value));
}
function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
return uint256(get(map._inner, key));
}
function get(
Bytes32ToUintMap storage map,
bytes32 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, key, errorMessage));
}
function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) {
bytes32[] memory store = keys(map._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
}
文件 11 的 41:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[toDeleteIndex] = lastValue;
set._indexes[lastValue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 12 的 41:IBaseRewardPool.sol
pragma solidity 0.8.17;
interface IBaseRewardPool {
function stakeFor(address, uint256) external;
function stake(uint256) external;
function stakeAll() external returns (bool);
function withdraw(uint256 amount, bool claim) external returns (bool);
function withdrawAndUnwrap(uint256 amount, bool claim) external returns (bool);
function earned(address account) external view returns (uint256);
function getReward() external;
function getReward(address _account, bool _claimExtras) external;
function extraRewardsLength() external view returns (uint256);
function extraRewards(uint256 _pid) external view returns (address);
function rewardToken() external view returns (address);
function balanceOf(address account) external view returns (uint256);
}
文件 13 的 41:IBonding.sol
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);
}
文件 14 的 41:IBooster.sol
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);
}
文件 15 的 41:IConicPool.sol
pragma solidity 0.8.17;
import "interfaces/pools/ILpToken.sol";
import "interfaces/pools/IRewardManager.sol";
import "interfaces/IOracle.sol";
import "interfaces/IController.sol";
import "interfaces/IPausable.sol";
import "interfaces/pools/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 maxDeviation() 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);
function totalUnderlying() external view returns (uint256);
function getTotalAndPerPoolUnderlying()
external
view
returns (
uint256 totalUnderlying_,
uint256 totalAllocated_,
uint256[] memory perPoolUnderlying_
);
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;
}
文件 16 的 41:IConicPoolWeightManagement.sol
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);
}
文件 17 的 41:IConicPoolWeightManager.sol
pragma solidity 0.8.17;
import "interfaces/pools/IConicPoolWeightManagement.sol";
interface IConicPoolWeightManager is IConicPoolWeightManagement {
function getDepositPool(
uint256 totalUnderlying_,
uint256[] memory allocatedPerPool,
uint256 maxDeviation
) external view returns (uint256 poolIndex, uint256 maxDepositAmount);
function getWithdrawPool(
uint256 totalUnderlying_,
uint256[] memory allocatedPerPool,
uint256 maxDeviation
) external view returns (uint256 withdrawPoolIndex, uint256 maxWithdrawalAmount);
function computeTotalDeviation(
uint256 allocatedUnderlying_,
uint256[] memory perPoolAllocations_
) external view returns (uint256);
function isBalanced(
uint256[] memory allocatedPerPool_,
uint256 totalAllocated_,
uint256 maxDeviation
) external view returns (bool);
}
文件 18 的 41:IController.sol
pragma solidity 0.8.17;
import "interfaces/pools/IConicPoolWeightManagement.sol";
import "interfaces/pools/IConicPool.sol";
import "interfaces/IGenericOracle.sol";
import "interfaces/tokenomics/IInflationManager.sol";
import "interfaces/tokenomics/ILpTokenStaker.sol";
import "interfaces/tokenomics/IBonding.sol";
import "interfaces/IPoolAdapter.sol";
import "interfaces/IFeeRecipient.sol";
import "interfaces/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;
function inflationManager() external view returns (IInflationManager);
function setInflationManager(address manager) external;
function curveRegistryCache() external view returns (ICurveRegistryCache);
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;
function switchLpTokenStaker(address _lpTokenStaker) external;
function lpTokenStaker() external view returns (ILpTokenStaker);
function bonding() external view returns (IBonding);
function setBonding(address _bonding) external;
function feeRecipient() external view returns (IFeeRecipient);
function setFeeRecipient(address _feeRecipient) external;
function priceOracle() external view returns (IGenericOracle);
function setPriceOracle(address oracle) external;
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;
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;
function isAllowedMultipleDepositsWithdraws(address poolAddress) external view returns (bool);
function setAllowedMultipleDepositsWithdraws(address account, bool allowed) external;
function getMultipleDepositsWithdrawsWhitelist() external view returns (address[] memory);
function setMinimumTaintedTransferAmount(address token, uint256 amount) external;
function getMinimumTaintedTransferAmount(address token) external view returns (uint256);
function MAX_WEIGHT_UPDATE_MIN_DELAY() external view returns (uint256);
function MIN_WEIGHT_UPDATE_MIN_DELAY() external view returns (uint256);
}
文件 19 的 41:ICurvePoolV1.sol
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);
}
文件 20 的 41:ICurvePoolV2.sol
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);
}
文件 21 的 41:ICurveRegistryCache.sol
pragma solidity 0.8.17;
import "interfaces/vendor/IBooster.sol";
import "libraries/CurvePoolUtils.sol";
import "libraries/Types.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 initPool(address pool_, Types.PoolInfo memory poolInfo_) external;
function initPool(address pool_, uint256 pid_, Types.PoolInfo memory poolInfo_) 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);
function getAllUnderlyingCoins(address pool) external view returns (address[] memory);
}
文件 22 的 41:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 23 的 41:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 24 的 41:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "contracts/token/ERC20/IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 25 的 41:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 26 的 41:IFeeRecipient.sol
pragma solidity 0.8.17;
interface IFeeRecipient {
event FeesReceived(address indexed sender, uint256 crvAmount, uint256 cvxAmount);
function receiveFees(uint256 amountCrv, uint256 amountCvx) external;
}
文件 27 的 41:IGenericOracle.sol
pragma solidity 0.8.17;
import "interfaces/IOracle.sol";
interface IGenericOracle is IOracle {
function getOracle(address token) external view returns (IOracle);
function curveLpToUnderlying(
address curveLpToken,
address underlying,
uint256 curveLpAmount
) external view returns (uint256);
function curveLpToUnderlying(
address curveLpToken,
address underlying,
uint256 curveLpAmount,
uint256 underlyingPrice
) external view returns (uint256);
function underlyingToCurveLp(
address underlying,
address curveLpToken,
uint256 underlyingAmount
) external view returns (uint256);
}
文件 28 的 41:IInflationManager.sol
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;
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);
}
文件 29 的 41:ILpToken.sol
pragma solidity 0.8.17;
import "contracts/token/ERC20/extensions/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;
}
文件 30 的 41:ILpTokenStaker.sol
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);
}
文件 31 的 41:IOracle.sol
pragma solidity 0.8.17;
interface IOracle {
event TokenUpdated(address indexed token, address feed, uint256 maxDelay, bool isEthPrice);
function getUSDPrice(address token) external view returns (uint256);
function isTokenSupported(address token) external view returns (bool);
}
文件 32 的 41:IPausable.sol
pragma solidity 0.8.17;
import "contracts/access/Ownable.sol";
import "interfaces/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;
}
文件 33 的 41:IPoolAdapter.sol
pragma solidity 0.8.17;
interface IPoolAdapter {
enum PriceMode {
Latest,
Cached,
Minimum
}
function deposit(address pool, address underlying, uint256 underlyingAmount) external;
function withdraw(address pool, address underlying, uint256 underlyingAmount) external;
function computePoolValueInUSD(
address conicPool,
address pool
) external view returns (uint256 usdAmount);
function updatePriceCache(address pool) external;
function computePoolValueInUSD(
address conicPool,
address pool,
PriceMode priceMode
) external view returns (uint256 usdAmount);
function computePoolValueInUnderlying(
address conicPool,
address pool,
address underlying,
uint256 underlyingPrice
) external view returns (uint256 underlyingAmount);
function computePoolValueInUnderlying(
address conicPool,
address pool,
address underlying,
uint256 underlyingPrice,
PriceMode priceMode
) external view returns (uint256 underlyingAmount);
function claimEarnings(address conicPool, address pool) external;
function lpToken(address pool) external view returns (address);
function supportsAsset(address pool, address asset) external view returns (bool);
function getCRVEarnedOnConvex(
address account,
address curvePool
) external view returns (uint256);
function executeSanityCheck(address pool) external;
function getAllUnderlyingCoins(address pool) external view returns (address[] memory);
}
文件 34 的 41:IRewardManager.sol
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);
}
文件 35 的 41:IWithdrawalProcessor.sol
pragma solidity 0.8.17;
interface IWithdrawalProcessor {
function processWithdrawal(address account, uint256 underlyingAmount) external;
}
文件 36 的 41:LpToken.sol
pragma solidity 0.8.17;
import "contracts/token/ERC20/ERC20.sol";
import "contracts/token/ERC20/utils/SafeERC20.sol";
import "interfaces/IController.sol";
import "interfaces/pools/ILpToken.sol";
contract LpToken is ILpToken, ERC20 {
IController public immutable controller;
address public immutable override minter;
modifier onlyMinter() {
require(msg.sender == minter, "not authorized");
_;
}
mapping(address => uint256) internal _lastEvent;
uint8 private __decimals;
constructor(
address _controller,
address _minter,
uint8 _decimals,
string memory name_,
string memory symbol_
) ERC20(name_, symbol_) {
controller = IController(_controller);
minter = _minter;
__decimals = _decimals;
}
function decimals() public view virtual override(ERC20, IERC20Metadata) returns (uint8) {
return __decimals;
}
function mint(
address _account,
uint256 _amount,
address ubo
) external override onlyMinter returns (uint256) {
_ensureSingleEvent(ubo, _amount);
_mint(_account, _amount);
return _amount;
}
function burn(
address _owner,
uint256 _amount,
address ubo
) external override onlyMinter returns (uint256) {
_ensureSingleEvent(ubo, _amount);
_burn(_owner, _amount);
return _amount;
}
function taint(address from, address to, uint256 amount) external {
require(msg.sender == address(controller.lpTokenStaker()), "not authorized");
_taint(from, to, amount);
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal override {
if (from == address(0) || to == address(0)) return;
address lpTokenStaker = address(controller.lpTokenStaker());
if (from == lpTokenStaker || to == lpTokenStaker) return;
_taint(from, to, amount);
}
function _ensureSingleEvent(address ubo, uint256 amount) internal {
if (
!controller.isAllowedMultipleDepositsWithdraws(ubo) &&
amount > controller.getMinimumTaintedTransferAmount(address(this))
) {
require(_lastEvent[ubo] != block.number, "cannot mint/burn twice in a block");
_lastEvent[ubo] = block.number;
}
}
function _taint(address from, address to, uint256 amount) internal {
if (
from != to &&
_lastEvent[from] == block.number &&
amount > controller.getMinimumTaintedTransferAmount(address(this))
) {
_lastEvent[to] = block.number;
}
}
}
文件 37 的 41:Ownable.sol
pragma solidity ^0.8.0;
import "contracts/utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 38 的 41:Pausable.sol
pragma solidity 0.8.17;
import "contracts/access/Ownable.sol";
import "interfaces/IController.sol";
import "interfaces/IPausable.sol";
abstract contract Pausable is Ownable, IPausable {
uint256 internal constant _MIN_PAUSE_DURATION = 1 hours;
uint256 internal constant _MAX_PAUSE_DURATION = 3 days;
uint256 internal constant _INITIAL_PAUSE_DURATION = 8 hours;
uint256 public pausedUntil;
uint256 public pauseDuration;
IController public immutable controller;
modifier notPaused() {
require(!isPaused(), "paused");
_;
}
constructor(IController _controller) {
controller = _controller;
pauseDuration = _INITIAL_PAUSE_DURATION;
}
function setPauseDuration(uint256 _pauseDuration) external onlyOwner {
require(_pauseDuration >= _MIN_PAUSE_DURATION, "pause duration too short");
require(_pauseDuration <= _MAX_PAUSE_DURATION, "pause duration too long");
pauseDuration = _pauseDuration;
emit PauseDurationSet(pauseDuration);
}
function pause() external {
require(controller.isPauseManager(msg.sender), "not pause manager");
pausedUntil = block.timestamp + pauseDuration;
emit Paused(pausedUntil);
}
function isPaused() public view override returns (bool) {
return pausedUntil >= block.timestamp;
}
}
文件 39 的 41:SafeERC20.sol
pragma solidity ^0.8.0;
import "contracts/token/ERC20/IERC20.sol";
import "contracts/token/ERC20/extensions/IERC20Permit.sol";
import "contracts/utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
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));
}
}
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);
}
}
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");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
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");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 40 的 41:ScaledMath.sol
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;
}
}
文件 41 的 41:Types.sol
pragma solidity 0.8.17;
library Types {
struct Coin {
address coinAddress;
uint8 decimals;
}
struct CliffInfo {
uint256 currentCliff;
bool withinThreshold;
}
struct PoolInfo {
address lpToken;
address basePool;
uint256 assetType;
}
}
{
"compilationTarget": {
"contracts/ConicPool.sol": "ConicPool"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_underlying","type":"address"},{"internalType":"contract IRewardManager","name":"_rewardManager","type":"address"},{"internalType":"address","name":"_controller","type":"address"},{"internalType":"string","name":"_lpTokenName","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_cvx","type":"address"},{"internalType":"address","name":"_crv","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"claimedCrv","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimedCvx","type":"uint256"}],"name":"ClaimedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"curvePool_","type":"address"}],"name":"CurvePoolAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"curvePool_","type":"address"}],"name":"CurvePoolRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newThreshold","type":"uint256"}],"name":"DepegThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpReceived","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"factor","type":"uint256"}],"name":"EmergencyRebalancingRewardFactorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"curvePool_","type":"address"}],"name":"HandledDepeggedCurvePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"curvePool_","type":"address"},{"indexed":false,"internalType":"uint256","name":"pid_","type":"uint256"}],"name":"HandledInvalidConvexPid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxDeviation","type":"uint256"}],"name":"MaxDeviationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"NewMaxIdleCurveLpRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"curvePool","type":"address"},{"indexed":false,"internalType":"uint256","name":"newWeight","type":"uint256"}],"name":"NewWeight","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":"pauseDuration","type":"uint256"}],"name":"PauseDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"pausedUntil","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"RebalancingRewardsEnabledSet","type":"event"},{"anonymous":false,"inputs":[],"name":"Shutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allPools","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cachedTotalUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"computeTotalDeviation","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":"depegThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"underlyingAmount","type":"uint256"},{"internalType":"uint256","name":"minLpReceived","type":"uint256"},{"internalType":"bool","name":"stake","type":"bool"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"underlyingAmount","type":"uint256"},{"internalType":"uint256","name":"minLpReceived","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"underlyingAmount","type":"uint256"},{"internalType":"uint256","name":"minLpReceived","type":"uint256"},{"internalType":"bool","name":"stake","type":"bool"}],"name":"depositFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyRebalancingRewardsFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllUnderlyingCoins","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllocatedUnderlying","outputs":[{"components":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IConicPool.PoolWithAmount[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getPoolAtIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAndPerPoolUnderlying","outputs":[{"internalType":"uint256","name":"totalUnderlying_","type":"uint256"},{"internalType":"uint256","name":"totalAllocated_","type":"uint256"},{"internalType":"uint256[]","name":"perPoolUnderlying_","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"curvePool","type":"address"}],"name":"getWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWeights","outputs":[{"components":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint256","name":"weight","type":"uint256"}],"internalType":"struct IConicPoolWeightManagement.PoolWeight[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"curvePool_","type":"address"}],"name":"handleDepeggedCurvePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"curvePool_","type":"address"}],"name":"handleInvalidConvexPid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isBalanced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"isRegisteredPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpToken","outputs":[{"internalType":"contract ILpToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDeviation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxIdleCurveLpRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pausedUntil","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancingRewardActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancingRewardsActivatedAt","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancingRewardsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancingRewardsFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"removePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardManager","outputs":[{"internalType":"contract IRewardManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"runSanityChecks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"factor_","type":"uint256"}],"name":"setEmergencyRebalancingRewardFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxDeviation_","type":"uint256"}],"name":"setMaxDeviation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxIdleCurveLpRatio_","type":"uint256"}],"name":"setMaxIdleCurveLpRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseDuration","type":"uint256"}],"name":"setPauseDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setRebalancingRewardsEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutdownPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalDeviationAfterWeightUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUnderlying","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":"underlying","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"conicLpAmount","type":"uint256"},{"internalType":"uint256","name":"minUnderlyingReceived","type":"uint256"}],"name":"unstakeAndWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"conicLpAmount","type":"uint256"},{"internalType":"uint256","name":"minUnderlyingReceived","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"unstakeAndWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newDepegThreshold_","type":"uint256"}],"name":"updateDepegThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"updateRewardSpendingApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint256","name":"weight","type":"uint256"}],"internalType":"struct IConicPoolWeightManagement.PoolWeight[]","name":"poolWeights","type":"tuple[]"}],"name":"updateWeights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdExchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weightManager","outputs":[{"internalType":"contract IConicPoolWeightManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"conicLpAmount","type":"uint256"},{"internalType":"uint256","name":"minUnderlyingReceived","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"conicLpAmount","type":"uint256"},{"internalType":"uint256","name":"minUnderlyingReceived","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]