编译器
0.8.17+commit.8df45f5f
文件 1 的 25:ACLNonReentrantTrait.sol
pragma solidity ^0.8.17;
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {IACL} from "@gearbox-protocol/core-v2/contracts/interfaces/IACL.sol";
import {
CallerNotControllerException,
CallerNotPausableAdminException,
CallerNotUnpausableAdminException
} from "../interfaces/IExceptions.sol";
import {ACLTrait} from "./ACLTrait.sol";
import {ReentrancyGuardTrait} from "./ReentrancyGuardTrait.sol";
abstract contract ACLNonReentrantTrait is ACLTrait, Pausable, ReentrancyGuardTrait {
event NewController(address indexed newController);
address public controller;
modifier controllerOnly() {
_ensureCallerIsControllerOrConfigurator();
_;
}
function _ensureCallerIsControllerOrConfigurator() internal view {
if (msg.sender != controller && !_isConfigurator({account: msg.sender})) {
revert CallerNotControllerException();
}
}
modifier pausableAdminsOnly() {
_ensureCallerIsPausableAdmin();
_;
}
function _ensureCallerIsPausableAdmin() internal view {
if (!_isPausableAdmin({account: msg.sender})) {
revert CallerNotPausableAdminException();
}
}
modifier unpausableAdminsOnly() {
_ensureCallerIsUnpausableAdmin();
_;
}
function _ensureCallerIsUnpausableAdmin() internal view {
if (!_isUnpausableAdmin({account: msg.sender})) {
revert CallerNotUnpausableAdminException();
}
}
constructor(address addressProvider) ACLTrait(addressProvider) {
controller = IACL(acl).owner();
}
function pause() external virtual pausableAdminsOnly {
_pause();
}
function unpause() external virtual unpausableAdminsOnly {
_unpause();
}
function setController(address newController) external configuratorOnly {
if (controller == newController) return;
controller = newController;
emit NewController(newController);
}
function _isPausableAdmin(address account) internal view returns (bool) {
return IACL(acl).isPausableAdmin(account);
}
function _isUnpausableAdmin(address account) internal view returns (bool) {
return IACL(acl).isUnpausableAdmin(account);
}
}
文件 2 的 25:ACLTrait.sol
pragma solidity ^0.8.17;
import {IACL} from "@gearbox-protocol/core-v2/contracts/interfaces/IACL.sol";
import {AP_ACL, IAddressProviderV3, NO_VERSION_CONTROL} from "../interfaces/IAddressProviderV3.sol";
import {CallerNotConfiguratorException} from "../interfaces/IExceptions.sol";
import {SanityCheckTrait} from "./SanityCheckTrait.sol";
abstract contract ACLTrait is SanityCheckTrait {
address public immutable acl;
constructor(address addressProvider) nonZeroAddress(addressProvider) {
acl = IAddressProviderV3(addressProvider).getAddressOrRevert(AP_ACL, NO_VERSION_CONTROL);
}
modifier configuratorOnly() {
_ensureCallerIsConfigurator();
_;
}
function _ensureCallerIsConfigurator() internal view {
if (!_isConfigurator({account: msg.sender})) {
revert CallerNotConfiguratorException();
}
}
function _isConfigurator(address account) internal view returns (bool) {
return IACL(acl).isConfigurator(account);
}
}
文件 3 的 25: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);
}
}
}
文件 4 的 25:Constants.sol
pragma solidity ^0.8.10;
uint256 constant WAD = 1e18;
uint256 constant RAY = 1e27;
uint16 constant PERCENTAGE_FACTOR = 1e4;
uint256 constant ALLOWANCE_THRESHOLD = type(uint96).max >> 3;
uint16 constant DEFAULT_FEE_INTEREST = 50_00;
uint16 constant DEFAULT_FEE_LIQUIDATION = 1_50;
uint16 constant DEFAULT_LIQUIDATION_PREMIUM = 4_00;
uint16 constant DEFAULT_FEE_LIQUIDATION_EXPIRED = 1_00;
uint16 constant DEFAULT_LIQUIDATION_PREMIUM_EXPIRED = 2_00;
uint16 constant DEFAULT_LIMIT_PER_BLOCK_MULTIPLIER = 2;
uint256 constant SECONDS_PER_YEAR = 365 days;
uint256 constant SECONDS_PER_ONE_AND_HALF_YEAR = (SECONDS_PER_YEAR * 3) / 2;
uint8 constant LEVERAGE_DECIMALS = 100;
uint8 constant MAX_WITHDRAW_FEE = 100;
uint256 constant EXACT_INPUT = 1;
uint256 constant EXACT_OUTPUT = 2;
address constant UNIVERSAL_CONTRACT = 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC;
文件 5 的 25: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;
}
}
文件 6 的 25:CurveStableLPPriceFeed.sol
pragma solidity ^0.8.17;
import {LPPriceFeed} from "../LPPriceFeed.sol";
import {PriceFeedParams} from "../PriceFeedParams.sol";
import {ICurvePool} from "../../interfaces/curve/ICurvePool.sol";
import {PriceFeedType} from "@gearbox-protocol/sdk-gov/contracts/PriceFeedType.sol";
import {WAD} from "@gearbox-protocol/core-v2/contracts/libraries/Constants.sol";
contract CurveStableLPPriceFeed is LPPriceFeed {
uint256 public constant override version = 3_00;
PriceFeedType public immutable override priceFeedType;
uint16 public immutable nCoins;
address public immutable priceFeed0;
uint32 public immutable stalenessPeriod0;
bool public immutable skipCheck0;
address public immutable priceFeed1;
uint32 public immutable stalenessPeriod1;
bool public immutable skipCheck1;
address public immutable priceFeed2;
uint32 public immutable stalenessPeriod2;
bool public immutable skipCheck2;
address public immutable priceFeed3;
uint32 public immutable stalenessPeriod3;
bool public immutable skipCheck3;
constructor(
address addressProvider,
uint256 lowerBound,
address _token,
address _pool,
PriceFeedParams[4] memory priceFeeds
)
LPPriceFeed(addressProvider, _token, _pool)
nonZeroAddress(priceFeeds[0].priceFeed)
nonZeroAddress(priceFeeds[1].priceFeed)
{
priceFeed0 = priceFeeds[0].priceFeed;
priceFeed1 = priceFeeds[1].priceFeed;
priceFeed2 = priceFeeds[2].priceFeed;
priceFeed3 = priceFeeds[3].priceFeed;
stalenessPeriod0 = priceFeeds[0].stalenessPeriod;
stalenessPeriod1 = priceFeeds[1].stalenessPeriod;
stalenessPeriod2 = priceFeeds[2].stalenessPeriod;
stalenessPeriod3 = priceFeeds[3].stalenessPeriod;
nCoins = priceFeed2 == address(0) ? 2 : (priceFeed3 == address(0) ? 3 : 4);
skipCheck0 = _validatePriceFeed(priceFeed0, stalenessPeriod0);
skipCheck1 = _validatePriceFeed(priceFeed1, stalenessPeriod1);
skipCheck2 = nCoins > 2 ? _validatePriceFeed(priceFeed2, stalenessPeriod2) : false;
skipCheck3 = nCoins > 3 ? _validatePriceFeed(priceFeed3, stalenessPeriod3) : false;
priceFeedType = nCoins == 2
? PriceFeedType.CURVE_2LP_ORACLE
: (nCoins == 3 ? PriceFeedType.CURVE_3LP_ORACLE : PriceFeedType.CURVE_4LP_ORACLE);
_setLimiter(lowerBound);
}
function getAggregatePrice() public view override returns (int256 answer) {
answer = _getValidatedPrice(priceFeed0, stalenessPeriod0, skipCheck0);
int256 answer2 = _getValidatedPrice(priceFeed1, stalenessPeriod1, skipCheck1);
if (answer2 < answer) answer = answer2;
if (nCoins > 2) {
answer2 = _getValidatedPrice(priceFeed2, stalenessPeriod2, skipCheck2);
if (answer2 < answer) answer = answer2;
if (nCoins > 3) {
answer2 = _getValidatedPrice(priceFeed3, stalenessPeriod3, skipCheck3);
if (answer2 < answer) answer = answer2;
}
}
}
function getLPExchangeRate() public view override returns (uint256) {
return uint256(ICurvePool(lpContract).get_virtual_price());
}
function getScale() public pure override returns (uint256) {
return WAD;
}
}
文件 7 的 25:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../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 {}
}
文件 8 的 25:IACL.sol
pragma solidity ^0.8.10;
import { IVersion } from "./IVersion.sol";
interface IACLExceptions {
error AddressNotPausableAdminException(address addr);
error AddressNotUnpausableAdminException(address addr);
}
interface IACLEvents {
event PausableAdminAdded(address indexed newAdmin);
event PausableAdminRemoved(address indexed admin);
event UnpausableAdminAdded(address indexed newAdmin);
event UnpausableAdminRemoved(address indexed admin);
}
interface IACL is IACLEvents, IACLExceptions, IVersion {
function isPausableAdmin(address addr) external view returns (bool);
function isUnpausableAdmin(address addr) external view returns (bool);
function isConfigurator(address account) external view returns (bool);
function owner() external view returns (address);
}
文件 9 的 25:IAddressProviderV3.sol
pragma solidity ^0.8.17;
import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol";
uint256 constant NO_VERSION_CONTROL = 0;
bytes32 constant AP_CONTRACTS_REGISTER = "CONTRACTS_REGISTER";
bytes32 constant AP_ACL = "ACL";
bytes32 constant AP_PRICE_ORACLE = "PRICE_ORACLE";
bytes32 constant AP_ACCOUNT_FACTORY = "ACCOUNT_FACTORY";
bytes32 constant AP_DATA_COMPRESSOR = "DATA_COMPRESSOR";
bytes32 constant AP_TREASURY = "TREASURY";
bytes32 constant AP_GEAR_TOKEN = "GEAR_TOKEN";
bytes32 constant AP_WETH_TOKEN = "WETH_TOKEN";
bytes32 constant AP_WETH_GATEWAY = "WETH_GATEWAY";
bytes32 constant AP_ROUTER = "ROUTER";
bytes32 constant AP_BOT_LIST = "BOT_LIST";
bytes32 constant AP_GEAR_STAKING = "GEAR_STAKING";
bytes32 constant AP_ZAPPER_REGISTER = "ZAPPER_REGISTER";
interface IAddressProviderV3Events {
event SetAddress(bytes32 indexed key, address indexed value, uint256 indexed version);
}
interface IAddressProviderV3 is IAddressProviderV3Events, IVersion {
function addresses(bytes32 key, uint256 _version) external view returns (address);
function getAddressOrRevert(bytes32 key, uint256 _version) external view returns (address result);
function setAddress(bytes32 key, address value, bool saveVersion) external;
}
文件 10 的 25:ICurvePool.sol
pragma solidity ^0.8.17;
interface ICurvePool {
function get_virtual_price() external view returns (uint256);
function price_oracle() external view returns (uint256);
}
文件 11 的 25: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);
}
文件 12 的 25:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../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);
}
文件 13 的 25:IExceptions.sol
pragma solidity ^0.8.17;
error ZeroAddressException();
error AmountCantBeZeroException();
error IncorrectParameterException();
error InsufficientBalanceException();
error ValueOutOfRangeException();
error ReceiveIsNotAllowedException();
error AddressIsNotContractException(address);
error TokenNotAllowedException();
error TokenAlreadyAddedException();
error TokenIsNotQuotedException();
error TargetContractNotAllowedException();
error NotImplementedException();
error RegisteredCreditManagerOnlyException();
error RegisteredPoolOnlyException();
error AddressNotFoundException();
error IncompatibleCreditManagerException();
error IncompatibleSuccessorException();
error VotingContractNotAllowedException();
error InsufficientVotesException();
error BorrowingMoreThanU2ForbiddenException();
error CreditManagerCantBorrowException();
error IncompatiblePoolQuotaKeeperException();
error QuotaIsOutOfBoundsException();
error NotEnoughCollateralException();
error AllowanceFailedException();
error CreditAccountDoesNotExistException();
error TooManyTokensException();
error TooManyEnabledTokensException();
error ActiveCreditAccountNotSetException();
error DebtUpdatedTwiceInOneBlockException();
error DebtToZeroWithActiveQuotasException();
error UpdateQuotaOnZeroDebtAccountException();
error CloseAccountWithNonZeroDebtException();
error InsufficientRemainingFundsException();
error ActiveCreditAccountOverridenException();
error IncorrectTokenContractException();
error IncorrectLiquidationThresholdException();
error IncorrectLimitsException();
error IncorrectExpirationDateException();
error IncompatibleContractException();
error AdapterIsNotRegisteredException();
error ForbiddenInWhitelistedModeException();
error NotAllowedWhenNotExpirableException();
error UnknownMethodException();
error CloseAccountWithEnabledTokensException();
error CreditAccountNotLiquidatableException();
error BorrowedBlockLimitException();
error BorrowAmountOutOfLimitsException();
error NotAllowedAfterExpirationException();
error ExpectedBalancesAlreadySetException();
error ExpectedBalancesNotSetException();
error BalanceLessThanExpectedException();
error ForbiddenTokensException();
error ForbiddenTokenEnabledException();
error ForbiddenTokenBalanceIncreasedException();
error RemainingTokenBalanceIncreasedException();
error NotApprovedBotException();
error NoPermissionException(uint256 permission);
error UnexpectedPermissionsException();
error CustomHealthFactorTooLowException();
error InvalidCollateralHintException();
error CallerNotCreditAccountOwnerException();
error CallerNotConfiguratorException();
error CallerNotAccountFactoryException();
error CallerNotCreditManagerException();
error CallerNotCreditFacadeException();
error CallerNotControllerException();
error CallerNotPausableAdminException();
error CallerNotUnpausableAdminException();
error CallerNotGaugeException();
error CallerNotPoolQuotaKeeperException();
error CallerNotVoterException();
error CallerNotAdapterException();
error CallerNotMigratorException();
error CallerNotExecutorException();
error CallerNotVetoAdminException();
error ParameterChecksFailedException();
error TxNotQueuedException();
error TxExecutedOutsideTimeWindowException();
error TxExecutionRevertedException();
error ParameterChangedAfterQueuedTxException();
error InvalidBotException();
error MasterCreditAccountAlreadyDeployedException();
error CreditAccountIsInUseException();
error IncorrectPriceFeedException();
error PriceFeedDoesNotExistException();
error IncorrectPriceException();
error StalePriceException();
文件 14 的 25:ILPPriceFeed.sol
pragma solidity ^0.8.17;
import {IPriceFeed} from "@gearbox-protocol/core-v2/contracts/interfaces/IPriceFeed.sol";
interface ILPPriceFeedEvents {
event SetBounds(uint256 lowerBound, uint256 upperBound);
event SetUpdateBoundsAllowed(bool allowed);
}
interface ILPPriceFeedExceptions {
error LowerBoundCantBeZeroException();
error ExchangeRateOutOfBoundsException();
error UpdateBoundsNotAllowedException();
error UpdateBoundsBeforeCooldownException();
error ReserveFeedMustNotBeSelfException();
}
interface ILPPriceFeed is IPriceFeed, ILPPriceFeedEvents, ILPPriceFeedExceptions {
function priceOracle() external view returns (address);
function lpToken() external view returns (address);
function lpContract() external view returns (address);
function lowerBound() external view returns (uint256);
function upperBound() external view returns (uint256);
function updateBoundsAllowed() external view returns (bool);
function lastBoundsUpdate() external view returns (uint40);
function getAggregatePrice() external view returns (int256 answer);
function getLPExchangeRate() external view returns (uint256 exchangeRate);
function getScale() external view returns (uint256 scale);
function allowBoundsUpdate() external;
function forbidBoundsUpdate() external;
function setLimiter(uint256 newLowerBound) external;
function updateBounds(bytes calldata updateData) external;
}
文件 15 的 25:IPriceFeed.sol
pragma solidity ^0.8.0;
import { PriceFeedType } from "@gearbox-protocol/sdk-gov/contracts/PriceFeedType.sol";
interface IPriceFeed {
function priceFeedType() external view returns (PriceFeedType);
function version() external view returns (uint256);
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function skipPriceCheck() external view returns (bool);
function latestRoundData()
external
view
returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80);
}
interface IUpdatablePriceFeed is IPriceFeed {
function updatable() external view returns (bool);
function updatePrice(bytes calldata data) external;
}
文件 16 的 25:IPriceOracleBase.sol
pragma solidity ^0.8.10;
import { IVersion } from "./IVersion.sol";
interface IPriceOracleBase is IVersion {
function getPrice(address token) external view returns (uint256);
function convertToUSD(
uint256 amount,
address token
) external view returns (uint256);
function convertFromUSD(
uint256 amount,
address token
) external view returns (uint256);
function convert(
uint256 amount,
address tokenFrom,
address tokenTo
) external view returns (uint256);
function priceFeeds(
address token
) external view returns (address priceFeed);
}
文件 17 的 25:IPriceOracleV3.sol
pragma solidity ^0.8.17;
import {IPriceOracleBase} from "@gearbox-protocol/core-v2/contracts/interfaces/IPriceOracleBase.sol";
struct PriceFeedParams {
address priceFeed;
uint32 stalenessPeriod;
bool skipCheck;
uint8 decimals;
bool useReserve;
bool trusted;
}
interface IPriceOracleV3Events {
event SetPriceFeed(
address indexed token, address indexed priceFeed, uint32 stalenessPeriod, bool skipCheck, bool trusted
);
event SetReservePriceFeed(address indexed token, address indexed priceFeed, uint32 stalenessPeriod, bool skipCheck);
event SetReservePriceFeedStatus(address indexed token, bool active);
}
interface IPriceOracleV3 is IPriceOracleBase, IPriceOracleV3Events {
function getPriceSafe(address token) external view returns (uint256);
function getPriceRaw(address token, bool reserve) external view returns (uint256);
function priceFeedsRaw(address token, bool reserve) external view returns (address);
function priceFeedParams(address token)
external
view
returns (address priceFeed, uint32 stalenessPeriod, bool skipCheck, uint8 decimals, bool trusted);
function safeConvertToUSD(uint256 amount, address token) external view returns (uint256);
function setPriceFeed(address token, address priceFeed, uint32 stalenessPeriod, bool trusted) external;
function setReservePriceFeed(address token, address priceFeed, uint32 stalenessPeriod) external;
function setReservePriceFeedStatus(address token, bool active) external;
}
文件 18 的 25:IVersion.sol
pragma solidity ^0.8.10;
interface IVersion {
function version() external view returns (uint256);
}
文件 19 的 25:LPPriceFeed.sol
pragma solidity ^0.8.17;
import {ILPPriceFeed} from "../interfaces/ILPPriceFeed.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {PERCENTAGE_FACTOR} from "@gearbox-protocol/core-v2/contracts/libraries/Constants.sol";
import {ACLNonReentrantTrait} from "@gearbox-protocol/core-v3/contracts/traits/ACLNonReentrantTrait.sol";
import {PriceFeedValidationTrait} from "@gearbox-protocol/core-v3/contracts/traits/PriceFeedValidationTrait.sol";
import {IPriceOracleV3} from "@gearbox-protocol/core-v3/contracts/interfaces/IPriceOracleV3.sol";
import {IUpdatablePriceFeed} from "@gearbox-protocol/core-v2/contracts/interfaces/IPriceFeed.sol";
import {
IAddressProviderV3, AP_PRICE_ORACLE
} from "@gearbox-protocol/core-v3/contracts/interfaces/IAddressProviderV3.sol";
uint256 constant WINDOW_SIZE = 200;
uint256 constant BUFFER_SIZE = 100;
uint256 constant UPDATE_BOUNDS_COOLDOWN = 1 days;
abstract contract LPPriceFeed is ILPPriceFeed, ACLNonReentrantTrait, PriceFeedValidationTrait {
uint8 public constant override decimals = 8;
bool public constant override skipPriceCheck = true;
address public immutable override priceOracle;
address public immutable override lpToken;
address public immutable override lpContract;
uint256 public override lowerBound;
bool public override updateBoundsAllowed;
uint40 public override lastBoundsUpdate;
constructor(address _addressProvider, address _lpToken, address _lpContract)
ACLNonReentrantTrait(_addressProvider)
nonZeroAddress(_lpToken)
nonZeroAddress(_lpContract)
{
priceOracle = IAddressProviderV3(_addressProvider).getAddressOrRevert(AP_PRICE_ORACLE, 3_00);
lpToken = _lpToken;
lpContract = _lpContract;
}
function description() external view override returns (string memory) {
return string(abi.encodePacked(ERC20(lpToken).symbol(), " / USD price feed"));
}
function latestRoundData() external view override returns (uint80, int256 answer, uint256, uint256, uint80) {
uint256 exchangeRate = getLPExchangeRate();
uint256 lb = lowerBound;
if (exchangeRate < lb) revert ExchangeRateOutOfBoundsException();
uint256 ub = _calcUpperBound(lb);
if (exchangeRate > ub) exchangeRate = ub;
answer = int256((exchangeRate * uint256(getAggregatePrice())) / getScale());
return (0, answer, 0, 0, 0);
}
function upperBound() external view returns (uint256) {
return _calcUpperBound(lowerBound);
}
function getAggregatePrice() public view virtual override returns (int256 answer);
function getLPExchangeRate() public view virtual override returns (uint256 exchangeRate);
function getScale() public view virtual override returns (uint256 scale);
function allowBoundsUpdate()
external
override
configuratorOnly
{
if (updateBoundsAllowed) return;
updateBoundsAllowed = true;
emit SetUpdateBoundsAllowed(true);
}
function forbidBoundsUpdate()
external
override
controllerOnly
{
if (!updateBoundsAllowed) return;
updateBoundsAllowed = false;
emit SetUpdateBoundsAllowed(false);
}
function setLimiter(uint256 newLowerBound)
external
override
controllerOnly
{
_setLimiter(newLowerBound);
}
function updateBounds(bytes calldata updateData) external override {
if (!updateBoundsAllowed) revert UpdateBoundsNotAllowedException();
if (block.timestamp < lastBoundsUpdate + UPDATE_BOUNDS_COOLDOWN) revert UpdateBoundsBeforeCooldownException();
lastBoundsUpdate = uint40(block.timestamp);
address reserveFeed = IPriceOracleV3(priceOracle).priceFeedsRaw({token: lpToken, reserve: true});
if (reserveFeed == address(this)) revert ReserveFeedMustNotBeSelfException();
try IUpdatablePriceFeed(reserveFeed).updatable() returns (bool updatable) {
if (updatable) IUpdatablePriceFeed(reserveFeed).updatePrice(updateData);
} catch {}
uint256 reserveAnswer = IPriceOracleV3(priceOracle).getPriceRaw({token: lpToken, reserve: true});
uint256 reserveExchangeRate = uint256(reserveAnswer * getScale() / uint256(getAggregatePrice()));
_ensureValueInBounds(reserveExchangeRate, lowerBound);
_setLimiter(_calcLowerBound(reserveExchangeRate));
}
function _setLimiter(uint256 lower) internal {
if (lower == 0) revert LowerBoundCantBeZeroException();
uint256 upper = _ensureValueInBounds(getLPExchangeRate(), lower);
lowerBound = lower;
emit SetBounds(lower, upper);
}
function _calcUpperBound(uint256 _lowerBound) internal pure returns (uint256) {
return _lowerBound * (PERCENTAGE_FACTOR + WINDOW_SIZE) / PERCENTAGE_FACTOR;
}
function _calcLowerBound(uint256 exchangeRate) internal pure returns (uint256) {
return exchangeRate * (PERCENTAGE_FACTOR - BUFFER_SIZE) / PERCENTAGE_FACTOR;
}
function _ensureValueInBounds(uint256 value, uint256 lower) internal pure returns (uint256 upper) {
if (value < lower) revert ExchangeRateOutOfBoundsException();
upper = _calcUpperBound(lower);
if (value > upper) revert ExchangeRateOutOfBoundsException();
}
}
文件 20 的 25:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 21 的 25:PriceFeedParams.sol
pragma solidity ^0.8.17;
struct PriceFeedParams {
address priceFeed;
uint32 stalenessPeriod;
}
文件 22 的 25:PriceFeedType.sol
pragma solidity ^0.8.17;
enum PriceFeedType {
CHAINLINK_ORACLE,
YEARN_ORACLE,
CURVE_2LP_ORACLE,
CURVE_3LP_ORACLE,
CURVE_4LP_ORACLE,
ZERO_ORACLE,
WSTETH_ORACLE,
BOUNDED_ORACLE,
COMPOSITE_ORACLE,
WRAPPED_AAVE_V2_ORACLE,
COMPOUND_V2_ORACLE,
BALANCER_STABLE_LP_ORACLE,
BALANCER_WEIGHTED_LP_ORACLE,
CURVE_CRYPTO_ORACLE,
THE_SAME_AS,
REDSTONE_ORACLE,
ERC4626_VAULT_ORACLE,
NETWORK_DEPENDENT,
CURVE_USD_ORACLE,
PYTH_ORACLE,
MELLOW_LRT_ORACLE,
PENDLE_PT_TWAP_ORACLE
}
文件 23 的 25:PriceFeedValidationTrait.sol
pragma solidity ^0.8.17;
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {
AddressIsNotContractException,
IncorrectParameterException,
IncorrectPriceException,
IncorrectPriceFeedException,
PriceFeedDoesNotExistException,
StalePriceException
} from "../interfaces/IExceptions.sol";
import {IPriceFeed, IUpdatablePriceFeed} from "@gearbox-protocol/core-v2/contracts/interfaces/IPriceFeed.sol";
abstract contract PriceFeedValidationTrait {
using Address for address;
function _checkAnswer(int256 price, uint256 updatedAt, uint32 stalenessPeriod) internal view {
if (price <= 0) revert IncorrectPriceException();
if (block.timestamp >= updatedAt + stalenessPeriod) revert StalePriceException();
}
function _validatePriceFeed(address priceFeed, uint32 stalenessPeriod) internal view returns (bool skipCheck) {
if (!priceFeed.isContract()) revert AddressIsNotContractException(priceFeed);
try IPriceFeed(priceFeed).decimals() returns (uint8 _decimals) {
if (_decimals != 8) revert IncorrectPriceFeedException();
} catch {
revert IncorrectPriceFeedException();
}
try IPriceFeed(priceFeed).skipPriceCheck() returns (bool _skipCheck) {
skipCheck = _skipCheck;
} catch {}
try IPriceFeed(priceFeed).latestRoundData() returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80)
{
if (skipCheck) {
if (stalenessPeriod != 0) revert IncorrectParameterException();
} else {
if (stalenessPeriod == 0) revert IncorrectParameterException();
bool updatable;
try IUpdatablePriceFeed(priceFeed).updatable() returns (bool _updatable) {
updatable = _updatable;
} catch {}
if (!updatable) _checkAnswer(answer, updatedAt, stalenessPeriod);
}
} catch {
revert IncorrectPriceFeedException();
}
}
function _getValidatedPrice(address priceFeed, uint32 stalenessPeriod, bool skipCheck)
internal
view
returns (int256 answer)
{
uint256 updatedAt;
(, answer,, updatedAt,) = IPriceFeed(priceFeed).latestRoundData();
if (!skipCheck) _checkAnswer(answer, updatedAt, stalenessPeriod);
}
}
文件 24 的 25:ReentrancyGuardTrait.sol
pragma solidity ^0.8.17;
uint8 constant NOT_ENTERED = 1;
uint8 constant ENTERED = 2;
abstract contract ReentrancyGuardTrait {
uint8 internal _reentrancyStatus = NOT_ENTERED;
modifier nonReentrant() {
_ensureNotEntered();
_reentrancyStatus = ENTERED;
_;
_reentrancyStatus = NOT_ENTERED;
}
function _ensureNotEntered() internal view {
require(_reentrancyStatus != ENTERED, "ReentrancyGuard: reentrant call");
}
}
文件 25 的 25:SanityCheckTrait.sol
pragma solidity ^0.8.17;
import {ZeroAddressException} from "../interfaces/IExceptions.sol";
abstract contract SanityCheckTrait {
modifier nonZeroAddress(address addr) {
_revertIfZeroAddress(addr);
_;
}
function _revertIfZeroAddress(address addr) private pure {
if (addr == address(0)) revert ZeroAddressException();
}
}
{
"compilationTarget": {
"node_modules/@gearbox-protocol/oracles-v3/contracts/oracles/curve/CurveStableLPPriceFeed.sol": "CurveStableLPPriceFeed"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": [
":@1inch/=node_modules/@1inch/",
":@arbitrum/=node_modules/@arbitrum/",
":@chainlink/=node_modules/@chainlink/",
":@eth-optimism/=node_modules/@eth-optimism/",
":@gearbox-protocol/=node_modules/@gearbox-protocol/",
":@openzeppelin/=node_modules/@openzeppelin/",
":@redstone-finance/=node_modules/@redstone-finance/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":eth-gas-reporter/=node_modules/eth-gas-reporter/",
":forge-std/=lib/forge-std/src/"
]
}
[{"inputs":[{"internalType":"address","name":"addressProvider","type":"address"},{"internalType":"uint256","name":"lowerBound","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_pool","type":"address"},{"components":[{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint32","name":"stalenessPeriod","type":"uint32"}],"internalType":"struct PriceFeedParams[4]","name":"priceFeeds","type":"tuple[4]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"AddressIsNotContractException","type":"error"},{"inputs":[],"name":"CallerNotConfiguratorException","type":"error"},{"inputs":[],"name":"CallerNotControllerException","type":"error"},{"inputs":[],"name":"CallerNotPausableAdminException","type":"error"},{"inputs":[],"name":"CallerNotUnpausableAdminException","type":"error"},{"inputs":[],"name":"ExchangeRateOutOfBoundsException","type":"error"},{"inputs":[],"name":"IncorrectParameterException","type":"error"},{"inputs":[],"name":"IncorrectPriceException","type":"error"},{"inputs":[],"name":"IncorrectPriceFeedException","type":"error"},{"inputs":[],"name":"LowerBoundCantBeZeroException","type":"error"},{"inputs":[],"name":"ReserveFeedMustNotBeSelfException","type":"error"},{"inputs":[],"name":"StalePriceException","type":"error"},{"inputs":[],"name":"UpdateBoundsBeforeCooldownException","type":"error"},{"inputs":[],"name":"UpdateBoundsNotAllowedException","type":"error"},{"inputs":[],"name":"ZeroAddressException","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newController","type":"address"}],"name":"NewController","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lowerBound","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"upperBound","type":"uint256"}],"name":"SetBounds","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"SetUpdateBoundsAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"acl","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowBoundsUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"forbidBoundsUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAggregatePrice","outputs":[{"internalType":"int256","name":"answer","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLPExchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"lastBoundsUpdate","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint80","name":"","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lowerBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nCoins","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedType","outputs":[{"internalType":"enum PriceFeedType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newController","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLowerBound","type":"uint256"}],"name":"setLimiter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"skipCheck0","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skipCheck1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skipCheck2","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skipCheck3","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skipPriceCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stalenessPeriod0","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stalenessPeriod1","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stalenessPeriod2","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stalenessPeriod3","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"updateData","type":"bytes"}],"name":"updateBounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateBoundsAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upperBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]