Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
9779955 | 21 hrs ago | Contract Creation | 0 S |
Loading...
Loading
Contract Name:
PriceOracleV3
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import { AddressIsNotContractException, IncorrectTokenContractException, PriceFeedDoesNotExistException } from "../interfaces/IExceptions.sol"; import {IPriceOracleV3, PriceFeedParams} from "../interfaces/IPriceOracleV3.sol"; import {ACLNonReentrantTrait} from "../traits/ACLNonReentrantTrait.sol"; import {PriceFeedValidationTrait} from "../traits/PriceFeedValidationTrait.sol"; /// @title Price oracle V3 /// @notice Acts as router that dispatches calls to corresponding price feeds. /// Underlying price feeds can be arbitrary, but they must adhere to Chainlink interface, /// e.g., implement `latestRoundData` and always return answers with 8 decimals. /// They may also implement their own price checks, in which case they may incidcate it /// to the price oracle by returning `skipPriceCheck = true`. /// @notice Price oracle also allows to set a reserve price feed for a token, that can be activated /// in case the main one becomes stale or starts returning wrong values. /// One should not expect the reserve price feed to always differ from the main one, although /// most often that would be the case. /// @notice Price oracle additionaly provides "safe" conversion functions, which use minimum of main /// and reserve feed prices (the latter is assumed to be zero if reserve feed is not set). /// There are also trusted price feeds, for which safe prices are simply main feed prices. contract PriceOracleV3 is ACLNonReentrantTrait, PriceFeedValidationTrait, IPriceOracleV3 { /// @notice Contract version uint256 public constant override version = 3_00; /// @dev Mapping from token address to price feed parameters mapping(address => PriceFeedParams) internal _priceFeedsParams; /// @notice Constructor /// @param addressProvider Address provider contract address constructor(address addressProvider) ACLNonReentrantTrait(addressProvider) {} /// @notice Returns `token`'s price in USD (with 8 decimals) from the currently active price feed function getPrice(address token) external view override returns (uint256 price) { (price,) = _getPrice(token); } /// @notice Returns `token`'s safe price in USD (with 8 decimals) function getPriceSafe(address token) external view override returns (uint256 price) { (price,) = _getPriceSafe(token); } /// @notice Returns `token`'s price in USD (with 8 decimals) from the specified price feed function getPriceRaw(address token, bool reserve) external view returns (uint256 price) { (price,) = _getPriceRaw(token, reserve); } /// @notice Converts `amount` of `token` into USD amount (with 8 decimals) function convertToUSD(uint256 amount, address token) external view override returns (uint256) { (uint256 price, uint256 scale) = _getPrice(token); return amount * price / scale; // U:[PO-9] } /// @notice Converts `amount` of USD (with 8 decimals) into `token` amount function convertFromUSD(uint256 amount, address token) external view override returns (uint256) { (uint256 price, uint256 scale) = _getPrice(token); return amount * scale / price; // U:[PO-9] } /// @notice Converts `amount` of `tokenFrom` into `tokenTo` amount function convert(uint256 amount, address tokenFrom, address tokenTo) external view override returns (uint256) { (uint256 priceFrom, uint256 scaleFrom) = _getPrice(tokenFrom); (uint256 priceTo, uint256 scaleTo) = _getPrice(tokenTo); return amount * priceFrom * scaleTo / (priceTo * scaleFrom); // U:[PO-10] } /// @notice Converts `amount` of `token` into USD amount (with 8 decimals) using safe price function safeConvertToUSD(uint256 amount, address token) external view override returns (uint256) { (uint256 price, uint256 scale) = _getPriceSafe(token); return amount * price / scale; // U:[PO-11] } /// @notice Returns the price feed for `token` or reverts if price feed is not set function priceFeeds(address token) external view override returns (address priceFeed) { (priceFeed,,,,) = priceFeedParams(token); // U:[PO-8] } /// @notice Returns the specified price feed for `token` function priceFeedsRaw(address token, bool reserve) external view override returns (address priceFeed) { (priceFeed,,,,,) = _getPriceFeedParams(reserve ? _getTokenReserveKey(token) : token); } /// @notice Returns currently active price feed parameters for `token` or reverts if price feed is not set function priceFeedParams(address token) public view override returns (address priceFeed, uint32 stalenessPeriod, bool skipCheck, uint8 decimals, bool trusted) { bool useReserve; (priceFeed, stalenessPeriod, skipCheck, decimals, useReserve, trusted) = _getPriceFeedParams(token); if (useReserve) { (priceFeed, stalenessPeriod, skipCheck, decimals,, trusted) = _getPriceFeedParams(_getTokenReserveKey(token)); } } // --------- // // INTERNALS // // --------- // /// @dev Returns `token`'s price and scale from the currently active price feed function _getPrice(address token) internal view returns (uint256 price, uint256 scale) { (address priceFeed, uint32 stalenessPeriod, bool skipCheck, uint8 decimals,) = priceFeedParams(token); return _getPrice(priceFeed, stalenessPeriod, skipCheck, decimals); } /// @dev Returns `token`'s price and scale from the explicitly specified price feed function _getPriceRaw(address token, bool reserve) internal view returns (uint256 price, uint256 scale) { (address priceFeed, uint32 stalenessPeriod, bool skipCheck, uint8 decimals,,) = _getPriceFeedParams(reserve ? _getTokenReserveKey(token) : token); return _getPrice(priceFeed, stalenessPeriod, skipCheck, decimals); } /// @dev Returns `token`'s safe price and scale function _getPriceSafe(address token) internal view returns (uint256 price, uint256 scale) { (address priceFeed, uint32 stalenessPeriod, bool skipCheck, uint8 decimals,, bool trusted) = _getPriceFeedParams(token); (price, scale) = _getPrice(priceFeed, stalenessPeriod, skipCheck, decimals); // U:[PO-11] if (!trusted) { if (_priceFeedsParams[_getTokenReserveKey(token)].priceFeed == address(0)) return (0, scale); // U:[PO-11] (uint256 reservePrice,) = _getPriceRaw(token, true); price = Math.min(price, reservePrice); // U:[PO-11] } } /// @dev Returns price feed answer and scale, optionally performs sanity and staleness checks function _getPrice(address priceFeed, uint32 stalenessPeriod, bool skipCheck, uint8 decimals) internal view returns (uint256 price, uint256 scale) { int256 answer = _getValidatedPrice(priceFeed, stalenessPeriod, skipCheck); // U:[PO-1] // answer should not be negative (price feeds with `skipCheck = true` must ensure that!) price = uint256(answer); // U:[PO-1] // 1 <= decimals <= 18, so the operation is safe unchecked { scale = 10 ** decimals; // U:[PO-1] } } /// @dev Efficiently loads `token`'s price feed parameters from storage function _getPriceFeedParams(address token) internal view returns ( address priceFeed, uint32 stalenessPeriod, bool skipCheck, uint8 decimals, bool useReserve, bool trusted ) { PriceFeedParams storage params = _priceFeedsParams[token]; assembly { let data := sload(params.slot) priceFeed := data stalenessPeriod := shr(160, data) skipCheck := and(shr(192, data), 0x01) decimals := shr(200, data) useReserve := and(shr(208, data), 0x01) trusted := and(shr(216, data), 0x01) } // U:[PO-2] if (priceFeed == address(0)) revert PriceFeedDoesNotExistException(); // U:[PO-2] } /// @dev Returns key that is used to store `token`'s reserve feed in `_priceFeedParams` function _getTokenReserveKey(address token) internal pure returns (address key) { // address(uint160(uint256(keccak256(abi.encodePacked("RESERVE", token))))) assembly { mstore(0x0, or("RESERVE", shl(0x28, token))) key := keccak256(0x0, 0x1b) } // U:[PO-3] } // ------------- // // CONFIGURATION // // ------------- // /// @notice Sets price feed for a given token function setPriceFeed(address token, address priceFeed, uint32 stalenessPeriod, bool trusted) external override nonZeroAddress(token) // U:[PO-6] nonZeroAddress(priceFeed) // U:[PO-6] configuratorOnly // U:[PO-6] { uint8 decimals = _priceFeedsParams[token].decimals; decimals = decimals == 0 ? _validateToken(token) : decimals; // U:[PO-6] bool skipCheck = _validatePriceFeed(priceFeed, stalenessPeriod); // U:[PO-6] _priceFeedsParams[token] = PriceFeedParams({ priceFeed: priceFeed, stalenessPeriod: stalenessPeriod, skipCheck: skipCheck, decimals: decimals, useReserve: false, trusted: trusted }); // U:[PO-6] emit SetPriceFeed(token, priceFeed, stalenessPeriod, skipCheck, trusted); // U:[PO-6] } /// @notice Sets reserve price feed for a given token /// @dev Main price feed for the token must already be set function setReservePriceFeed(address token, address priceFeed, uint32 stalenessPeriod) external override nonZeroAddress(token) // U:[PO-7] nonZeroAddress(priceFeed) // U:[PO-7] configuratorOnly // U:[PO-7] { uint8 decimals = _priceFeedsParams[token].decimals; if (decimals == 0) revert PriceFeedDoesNotExistException(); // U:[PO-7] bool skipCheck = _validatePriceFeed(priceFeed, stalenessPeriod); // U:[PO-7] _priceFeedsParams[_getTokenReserveKey(token)] = PriceFeedParams({ priceFeed: priceFeed, stalenessPeriod: stalenessPeriod, skipCheck: skipCheck, decimals: decimals, useReserve: false, trusted: false }); // U:[PO-7] emit SetReservePriceFeed(token, priceFeed, stalenessPeriod, skipCheck); // U:[PO-7] } /// @notice Sets `token`'s reserve price feed status to `active` /// @dev Reserve price feed for the token must already be set function setReservePriceFeedStatus(address token, bool active) external override controllerOnly // U:[PO-8] { if (_priceFeedsParams[_getTokenReserveKey(token)].priceFeed == address(0)) { revert PriceFeedDoesNotExistException(); // U:[PO-8] } if (_priceFeedsParams[token].useReserve != active) { _priceFeedsParams[token].useReserve = active; // U:[PO-8] emit SetReservePriceFeedStatus(token, active); // U:[PO-8] } } /// @dev Validates that `token` is a contract that returns `decimals` within allowed range function _validateToken(address token) internal view returns (uint8 decimals) { if (!Address.isContract(token)) revert AddressIsNotContractException(token); // U:[PO-4] try ERC20(token).decimals() returns (uint8 _decimals) { if (_decimals == 0 || _decimals > 18) revert IncorrectTokenContractException(); // U:[PO-4] decimals = _decimals; // U:[PO-4] } catch { revert IncorrectTokenContractException(); // U:[PO-4] } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ 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; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ 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; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ 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; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ 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; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ 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 { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ 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; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ 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); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; // ------- // // GENERAL // // ------- // /// @notice Thrown on attempting to set an important address to zero address error ZeroAddressException(); /// @notice Thrown when attempting to pass a zero amount to a funding-related operation error AmountCantBeZeroException(); /// @notice Thrown on incorrect input parameter error IncorrectParameterException(); /// @notice Thrown when balance is insufficient to perform an operation error InsufficientBalanceException(); /// @notice Thrown if parameter is out of range error ValueOutOfRangeException(); /// @notice Thrown when trying to send ETH to a contract that is not allowed to receive ETH directly error ReceiveIsNotAllowedException(); /// @notice Thrown on attempting to set an EOA as an important contract in the system error AddressIsNotContractException(address); /// @notice Thrown on attempting to receive a token that is not a collateral token or was forbidden error TokenNotAllowedException(); /// @notice Thrown on attempting to add a token that is already in a collateral list error TokenAlreadyAddedException(); /// @notice Thrown when attempting to use quota-related logic for a token that is not quoted in quota keeper error TokenIsNotQuotedException(); /// @notice Thrown on attempting to interact with an address that is not a valid target contract error TargetContractNotAllowedException(); /// @notice Thrown if function is not implemented error NotImplementedException(); // ------------------ // // CONTRACTS REGISTER // // ------------------ // /// @notice Thrown when an address is expected to be a registered credit manager, but is not error RegisteredCreditManagerOnlyException(); /// @notice Thrown when an address is expected to be a registered pool, but is not error RegisteredPoolOnlyException(); // ---------------- // // ADDRESS PROVIDER // // ---------------- // /// @notice Reverts if address key isn't found in address provider error AddressNotFoundException(); // ----------------- // // POOL, PQK, GAUGES // // ----------------- // /// @notice Thrown by pool-adjacent contracts when a credit manager being connected has a wrong pool address error IncompatibleCreditManagerException(); /// @notice Thrown when attempting to set an incompatible successor staking contract error IncompatibleSuccessorException(); /// @notice Thrown when attempting to vote in a non-approved contract error VotingContractNotAllowedException(); /// @notice Thrown when attempting to unvote more votes than there are error InsufficientVotesException(); /// @notice Thrown when attempting to borrow more than the second point on a two-point curve error BorrowingMoreThanU2ForbiddenException(); /// @notice Thrown when a credit manager attempts to borrow more than its limit in the current block, or in general error CreditManagerCantBorrowException(); /// @notice Thrown when attempting to connect a quota keeper to an incompatible pool error IncompatiblePoolQuotaKeeperException(); /// @notice Thrown when the quota is outside of min/max bounds error QuotaIsOutOfBoundsException(); // -------------- // // CREDIT MANAGER // // -------------- // /// @notice Thrown on failing a full collateral check after multicall error NotEnoughCollateralException(); /// @notice Thrown if an attempt to approve a collateral token to adapter's target contract fails error AllowanceFailedException(); /// @notice Thrown on attempting to perform an action for a credit account that does not exist error CreditAccountDoesNotExistException(); /// @notice Thrown on configurator attempting to add more than 255 collateral tokens error TooManyTokensException(); /// @notice Thrown if more than the maximum number of tokens were enabled on a credit account error TooManyEnabledTokensException(); /// @notice Thrown when attempting to execute a protocol interaction without active credit account set error ActiveCreditAccountNotSetException(); /// @notice Thrown when trying to update credit account's debt more than once in the same block error DebtUpdatedTwiceInOneBlockException(); /// @notice Thrown when trying to repay all debt while having active quotas error DebtToZeroWithActiveQuotasException(); /// @notice Thrown when a zero-debt account attempts to update quota error UpdateQuotaOnZeroDebtAccountException(); /// @notice Thrown when attempting to close an account with non-zero debt error CloseAccountWithNonZeroDebtException(); /// @notice Thrown when value of funds remaining on the account after liquidation is insufficient error InsufficientRemainingFundsException(); /// @notice Thrown when Credit Facade tries to write over a non-zero active Credit Account error ActiveCreditAccountOverridenException(); // ------------------- // // CREDIT CONFIGURATOR // // ------------------- // /// @notice Thrown on attempting to use a non-ERC20 contract or an EOA as a token error IncorrectTokenContractException(); /// @notice Thrown if the newly set LT if zero or greater than the underlying's LT error IncorrectLiquidationThresholdException(); /// @notice Thrown if borrowing limits are incorrect: minLimit > maxLimit or maxLimit > blockLimit error IncorrectLimitsException(); /// @notice Thrown if the new expiration date is less than the current expiration date or current timestamp error IncorrectExpirationDateException(); /// @notice Thrown if a contract returns a wrong credit manager or reverts when trying to retrieve it error IncompatibleContractException(); /// @notice Thrown if attempting to forbid an adapter that is not registered in the credit manager error AdapterIsNotRegisteredException(); // ------------- // // CREDIT FACADE // // ------------- // /// @notice Thrown when attempting to perform an action that is forbidden in whitelisted mode error ForbiddenInWhitelistedModeException(); /// @notice Thrown if credit facade is not expirable, and attempted aciton requires expirability error NotAllowedWhenNotExpirableException(); /// @notice Thrown if a selector that doesn't match any allowed function is passed to the credit facade in a multicall error UnknownMethodException(); /// @notice Thrown when trying to close an account with enabled tokens error CloseAccountWithEnabledTokensException(); /// @notice Thrown if a liquidator tries to liquidate an account with a health factor above 1 error CreditAccountNotLiquidatableException(); /// @notice Thrown if too much new debt was taken within a single block error BorrowedBlockLimitException(); /// @notice Thrown if the new debt principal for a credit account falls outside of borrowing limits error BorrowAmountOutOfLimitsException(); /// @notice Thrown if a user attempts to open an account via an expired credit facade error NotAllowedAfterExpirationException(); /// @notice Thrown if expected balances are attempted to be set twice without performing a slippage check error ExpectedBalancesAlreadySetException(); /// @notice Thrown if attempting to perform a slippage check when excepted balances are not set error ExpectedBalancesNotSetException(); /// @notice Thrown if balance of at least one token is less than expected during a slippage check error BalanceLessThanExpectedException(); /// @notice Thrown when trying to perform an action that is forbidden when credit account has enabled forbidden tokens error ForbiddenTokensException(); /// @notice Thrown when new forbidden tokens are enabled during the multicall error ForbiddenTokenEnabledException(); /// @notice Thrown when enabled forbidden token balance is increased during the multicall error ForbiddenTokenBalanceIncreasedException(); /// @notice Thrown when the remaining token balance is increased during the liquidation error RemainingTokenBalanceIncreasedException(); /// @notice Thrown if `botMulticall` is called by an address that is not approved by account owner or is forbidden error NotApprovedBotException(); /// @notice Thrown when attempting to perform a multicall action with no permission for it error NoPermissionException(uint256 permission); /// @notice Thrown when attempting to give a bot unexpected permissions error UnexpectedPermissionsException(); /// @notice Thrown when a custom HF parameter lower than 10000 is passed into the full collateral check error CustomHealthFactorTooLowException(); /// @notice Thrown when submitted collateral hint is not a valid token mask error InvalidCollateralHintException(); // ------ // // ACCESS // // ------ // /// @notice Thrown on attempting to call an access restricted function not as credit account owner error CallerNotCreditAccountOwnerException(); /// @notice Thrown on attempting to call an access restricted function not as configurator error CallerNotConfiguratorException(); /// @notice Thrown on attempting to call an access-restructed function not as account factory error CallerNotAccountFactoryException(); /// @notice Thrown on attempting to call an access restricted function not as credit manager error CallerNotCreditManagerException(); /// @notice Thrown on attempting to call an access restricted function not as credit facade error CallerNotCreditFacadeException(); /// @notice Thrown on attempting to call an access restricted function not as controller or configurator error CallerNotControllerException(); /// @notice Thrown on attempting to pause a contract without pausable admin rights error CallerNotPausableAdminException(); /// @notice Thrown on attempting to unpause a contract without unpausable admin rights error CallerNotUnpausableAdminException(); /// @notice Thrown on attempting to call an access restricted function not as gauge error CallerNotGaugeException(); /// @notice Thrown on attempting to call an access restricted function not as quota keeper error CallerNotPoolQuotaKeeperException(); /// @notice Thrown on attempting to call an access restricted function not as voter error CallerNotVoterException(); /// @notice Thrown on attempting to call an access restricted function not as allowed adapter error CallerNotAdapterException(); /// @notice Thrown on attempting to call an access restricted function not as migrator error CallerNotMigratorException(); /// @notice Thrown when an address that is not the designated executor attempts to execute a transaction error CallerNotExecutorException(); /// @notice Thrown on attempting to call an access restricted function not as veto admin error CallerNotVetoAdminException(); // ------------------- // // CONTROLLER TIMELOCK // // ------------------- // /// @notice Thrown when the new parameter values do not satisfy required conditions error ParameterChecksFailedException(); /// @notice Thrown when attempting to execute a non-queued transaction error TxNotQueuedException(); /// @notice Thrown when attempting to execute a transaction that is either immature or stale error TxExecutedOutsideTimeWindowException(); /// @notice Thrown when execution of a transaction fails error TxExecutionRevertedException(); /// @notice Thrown when the value of a parameter on execution is different from the value on queue error ParameterChangedAfterQueuedTxException(); // -------- // // BOT LIST // // -------- // /// @notice Thrown when attempting to set non-zero permissions for a forbidden or special bot error InvalidBotException(); // --------------- // // ACCOUNT FACTORY // // --------------- // /// @notice Thrown when trying to deploy second master credit account for a credit manager error MasterCreditAccountAlreadyDeployedException(); /// @notice Thrown when trying to rescue funds from a credit account that is currently in use error CreditAccountIsInUseException(); // ------------ // // PRICE ORACLE // // ------------ // /// @notice Thrown on attempting to set a token price feed to an address that is not a correct price feed error IncorrectPriceFeedException(); /// @notice Thrown on attempting to interact with a price feed for a token not added to the price oracle error PriceFeedDoesNotExistException(); /// @notice Thrown when price feed returns incorrect price for a token error IncorrectPriceException(); /// @notice Thrown when token's price feed becomes stale error StalePriceException();
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. 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 { /// @notice Emitted when new price feed is set for token event SetPriceFeed( address indexed token, address indexed priceFeed, uint32 stalenessPeriod, bool skipCheck, bool trusted ); /// @notice Emitted when new reserve price feed is set for token event SetReservePriceFeed(address indexed token, address indexed priceFeed, uint32 stalenessPeriod, bool skipCheck); /// @notice Emitted when new reserve price feed status is set for a token event SetReservePriceFeedStatus(address indexed token, bool active); } /// @title Price oracle V3 interface 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); // ------------- // // CONFIGURATION // // ------------- // 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; }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. 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"; /// @title ACL non-reentrant trait /// @notice Extended version of `ACLTrait` that implements pausable functionality, /// reentrancy protection and external controller role abstract contract ACLNonReentrantTrait is ACLTrait, Pausable, ReentrancyGuardTrait { /// @notice Emitted when new external controller is set event NewController(address indexed newController); /// @notice External controller address address public controller; /// @dev Ensures that function caller is external controller or configurator modifier controllerOnly() { _ensureCallerIsControllerOrConfigurator(); _; } /// @dev Reverts if the caller is not controller or configurator /// @dev Used to cut contract size on modifiers function _ensureCallerIsControllerOrConfigurator() internal view { if (msg.sender != controller && !_isConfigurator({account: msg.sender})) { revert CallerNotControllerException(); } } /// @dev Ensures that function caller has pausable admin role modifier pausableAdminsOnly() { _ensureCallerIsPausableAdmin(); _; } /// @dev Reverts if the caller is not pausable admin /// @dev Used to cut contract size on modifiers function _ensureCallerIsPausableAdmin() internal view { if (!_isPausableAdmin({account: msg.sender})) { revert CallerNotPausableAdminException(); } } /// @dev Ensures that function caller has unpausable admin role modifier unpausableAdminsOnly() { _ensureCallerIsUnpausableAdmin(); _; } /// @dev Reverts if the caller is not unpausable admin /// @dev Used to cut contract size on modifiers function _ensureCallerIsUnpausableAdmin() internal view { if (!_isUnpausableAdmin({account: msg.sender})) { revert CallerNotUnpausableAdminException(); } } /// @notice Constructor /// @param addressProvider Address provider contract address constructor(address addressProvider) ACLTrait(addressProvider) { controller = IACL(acl).owner(); } /// @notice Pauses contract, can only be called by an account with pausable admin role function pause() external virtual pausableAdminsOnly { _pause(); } /// @notice Unpauses contract, can only be called by an account with unpausable admin role function unpause() external virtual unpausableAdminsOnly { _unpause(); } /// @notice Sets new external controller, can only be called by configurator function setController(address newController) external configuratorOnly { if (controller == newController) return; controller = newController; emit NewController(newController); } /// @dev Checks whether given account has pausable admin role function _isPausableAdmin(address account) internal view returns (bool) { return IACL(acl).isPausableAdmin(account); } /// @dev Checks whether given account has unpausable admin role function _isUnpausableAdmin(address account) internal view returns (bool) { return IACL(acl).isUnpausableAdmin(account); } }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. 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"; /// @title Price feed validation trait abstract contract PriceFeedValidationTrait { using Address for address; /// @dev Ensures that price is positive and not stale function _checkAnswer(int256 price, uint256 updatedAt, uint32 stalenessPeriod) internal view { if (price <= 0) revert IncorrectPriceException(); if (block.timestamp >= updatedAt + stalenessPeriod) revert StalePriceException(); } /// @dev Valites that `priceFeed` is a contract that adheres to Chainlink interface and passes sanity checks /// @dev Some price feeds return stale prices unless updated right before querying their answer, which causes /// issues during deployment and configuration, so for such price feeds staleness check is skipped, and /// special care must be taken to ensure all parameters are in tune. function _validatePriceFeed(address priceFeed, uint32 stalenessPeriod) internal view returns (bool skipCheck) { if (!priceFeed.isContract()) revert AddressIsNotContractException(priceFeed); // U:[PO-5] try IPriceFeed(priceFeed).decimals() returns (uint8 _decimals) { if (_decimals != 8) revert IncorrectPriceFeedException(); // U:[PO-5] } catch { revert IncorrectPriceFeedException(); // U:[PO-5] } try IPriceFeed(priceFeed).skipPriceCheck() returns (bool _skipCheck) { skipCheck = _skipCheck; // U:[PO-5] } catch {} try IPriceFeed(priceFeed).latestRoundData() returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80) { if (skipCheck) { if (stalenessPeriod != 0) revert IncorrectParameterException(); // U:[PO-5] } else { if (stalenessPeriod == 0) revert IncorrectParameterException(); // U:[PO-5] bool updatable; try IUpdatablePriceFeed(priceFeed).updatable() returns (bool _updatable) { updatable = _updatable; } catch {} if (!updatable) _checkAnswer(answer, updatedAt, stalenessPeriod); // U:[PO-5] } } catch { revert IncorrectPriceFeedException(); // U:[PO-5] } } /// @dev Returns answer from a price feed with optional sanity and staleness checks function _getValidatedPrice(address priceFeed, uint32 stalenessPeriod, bool skipCheck) internal view returns (int256 answer) { uint256 updatedAt; (, answer,, updatedAt,) = IPriceFeed(priceFeed).latestRoundData(); // U:[PO-1] if (!skipCheck) _checkAnswer(answer, updatedAt, stalenessPeriod); // U:[PO-1] } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; import { IVersion } from "./IVersion.sol"; /// @title Price oracle base interface /// @notice Functions shared accross newer and older versions 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; import { IVersion } from "./IVersion.sol"; interface IACLExceptions { /// @dev Thrown when attempting to delete an address from a set that is not a pausable admin error AddressNotPausableAdminException(address addr); /// @dev Thrown when attempting to delete an address from a set that is not a unpausable admin error AddressNotUnpausableAdminException(address addr); } interface IACLEvents { /// @dev Emits when a new admin is added that can pause contracts event PausableAdminAdded(address indexed newAdmin); /// @dev Emits when a Pausable admin is removed event PausableAdminRemoved(address indexed admin); /// @dev Emits when a new admin is added that can unpause contracts event UnpausableAdminAdded(address indexed newAdmin); /// @dev Emits when an Unpausable admin is removed event UnpausableAdminRemoved(address indexed admin); } /// @title ACL interface interface IACL is IACLEvents, IACLExceptions, IVersion { /// @dev Returns true if the address is a pausable admin and false if not /// @param addr Address to check function isPausableAdmin(address addr) external view returns (bool); /// @dev Returns true if the address is unpausable admin and false if not /// @param addr Address to check function isUnpausableAdmin(address addr) external view returns (bool); /// @dev Returns true if an address has configurator rights /// @param account Address to check function isConfigurator(address account) external view returns (bool); /// @dev Returns address of configurator function owner() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. 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"; /// @title ACL trait /// @notice Utility class for ACL (access-control list) consumers abstract contract ACLTrait is SanityCheckTrait { /// @notice ACL contract address address public immutable acl; /// @notice Constructor /// @param addressProvider Address provider contract address constructor(address addressProvider) nonZeroAddress(addressProvider) { acl = IAddressProviderV3(addressProvider).getAddressOrRevert(AP_ACL, NO_VERSION_CONTROL); } /// @dev Ensures that function caller has configurator role modifier configuratorOnly() { _ensureCallerIsConfigurator(); _; } /// @dev Reverts if the caller is not the configurator /// @dev Used to cut contract size on modifiers function _ensureCallerIsConfigurator() internal view { if (!_isConfigurator({account: msg.sender})) { revert CallerNotConfiguratorException(); } } /// @dev Checks whether given account has configurator role function _isConfigurator(address account) internal view returns (bool) { return IACL(acl).isConfigurator(account); } }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; uint8 constant NOT_ENTERED = 1; uint8 constant ENTERED = 2; /// @title Reentrancy guard trait /// @notice Same as OpenZeppelin's `ReentrancyGuard` but only uses 1 byte of storage instead of 32 abstract contract ReentrancyGuardTrait { uint8 internal _reentrancyStatus = NOT_ENTERED; /// @dev Prevents a contract from calling itself, directly or indirectly. /// Calling a `nonReentrant` function from another `nonReentrant` /// function is not supported. It is possible to prevent this from happening /// by making the `nonReentrant` function external, and making it call a /// `private` function that does the actual work. modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true _ensureNotEntered(); // Any calls to nonReentrant after this point will fail _reentrancyStatus = ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _reentrancyStatus = NOT_ENTERED; } /// @dev Reverts if the contract is currently entered /// @dev Used to cut contract size on modifiers function _ensureNotEntered() internal view { require(_reentrancyStatus != ENTERED, "ReentrancyGuard: reentrant call"); } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.0; import { PriceFeedType } from "@gearbox-protocol/sdk-gov/contracts/PriceFeedType.sol"; /// @title Price feed interface 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); } /// @title Updatable price feed interface interface IUpdatablePriceFeed is IPriceFeed { function updatable() external view returns (bool); function updatePrice(bytes calldata data) external; }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; /// @title Version interface /// @notice Defines contract version interface IVersion { /// @notice Contract version function version() external view returns (uint256); }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. 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 { /// @notice Emitted when an address is set for a contract key event SetAddress(bytes32 indexed key, address indexed value, uint256 indexed version); } /// @title Address provider V3 interface 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; }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {ZeroAddressException} from "../interfaces/IExceptions.sol"; /// @title Sanity check trait abstract contract SanityCheckTrait { /// @dev Ensures that passed address is non-zero modifier nonZeroAddress(address addr) { _revertIfZeroAddress(addr); _; } /// @dev Reverts if address is zero function _revertIfZeroAddress(address addr) private pure { if (addr == address(0)) revert ZeroAddressException(); } }
// SPDX-License-Identifier: UNLICENSED // Gearbox. Generalized leverage protocol that allows to take leverage and then use it across other DeFi protocols and platforms in a composable way. // (c) Gearbox Foundation, 2023 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 }
{ "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/" ], "optimizer": { "enabled": true, "runs": 1000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"addressProvider","type":"address"}],"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":"IncorrectParameterException","type":"error"},{"inputs":[],"name":"IncorrectPriceException","type":"error"},{"inputs":[],"name":"IncorrectPriceFeedException","type":"error"},{"inputs":[],"name":"IncorrectTokenContractException","type":"error"},{"inputs":[],"name":"PriceFeedDoesNotExistException","type":"error"},{"inputs":[],"name":"StalePriceException","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":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"priceFeed","type":"address"},{"indexed":false,"internalType":"uint32","name":"stalenessPeriod","type":"uint32"},{"indexed":false,"internalType":"bool","name":"skipCheck","type":"bool"},{"indexed":false,"internalType":"bool","name":"trusted","type":"bool"}],"name":"SetPriceFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"priceFeed","type":"address"},{"indexed":false,"internalType":"uint32","name":"stalenessPeriod","type":"uint32"},{"indexed":false,"internalType":"bool","name":"skipCheck","type":"bool"}],"name":"SetReservePriceFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"SetReservePriceFeedStatus","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":"controller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"tokenFrom","type":"address"},{"internalType":"address","name":"tokenTo","type":"address"}],"name":"convert","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"convertFromUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"convertToUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"reserve","type":"bool"}],"name":"getPriceRaw","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getPriceSafe","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"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":[{"internalType":"address","name":"token","type":"address"}],"name":"priceFeedParams","outputs":[{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint32","name":"stalenessPeriod","type":"uint32"},{"internalType":"bool","name":"skipCheck","type":"bool"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"bool","name":"trusted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"priceFeeds","outputs":[{"internalType":"address","name":"priceFeed","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"reserve","type":"bool"}],"name":"priceFeedsRaw","outputs":[{"internalType":"address","name":"priceFeed","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"safeConvertToUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newController","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint32","name":"stalenessPeriod","type":"uint32"},{"internalType":"bool","name":"trusted","type":"bool"}],"name":"setPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint32","name":"stalenessPeriod","type":"uint32"}],"name":"setReservePriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"active","type":"bool"}],"name":"setReservePriceFeedStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040526000805461ff0019166101001790553480156200002057600080fd5b5060405162001a9538038062001a958339810160408190526200004391620001a0565b808080620000518162000175565b604051632bdad0e360e11b8152621050d360ea1b6004820152600060248201526001600160a01b038316906357b5a1c690604401602060405180830381865afa158015620000a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000c99190620001a0565b6001600160a01b031660808190526000805460ff1916905560408051638da5cb5b60e01b81529051919350638da5cb5b92506004808201926020929091908290030181865afa15801562000121573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001479190620001a0565b600060026101000a8154816001600160a01b0302191690836001600160a01b031602179055505050620001d2565b6001600160a01b0381166200019d57604051635919af9760e11b815260040160405180910390fd5b50565b600060208284031215620001b357600080fd5b81516001600160a01b0381168114620001cb57600080fd5b9392505050565b60805161189262000203600039600081816102f7015281816112db0152818161140b01526114c901526118926000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c80638f8a8aba116100cd578063ccdd1ce311610081578063f77c479111610066578063f77c479114610319578063f9a6503014610332578063ff2998451461034557600080fd5b8063ccdd1ce31461029e578063de287359146102f257600080fd5b806392eefe9b116100b257806392eefe9b1461024d5780639dcb511a14610260578063b66102df1461028b57600080fd5b80638f8a8aba14610227578063903456711461023a57600080fd5b806354fd4d50116101245780635c975abb116101095780635c975abb146101f65780637afb01041461020c5780638456cb591461021f57600080fd5b806354fd4d50146101da578063553552fe146101e357600080fd5b80631b6dfcc0116101555780631b6dfcc0146101ac5780633f4ba83a146101bf57806341976e09146101c757600080fd5b806301aecdfa146101715780630b51dadf14610197575b600080fd5b61018461017f3660046115e4565b610358565b6040519081526020015b60405180910390f35b6101aa6101a5366004611613565b61036a565b005b6101aa6101ba366004611664565b61060a565b6101aa61071b565b6101846101d53660046115e4565b61072d565b61018461012c81565b6101846101f136600461169b565b610738565b60005460ff16604051901515815260200161018e565b61018461021a36600461169b565b61076b565b6101aa610789565b610184610235366004611664565b610799565b6101aa6102483660046116c7565b6107ad565b6101aa61025b3660046115e4565b6109c8565b61027361026e3660046115e4565b610a54565b6040516001600160a01b03909116815260200161018e565b61018461029936600461171d565b610a6a565b6102b16102ac3660046115e4565b610ac2565b604080516001600160a01b03909616865263ffffffff90941660208601529115159284019290925260ff90911660608301521515608082015260a00161018e565b6102737f000000000000000000000000000000000000000000000000000000000000000081565b600054610273906201000090046001600160a01b031681565b61018461034036600461169b565b610b27565b610273610353366004611664565b610b35565b600061036382610b71565b5092915050565b8261037481610c13565b8261037e81610c13565b610386610c53565b6001600160a01b038516600090815260016020526040812054600160c81b900460ff16908190036103ca57604051630d1b18db60e31b815260040160405180910390fd5b60006103d68686610c92565b90506040518060c00160405280876001600160a01b031681526020018663ffffffff16815260200182151581526020018360ff16815260200160001515815260200160001515815250600160006104458a665245534552564560c81b60289190911b176000908152601b902090565b6001600160a01b0390811682526020808301939093526040918201600020845181548686015187860151606089015160808a015160a0909a01519487167fffffffffffffffff000000000000000000000000000000000000000000000000909416939093177401000000000000000000000000000000000000000063ffffffff93841602177fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000911515919091027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff1617600160c81b60ff90931692909202919091177fffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffff16600160d01b971515979097027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff16969096177b0100000000000000000000000000000000000000000000000000000091151591909102179055815193891684528415159284019290925288821692918a16917f0622a3fd57e320160fa23aaad98e12139a7922016875937c646e76237005c01c910160405180910390a350505050505050565b610612610f19565b665245534552564560c81b602883901b176000908152601b81206001600160a01b03908116825260016020526040909120541661066257604051630d1b18db60e31b815260040160405180910390fd5b6001600160a01b03821660009081526001602052604090205460ff600160d01b90910416151581151514610717576001600160a01b038216600081815260016020526040908190208054841515600160d01b027fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff909116179055517f8065e881e49e3c3c04dadba3c10e1abdd738d4aa4a7807b49dc5d4600ec628859061070e90841515815260200190565b60405180910390a25b5050565b610723610f77565b61072b610fb6565b565b600061036382611008565b600080600061074684610b71565b9092509050806107568387611766565b610760919061177d565b925050505b92915050565b600080600061077984611008565b9092509050816107568287611766565b61079161103c565b61072b61107b565b60006107a583836110b8565b509392505050565b836107b781610c13565b836107c181610c13565b6107c9610c53565b6001600160a01b038616600090815260016020526040902054600160c81b900460ff1680156107f85780610801565b61080187611113565b9050600061080f8787610c92565b90506040518060c00160405280886001600160a01b031681526020018763ffffffff16815260200182151581526020018360ff168152602001600015158152602001861515815250600160008a6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548160ff02191690831515021790555060608201518160000160196101000a81548160ff021916908360ff160217905550608082015181600001601a6101000a81548160ff02191690831515021790555060a082015181600001601b6101000a81548160ff021916908315150217905550905050866001600160a01b0316886001600160a01b03167f6f6e6748412d711178a1e4442639251046367e322537226488cddaf6e8d4b8558884896040516109b69392919063ffffffff93909316835290151560208301521515604082015260600190565b60405180910390a35050505050505050565b6109d0610c53565b6000546001600160a01b03828116620100009092041614610a5157600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff16620100006001600160a01b03841690810291909117825560405190917fe253457d9ad994ca9682fc3bbc38c890dca73a2d5ecee3809e548bac8b00d7c691a25b50565b6000610a5f82610ac2565b509295945050505050565b6000806000610a7885611008565b91509150600080610a8886611008565b9092509050610a978383611766565b81610aa2868b611766565b610aac9190611766565b610ab6919061177d565b98975050505050505050565b600080600080600080610ad4876111f8565b949a50929850909650945090925090508015610b1d57602887901b665245534552564560c81b176000908152601b9020610b0d906111f8565b949a509298509096509450909250505b5091939590929450565b600080600061074684611008565b6000610b6482610b4557836111f8565b602884901b665245534552564560c81b176000908152601b90206111f8565b5093979650505050505050565b6000806000806000806000610b85886111f8565b9550509450945094509450610b9c85858585611264565b909750955080610c0957665245534552564560c81b602889901b176000908152601b81206001600160a01b039081168252600160205260409091205416610beb57600096505050505050915091565b6000610bf88960016110b8565b509050610c058882611288565b9750505b5050505050915091565b6001600160a01b038116610a51576040517fb2335f2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c5c336112a0565b61072b576040517f61081c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600160a01b0383163b610ccc5760405163df4c572d60e01b81526001600160a01b03841660048201526024015b60405180910390fd5b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610d26575060408051601f3d908101601f19168201909252610d239181019061179f565b60015b610d43576040516367a7cd4360e01b815260040160405180910390fd5b8060ff16600814610d67576040516367a7cd4360e01b815260040160405180910390fd5b50826001600160a01b031663d62ada116040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610dc2575060408051601f3d908101601f19168201909252610dbf918101906117c2565b60015b15610dca5790505b826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015610e24575060408051601f3d908101601f19168201909252610e21918101906117f9565b60015b610e41576040516367a7cd4360e01b815260040160405180910390fd5b8515610e715763ffffffff871615610e6c576040516347fbaa9760e01b815260040160405180910390fd5b610f0e565b8663ffffffff16600003610e98576040516347fbaa9760e01b815260040160405180910390fd5b6000886001600160a01b031663e75aeec86040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610ef4575060408051601f3d908101601f19168201909252610ef1918101906117c2565b60015b15610efc5790505b80610f0c57610f0c85848a611349565b505b505050505092915050565b6000546201000090046001600160a01b03163314801590610f405750610f3e336112a0565b155b1561072b576040517f0129bb9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f80336113d0565b61072b576040517f16e29ab700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fbe61143c565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60008060008060008061101a87610ac2565b50935093509350935061102f84848484611264565b9550955050505050915091565b6110453361148e565b61072b576040517fd794b1e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110836114fa565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610feb3390565b6000806000806000806110ee876110cf57886111f8565b602889901b665245534552564560c81b176000908152601b90206111f8565b5050935093509350935061110484848484611264565b95509550505050509250929050565b60006001600160a01b0382163b6111485760405163df4c572d60e01b81526001600160a01b0383166004820152602401610cc3565b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111a2575060408051601f3d908101601f1916820190925261119f9181019061179f565b60015b6111bf5760405163528ca31d60e01b815260040160405180910390fd5b60ff811615806111d2575060128160ff16115b156111f05760405163528ca31d60e01b815260040160405180910390fd5b90505b919050565b6001600160a01b03808216600090815260016020819052604090912080549260a084901c9260c085901c81169260c886901c9260d087901c83169260d888901c169190871661125a57604051630d1b18db60e31b815260040160405180910390fd5b5091939550919395565b600080600061127487878761154d565b9760ff909416600a0a965092945050505050565b60008183106112975781611299565b825b9392505050565b6040517f5f259aba0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690635f259aba906024015b602060405180830381865afa158015611325573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076591906117c2565b60008313611383576040517f53b798e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61139363ffffffff821683611849565b42106113cb576040517f16dd0ffb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6040517fd4eb5db00000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063d4eb5db090602401611308565b60005460ff1661072b5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610cc3565b6040517f3a41ec640000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a41ec6490602401611308565b60005460ff161561072b5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610cc3565b600080846001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561158e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b291906117f9565b509194509092508491506107a59050576107a5828286611349565b80356001600160a01b03811681146111f357600080fd5b6000602082840312156115f657600080fd5b611299826115cd565b803563ffffffff811681146111f357600080fd5b60008060006060848603121561162857600080fd5b611631846115cd565b925061163f602085016115cd565b915061164d604085016115ff565b90509250925092565b8015158114610a5157600080fd5b6000806040838503121561167757600080fd5b611680836115cd565b9150602083013561169081611656565b809150509250929050565b600080604083850312156116ae57600080fd5b823591506116be602084016115cd565b90509250929050565b600080600080608085870312156116dd57600080fd5b6116e6856115cd565b93506116f4602086016115cd565b9250611702604086016115ff565b9150606085013561171281611656565b939692955090935050565b60008060006060848603121561173257600080fd5b83359250611742602085016115cd565b915061164d604085016115cd565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761076557610765611750565b60008261179a57634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156117b157600080fd5b815160ff8116811461129957600080fd5b6000602082840312156117d457600080fd5b815161129981611656565b805169ffffffffffffffffffff811681146111f357600080fd5b600080600080600060a0868803121561181157600080fd5b61181a866117df565b945060208601519350604086015192506060860151915061183d608087016117df565b90509295509295909350565b808201808211156107655761076561175056fea2646970667358221220558c278ec52a583228401fde267bafb0e2730e15e11d54e04c86f522f3d986db64736f6c634300081100330000000000000000000000004b27b296273b72d7c7bfee1ace93dc081467c41b
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061016c5760003560e01c80638f8a8aba116100cd578063ccdd1ce311610081578063f77c479111610066578063f77c479114610319578063f9a6503014610332578063ff2998451461034557600080fd5b8063ccdd1ce31461029e578063de287359146102f257600080fd5b806392eefe9b116100b257806392eefe9b1461024d5780639dcb511a14610260578063b66102df1461028b57600080fd5b80638f8a8aba14610227578063903456711461023a57600080fd5b806354fd4d50116101245780635c975abb116101095780635c975abb146101f65780637afb01041461020c5780638456cb591461021f57600080fd5b806354fd4d50146101da578063553552fe146101e357600080fd5b80631b6dfcc0116101555780631b6dfcc0146101ac5780633f4ba83a146101bf57806341976e09146101c757600080fd5b806301aecdfa146101715780630b51dadf14610197575b600080fd5b61018461017f3660046115e4565b610358565b6040519081526020015b60405180910390f35b6101aa6101a5366004611613565b61036a565b005b6101aa6101ba366004611664565b61060a565b6101aa61071b565b6101846101d53660046115e4565b61072d565b61018461012c81565b6101846101f136600461169b565b610738565b60005460ff16604051901515815260200161018e565b61018461021a36600461169b565b61076b565b6101aa610789565b610184610235366004611664565b610799565b6101aa6102483660046116c7565b6107ad565b6101aa61025b3660046115e4565b6109c8565b61027361026e3660046115e4565b610a54565b6040516001600160a01b03909116815260200161018e565b61018461029936600461171d565b610a6a565b6102b16102ac3660046115e4565b610ac2565b604080516001600160a01b03909616865263ffffffff90941660208601529115159284019290925260ff90911660608301521515608082015260a00161018e565b6102737f000000000000000000000000ad131da4bddb40ebb5ceeaea87067553d431389581565b600054610273906201000090046001600160a01b031681565b61018461034036600461169b565b610b27565b610273610353366004611664565b610b35565b600061036382610b71565b5092915050565b8261037481610c13565b8261037e81610c13565b610386610c53565b6001600160a01b038516600090815260016020526040812054600160c81b900460ff16908190036103ca57604051630d1b18db60e31b815260040160405180910390fd5b60006103d68686610c92565b90506040518060c00160405280876001600160a01b031681526020018663ffffffff16815260200182151581526020018360ff16815260200160001515815260200160001515815250600160006104458a665245534552564560c81b60289190911b176000908152601b902090565b6001600160a01b0390811682526020808301939093526040918201600020845181548686015187860151606089015160808a015160a0909a01519487167fffffffffffffffff000000000000000000000000000000000000000000000000909416939093177401000000000000000000000000000000000000000063ffffffff93841602177fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000911515919091027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff1617600160c81b60ff90931692909202919091177fffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffff16600160d01b971515979097027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff16969096177b0100000000000000000000000000000000000000000000000000000091151591909102179055815193891684528415159284019290925288821692918a16917f0622a3fd57e320160fa23aaad98e12139a7922016875937c646e76237005c01c910160405180910390a350505050505050565b610612610f19565b665245534552564560c81b602883901b176000908152601b81206001600160a01b03908116825260016020526040909120541661066257604051630d1b18db60e31b815260040160405180910390fd5b6001600160a01b03821660009081526001602052604090205460ff600160d01b90910416151581151514610717576001600160a01b038216600081815260016020526040908190208054841515600160d01b027fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff909116179055517f8065e881e49e3c3c04dadba3c10e1abdd738d4aa4a7807b49dc5d4600ec628859061070e90841515815260200190565b60405180910390a25b5050565b610723610f77565b61072b610fb6565b565b600061036382611008565b600080600061074684610b71565b9092509050806107568387611766565b610760919061177d565b925050505b92915050565b600080600061077984611008565b9092509050816107568287611766565b61079161103c565b61072b61107b565b60006107a583836110b8565b509392505050565b836107b781610c13565b836107c181610c13565b6107c9610c53565b6001600160a01b038616600090815260016020526040902054600160c81b900460ff1680156107f85780610801565b61080187611113565b9050600061080f8787610c92565b90506040518060c00160405280886001600160a01b031681526020018763ffffffff16815260200182151581526020018360ff168152602001600015158152602001861515815250600160008a6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548160ff02191690831515021790555060608201518160000160196101000a81548160ff021916908360ff160217905550608082015181600001601a6101000a81548160ff02191690831515021790555060a082015181600001601b6101000a81548160ff021916908315150217905550905050866001600160a01b0316886001600160a01b03167f6f6e6748412d711178a1e4442639251046367e322537226488cddaf6e8d4b8558884896040516109b69392919063ffffffff93909316835290151560208301521515604082015260600190565b60405180910390a35050505050505050565b6109d0610c53565b6000546001600160a01b03828116620100009092041614610a5157600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff16620100006001600160a01b03841690810291909117825560405190917fe253457d9ad994ca9682fc3bbc38c890dca73a2d5ecee3809e548bac8b00d7c691a25b50565b6000610a5f82610ac2565b509295945050505050565b6000806000610a7885611008565b91509150600080610a8886611008565b9092509050610a978383611766565b81610aa2868b611766565b610aac9190611766565b610ab6919061177d565b98975050505050505050565b600080600080600080610ad4876111f8565b949a50929850909650945090925090508015610b1d57602887901b665245534552564560c81b176000908152601b9020610b0d906111f8565b949a509298509096509450909250505b5091939590929450565b600080600061074684611008565b6000610b6482610b4557836111f8565b602884901b665245534552564560c81b176000908152601b90206111f8565b5093979650505050505050565b6000806000806000806000610b85886111f8565b9550509450945094509450610b9c85858585611264565b909750955080610c0957665245534552564560c81b602889901b176000908152601b81206001600160a01b039081168252600160205260409091205416610beb57600096505050505050915091565b6000610bf88960016110b8565b509050610c058882611288565b9750505b5050505050915091565b6001600160a01b038116610a51576040517fb2335f2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c5c336112a0565b61072b576040517f61081c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600160a01b0383163b610ccc5760405163df4c572d60e01b81526001600160a01b03841660048201526024015b60405180910390fd5b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610d26575060408051601f3d908101601f19168201909252610d239181019061179f565b60015b610d43576040516367a7cd4360e01b815260040160405180910390fd5b8060ff16600814610d67576040516367a7cd4360e01b815260040160405180910390fd5b50826001600160a01b031663d62ada116040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610dc2575060408051601f3d908101601f19168201909252610dbf918101906117c2565b60015b15610dca5790505b826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015610e24575060408051601f3d908101601f19168201909252610e21918101906117f9565b60015b610e41576040516367a7cd4360e01b815260040160405180910390fd5b8515610e715763ffffffff871615610e6c576040516347fbaa9760e01b815260040160405180910390fd5b610f0e565b8663ffffffff16600003610e98576040516347fbaa9760e01b815260040160405180910390fd5b6000886001600160a01b031663e75aeec86040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610ef4575060408051601f3d908101601f19168201909252610ef1918101906117c2565b60015b15610efc5790505b80610f0c57610f0c85848a611349565b505b505050505092915050565b6000546201000090046001600160a01b03163314801590610f405750610f3e336112a0565b155b1561072b576040517f0129bb9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f80336113d0565b61072b576040517f16e29ab700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fbe61143c565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60008060008060008061101a87610ac2565b50935093509350935061102f84848484611264565b9550955050505050915091565b6110453361148e565b61072b576040517fd794b1e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110836114fa565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610feb3390565b6000806000806000806110ee876110cf57886111f8565b602889901b665245534552564560c81b176000908152601b90206111f8565b5050935093509350935061110484848484611264565b95509550505050509250929050565b60006001600160a01b0382163b6111485760405163df4c572d60e01b81526001600160a01b0383166004820152602401610cc3565b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111a2575060408051601f3d908101601f1916820190925261119f9181019061179f565b60015b6111bf5760405163528ca31d60e01b815260040160405180910390fd5b60ff811615806111d2575060128160ff16115b156111f05760405163528ca31d60e01b815260040160405180910390fd5b90505b919050565b6001600160a01b03808216600090815260016020819052604090912080549260a084901c9260c085901c81169260c886901c9260d087901c83169260d888901c169190871661125a57604051630d1b18db60e31b815260040160405180910390fd5b5091939550919395565b600080600061127487878761154d565b9760ff909416600a0a965092945050505050565b60008183106112975781611299565b825b9392505050565b6040517f5f259aba0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000ad131da4bddb40ebb5ceeaea87067553d431389590911690635f259aba906024015b602060405180830381865afa158015611325573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076591906117c2565b60008313611383576040517f53b798e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61139363ffffffff821683611849565b42106113cb576040517f16dd0ffb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6040517fd4eb5db00000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000ad131da4bddb40ebb5ceeaea87067553d43138959091169063d4eb5db090602401611308565b60005460ff1661072b5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610cc3565b6040517f3a41ec640000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000ad131da4bddb40ebb5ceeaea87067553d431389590911690633a41ec6490602401611308565b60005460ff161561072b5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610cc3565b600080846001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561158e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b291906117f9565b509194509092508491506107a59050576107a5828286611349565b80356001600160a01b03811681146111f357600080fd5b6000602082840312156115f657600080fd5b611299826115cd565b803563ffffffff811681146111f357600080fd5b60008060006060848603121561162857600080fd5b611631846115cd565b925061163f602085016115cd565b915061164d604085016115ff565b90509250925092565b8015158114610a5157600080fd5b6000806040838503121561167757600080fd5b611680836115cd565b9150602083013561169081611656565b809150509250929050565b600080604083850312156116ae57600080fd5b823591506116be602084016115cd565b90509250929050565b600080600080608085870312156116dd57600080fd5b6116e6856115cd565b93506116f4602086016115cd565b9250611702604086016115ff565b9150606085013561171281611656565b939692955090935050565b60008060006060848603121561173257600080fd5b83359250611742602085016115cd565b915061164d604085016115cd565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761076557610765611750565b60008261179a57634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156117b157600080fd5b815160ff8116811461129957600080fd5b6000602082840312156117d457600080fd5b815161129981611656565b805169ffffffffffffffffffff811681146111f357600080fd5b600080600080600060a0868803121561181157600080fd5b61181a866117df565b945060208601519350604086015192506060860151915061183d608087016117df565b90509295509295909350565b808201808211156107655761076561175056fea2646970667358221220558c278ec52a583228401fde267bafb0e2730e15e11d54e04c86f522f3d986db64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004b27b296273b72d7c7bfee1ace93dc081467c41b
-----Decoded View---------------
Arg [0] : addressProvider (address): 0x4b27b296273B72d7c7bfee1ACE93DC081467C41B
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000004b27b296273b72d7c7bfee1ace93dc081467c41b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.