Source Code
Overview
MNT Balance
MNT Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
InitOracle
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import '../common/library/InitErrors.sol';
import '../common/library/UncheckedIncrement.sol';
import {UnderACM} from '../common/UnderACM.sol';
import {IInitOracle, IBaseOracle} from '../interfaces/oracle/IInitOracle.sol';
import {Initializable} from '@openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol';
contract InitOracle is IInitOracle, UnderACM, Initializable {
using UncheckedIncrement for uint;
// constants
uint private constant ONE_E18 = 1e18;
bytes32 private constant GOVERNOR = keccak256('governor');
// storages
mapping(address => address) public primarySources; // @inheritdoc IInitOracle
mapping(address => address) public secondarySources; // @inheritdoc IInitOracle
mapping(address => uint) public maxPriceDeviations_e18; // @inheritdoc IInitOracle
// modifiers
modifier onlyGovernor() {
ACM.checkRole(GOVERNOR, msg.sender);
_;
}
// constructor
constructor(address _acm) UnderACM(_acm) {
_disableInitializers();
}
// initializer
/// @dev initialize the contract
function initialize() external initializer {}
// functions
/// @inheritdoc IBaseOracle
function getPrice_e36(address _token) public view returns (uint price_e36) {
bool isPrimarySourceValid;
bool isSecondarySourceValid;
uint primaryPrice_e36;
uint secondaryPrice_e36;
// get price from primary source
address primarySource = primarySources[_token];
_require(primarySource != address(0), Errors.PRIMARY_SOURCE_NOT_SET);
try IBaseOracle(primarySource).getPrice_e36(_token) returns (uint primaryPrice_e36_) {
primaryPrice_e36 = primaryPrice_e36_;
isPrimarySourceValid = true;
} catch {}
// get price from secondary source
address secondarySource = secondarySources[_token];
if (secondarySource != address(0)) {
try IBaseOracle(secondarySource).getPrice_e36(_token) returns (uint secondaryPrice_e36_) {
secondaryPrice_e36 = secondaryPrice_e36_;
isSecondarySourceValid = true;
} catch {}
}
// normal case: both sources are valid
// check that the prices are not too deviated
// abnormal case: one of the sources is invalid
// using the valid source - prioritize the primary source
// abnormal case: both sources are invalid
// revert
_require(isPrimarySourceValid || isSecondarySourceValid, Errors.NO_VALID_SOURCE);
if (isPrimarySourceValid && isSecondarySourceValid) {
// sort Price
(uint minPrice_e36, uint maxPrice_e36) = primaryPrice_e36 < secondaryPrice_e36
? (primaryPrice_e36, secondaryPrice_e36)
: (secondaryPrice_e36, primaryPrice_e36);
// check deviation
_require(
(maxPrice_e36 * ONE_E18) / minPrice_e36 <= maxPriceDeviations_e18[_token], Errors.TOO_MUCH_DEVIATION
);
}
price_e36 = isPrimarySourceValid ? primaryPrice_e36 : secondaryPrice_e36;
}
/// @inheritdoc IInitOracle
function getPrices_e36(address[] calldata _tokens) external view returns (uint[] memory prices_e36) {
prices_e36 = new uint[](_tokens.length);
for (uint i; i < _tokens.length; i = i.uinc()) {
prices_e36[i] = getPrice_e36(_tokens[i]);
}
}
/// @inheritdoc IInitOracle
function setPrimarySources(address[] calldata _tokens, address[] calldata _sources) external onlyGovernor {
_require(_tokens.length == _sources.length, Errors.ARRAY_LENGTH_MISMATCHED);
for (uint i; i < _tokens.length; i = i.uinc()) {
primarySources[_tokens[i]] = _sources[i];
emit SetPrimarySource(_tokens[i], _sources[i]);
}
}
/// @inheritdoc IInitOracle
function setSecondarySources(address[] calldata _tokens, address[] calldata _sources) external onlyGovernor {
_require(_tokens.length == _sources.length, Errors.ARRAY_LENGTH_MISMATCHED);
for (uint i; i < _tokens.length; i = i.uinc()) {
secondarySources[_tokens[i]] = _sources[i];
emit SetSecondarySource(_tokens[i], _sources[i]);
}
}
/// @inheritdoc IInitOracle
function setMaxPriceDeviations_e18(address[] calldata _tokens, uint[] calldata _maxPriceDeviations_e18)
external
onlyGovernor
{
_require(_tokens.length == _maxPriceDeviations_e18.length, Errors.ARRAY_LENGTH_MISMATCHED);
for (uint i; i < _tokens.length; i = i.uinc()) {
// sanity check
_require(_maxPriceDeviations_e18[i] >= ONE_E18, Errors.MAX_PRICE_DEVIATION_TOO_LOW);
maxPriceDeviations_e18[_tokens[i]] = _maxPriceDeviations_e18[i];
emit SetMaxPriceDeviation_e18(_tokens[i], _maxPriceDeviations_e18[i]);
}
}
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import {IAccessControlManager} from '../interfaces/common/IAccessControlManager.sol';
abstract contract UnderACM {
// immutables
IAccessControlManager public immutable ACM; // access control manager
// constructor
constructor(address _acm) {
ACM = IAccessControlManager(_acm);
}
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.1 <0.9.0;
// solhint-disable
/**
* @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are
* supported.
* Uses the default 'INC' prefix for the error code
*/
function _require(bool condition, uint errorCode) pure {
if (!condition) _revert(errorCode);
}
/**
* @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are
* supported.
*/
function _require(bool condition, uint errorCode, bytes3 prefix) pure {
if (!condition) _revert(errorCode, prefix);
}
/**
* @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported.
* Uses the default 'INC' prefix for the error code
*/
function _revert(uint errorCode) pure {
_revert(errorCode, 0x494e43); // This is the raw byte representation of "INC"
}
/**
* @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported.
*/
function _revert(uint errorCode, bytes3 prefix) pure {
uint prefixUint = uint(uint24(prefix));
// We're going to dynamically create a revert string based on the error code, with the following format:
// 'INC#{errorCode}'
// where the code is left-padded with zeroes to three digits (so they range from 000 to 999).
//
// We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a
// number (8 to 16 bits) than the individual string characters.
//
// The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a
// much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a
// safe place to rely on it without worrying about how its usage might affect e.g. memory contents.
assembly {
// First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999
// range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for
// the '0' character.
let units := add(mod(errorCode, 10), 0x30)
errorCode := div(errorCode, 10)
let tenths := add(mod(errorCode, 10), 0x30)
errorCode := div(errorCode, 10)
let hundreds := add(mod(errorCode, 10), 0x30)
// With the individual characters, we can now construct the full string.
// We first append the '#' character (0x23) to the prefix. In the case of 'INC', it results in 0x42414c23 ('INC#')
// Then, we shift this by 24 (to provide space for the 3 bytes of the error code), and add the
// characters to it, each shifted by a multiple of 8.
// The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits
// per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte
// array).
let formattedPrefix := shl(24, add(0x23, shl(8, prefixUint)))
let revertReason := shl(200, add(formattedPrefix, add(add(units, shl(8, tenths)), shl(16, hundreds))))
// We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded
// message will have the following layout:
// [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ]
// The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We
// also write zeroes to the next 28 bytes of memory, but those are about to be overwritten.
mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// Next is the offset to the location of the string, which will be placed immediately after (20 bytes away).
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// The string length is fixed: 7 characters.
mstore(0x24, 7)
// Finally, the string itself is stored.
mstore(0x44, revertReason)
// Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of
// the encoded message is therefore 4 + 32 + 32 + 32 = 100.
revert(0, 100)
}
}
library Errors {
// Common
uint internal constant ZERO_VALUE = 100;
uint internal constant NOT_INIT_CORE = 101;
uint internal constant SLIPPAGE_CONTROL = 102;
uint internal constant CALL_FAILED = 103;
uint internal constant NOT_OWNER = 104;
uint internal constant NOT_WNATIVE = 105;
uint internal constant ALREADY_SET = 106;
uint internal constant NOT_WHITELISTED = 107;
// Input
uint internal constant ARRAY_LENGTH_MISMATCHED = 200;
uint internal constant INPUT_TOO_LOW = 201;
uint internal constant INPUT_TOO_HIGH = 202;
uint internal constant INVALID_INPUT = 203;
uint internal constant INVALID_TOKEN_IN = 204;
uint internal constant INVALID_TOKEN_OUT = 205;
uint internal constant NOT_SORTED_OR_DUPLICATED_INPUT = 206;
// Core
uint internal constant POSITION_NOT_HEALTHY = 300;
uint internal constant POSITION_NOT_FOUND = 301;
uint internal constant LOCKED_MULTICALL = 302;
uint internal constant POSITION_HEALTHY = 303;
uint internal constant INVALID_HEALTH_AFTER_LIQUIDATION = 304;
uint internal constant FLASH_PAUSED = 305;
uint internal constant INVALID_FLASHLOAN = 306;
uint internal constant NOT_AUTHORIZED = 307;
uint internal constant INVALID_CALLBACK_ADDRESS = 308;
// Lending Pool
uint internal constant MINT_PAUSED = 400;
uint internal constant REDEEM_PAUSED = 401;
uint internal constant BORROW_PAUSED = 402;
uint internal constant REPAY_PAUSED = 403;
uint internal constant NOT_ENOUGH_CASH = 404;
uint internal constant INVALID_AMOUNT_TO_REPAY = 405;
uint internal constant SUPPLY_CAP_REACHED = 406;
uint internal constant BORROW_CAP_REACHED = 407;
// Config
uint internal constant INVALID_MODE = 500;
uint internal constant TOKEN_NOT_WHITELISTED = 501;
uint internal constant INVALID_FACTOR = 502;
// Position Manager
uint internal constant COLLATERALIZE_PAUSED = 600;
uint internal constant DECOLLATERALIZE_PAUSED = 601;
uint internal constant MAX_COLLATERAL_COUNT_REACHED = 602;
uint internal constant NOT_CONTAIN = 603;
uint internal constant ALREADY_COLLATERALIZED = 604;
// Oracle
uint internal constant NO_VALID_SOURCE = 700;
uint internal constant TOO_MUCH_DEVIATION = 701;
uint internal constant MAX_PRICE_DEVIATION_TOO_LOW = 702;
uint internal constant NO_PRICE_ID = 703;
uint internal constant PYTH_CONFIG_NOT_SET = 704;
uint internal constant DATAFEED_ID_NOT_SET = 705;
uint internal constant MAX_STALETIME_NOT_SET = 706;
uint internal constant MAX_STALETIME_EXCEEDED = 707;
uint internal constant PRIMARY_SOURCE_NOT_SET = 708;
// Risk Manager
uint internal constant DEBT_CEILING_EXCEEDED = 800;
// Misc
uint internal constant UNIMPLEMENTED = 999;
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
library UncheckedIncrement {
function uinc(uint self) internal pure returns (uint) {
unchecked {
return self + 1;
}
}
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
/// @title Access Control Manager Interface
interface IAccessControlManager {
/// @dev check the role of the user, revert against an unauthorized user.
/// @param _role keccak256 hash of role name
/// @param _user user address to check for the role
function checkRole(bytes32 _role, address _user) external;
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
/// @title Base Oracle Interface
interface IBaseOracle {
/// @dev return the value of the token as USD, multiplied by 1e36.
/// @param _token token address
/// @return price_e36 token price in 1e36
function getPrice_e36(address _token) external view returns (uint price_e36);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import {IBaseOracle} from './IBaseOracle.sol';
/// @title Init Oracle Interface
interface IInitOracle is IBaseOracle {
event SetPrimarySource(address indexed token, address oracle);
event SetSecondarySource(address indexed token, address oracle);
event SetMaxPriceDeviation_e18(address indexed token, uint maxPriceDeviation_e18);
/// @dev return the oracle token's primary source
/// @param _token token address
/// @return primarySource primary oracle address
function primarySources(address _token) external view returns (address primarySource);
/// @dev return the oracle token's secondary source
/// @param _token token address
/// @return secondarySource secoundary oracle address
function secondarySources(address _token) external view returns (address secondarySource);
/// @dev return the max price deviation between the primary and secondary sources
/// @param _token token address
/// @return maxPriceDeviation_e18 max price deviation in 1e18
function maxPriceDeviations_e18(address _token) external view returns (uint maxPriceDeviation_e18);
/// @dev return the price of the tokens in USD, multiplied by 1e36.
/// @param _tokens token address list
/// @return prices_e36 the token prices for each tokens
function getPrices_e36(address[] calldata _tokens) external view returns (uint[] memory prices_e36);
/// @dev set primary source for tokens
/// @param _tokens token address list
/// @param _sources the primary source address for each tokens
function setPrimarySources(address[] calldata _tokens, address[] calldata _sources) external;
/// @dev set secondary source for tokens
/// @param _tokens token address list
/// @param _sources the secondary source address for each tokens
function setSecondarySources(address[] calldata _tokens, address[] calldata _sources) external;
/// @dev set max price deviation between the primary and sercondary sources
/// @param _tokens token address list
/// @param _maxPriceDeviations_e18 the max price deviation in 1e18 for each tokens
function setMaxPriceDeviations_e18(address[] calldata _tokens, uint[] calldata _maxPriceDeviations_e18) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// 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 AddressUpgradeable {
/**
* @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);
}
}
}{
"evmVersion": "paris",
"libraries": {},
"metadata": {
"appendCBOR": true,
"bytecodeHash": "ipfs",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"@forge-std/=lib/forge-std/src/",
"@openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts copy/=lib/openzeppelin-contracts copy/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/"
]
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_acm","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"maxPriceDeviation_e18","type":"uint256"}],"name":"SetMaxPriceDeviation_e18","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"oracle","type":"address"}],"name":"SetPrimarySource","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"oracle","type":"address"}],"name":"SetSecondarySource","type":"event"},{"inputs":[],"name":"ACM","outputs":[{"internalType":"contract IAccessControlManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPrice_e36","outputs":[{"internalType":"uint256","name":"price_e36","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"getPrices_e36","outputs":[{"internalType":"uint256[]","name":"prices_e36","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxPriceDeviations_e18","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"primarySources","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"secondarySources","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_maxPriceDeviations_e18","type":"uint256[]"}],"name":"setMaxPriceDeviations_e18","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address[]","name":"_sources","type":"address[]"}],"name":"setPrimarySources","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address[]","name":"_sources","type":"address[]"}],"name":"setSecondarySources","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a060405234801561001057600080fd5b50604051610ef1380380610ef183398101604081905261002f91610109565b6001600160a01b03811660805261004461004a565b50610139565b600054610100900460ff16156100b65760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614610107576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60006020828403121561011b57600080fd5b81516001600160a01b038116811461013257600080fd5b9392505050565b608051610d88610169600039600081816101bf015281816102c4015281816104a101526109500152610d886000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806373f4af961161006657806373f4af96146101635780638129fc1c14610176578063d3284b8b1461017e578063f1ccc433146101a7578063f9b80da1146101ba57600080fd5b806323c452bc146100a3578063332aee01146100cc5780633c15c732146100fa57806343f747b71461010f5780636402b2c414610150575b600080fd5b6100b66100b1366004610b9e565b6101e1565b6040516100c39190610be0565b60405180910390f35b6100ec6100da366004610c24565b60036020526000908152604090205481565b6040519081526020016100c3565b61010d610108366004610c54565b610289565b005b61013861011d366004610c24565b6001602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016100c3565b61010d61015e366004610c54565b610466565b6100ec610171366004610c24565b61063c565b61010d610808565b61013861018c366004610c24565b6002602052600090815260409020546001600160a01b031681565b61010d6101b5366004610c54565b610915565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b60608167ffffffffffffffff8111156101fc576101fc610cc0565b604051908082528060200260200182016040528015610225578160200160208202803683370190505b50905060005b828110156102825761025d84848381811061024857610248610cd6565b90506020020160208101906101719190610c24565b82828151811061026f5761026f610cd6565b602090810291909101015260010161022b565b5092915050565b6040516312d9a6ad60e01b81527f1e46cebd6689d8c64011118478db0c61a89aa2646c860df401de476fbf37898360048201523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906312d9a6ad90604401600060405180830381600087803b15801561031057600080fd5b505af1158015610324573d6000803e3d6000fd5b506103369250505083821460c8610ae3565b60005b8381101561045f5782828281811061035357610353610cd6565b90506020020160208101906103689190610c24565b6002600087878581811061037e5761037e610cd6565b90506020020160208101906103939190610c24565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b031916929091169190911790558484828181106103d6576103d6610cd6565b90506020020160208101906103eb9190610c24565b6001600160a01b03167f6513ff7375b3e5e1c5b28cb654c1eee78450348a1903e328ffcfad0a0b71ff1f84848481811061042757610427610cd6565b905060200201602081019061043c9190610c24565b6040516001600160a01b03909116815260200160405180910390a2600101610339565b5050505050565b6040516312d9a6ad60e01b81527f1e46cebd6689d8c64011118478db0c61a89aa2646c860df401de476fbf37898360048201523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906312d9a6ad90604401600060405180830381600087803b1580156104ed57600080fd5b505af1158015610501573d6000803e3d6000fd5b506105139250505083821460c8610ae3565b60005b8381101561045f5782828281811061053057610530610cd6565b90506020020160208101906105459190610c24565b6001600087878581811061055b5761055b610cd6565b90506020020160208101906105709190610c24565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b031916929091169190911790558484828181106105b3576105b3610cd6565b90506020020160208101906105c89190610c24565b6001600160a01b03167f7a6b4a9b50d0c1e3c8b51ea56e8316f9ba60f18293220c84cc131193241591eb84848481811061060457610604610cd6565b90506020020160208101906106199190610c24565b6040516001600160a01b03909116815260200160405180910390a2600101610516565b6001600160a01b03808216600090815260016020526040812054909182918291829182911661066f8115156102c4610ae3565b6040516339fa57cb60e11b81526001600160a01b0388811660048301528216906373f4af9690602401602060405180830381865afa9250505080156106d1575060408051601f3d908101601f191682019092526106ce91810190610cec565b60015b156106dd576001955092505b6001600160a01b0380881660009081526002602052604090205416801561076c576040516339fa57cb60e11b81526001600160a01b0389811660048301528216906373f4af9690602401602060405180830381865afa925050508015610760575060408051601f3d908101601f1916820190925261075d91810190610cec565b60015b1561076c576001955092505b61078086806107785750855b6102bc610ae3565b85801561078a5750845b156107ef576000808486106107a05784866107a3565b85855b6001600160a01b038c1660009081526003602052604090205491935091506107ec90836107d8670de0b6b3a764000085610d05565b6107e29190610d30565b11156102bd610ae3565b50505b856107fa57826107fc565b835b98975050505050505050565b600054610100900460ff16158080156108285750600054600160ff909116105b806108425750303b158015610842575060005460ff166001145b6108a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff1916600117905580156108cc576000805461ff0019166101001790555b8015610912576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6040516312d9a6ad60e01b81527f1e46cebd6689d8c64011118478db0c61a89aa2646c860df401de476fbf37898360048201523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906312d9a6ad90604401600060405180830381600087803b15801561099c57600080fd5b505af11580156109b0573d6000803e3d6000fd5b506109c29250505083821460c8610ae3565b60005b8381101561045f576109fc670de0b6b3a76400008484848181106109eb576109eb610cd6565b9050602002013510156102be610ae3565b828282818110610a0e57610a0e610cd6565b9050602002013560036000878785818110610a2b57610a2b610cd6565b9050602002016020810190610a409190610c24565b6001600160a01b03168152602081019190915260400160002055848482818110610a6c57610a6c610cd6565b9050602002016020810190610a819190610c24565b6001600160a01b03167fe4a60fd452b19d95d983d6dc6238c14e69c5d69ebc14b04887feee8bfa6800d3848484818110610abd57610abd610cd6565b90506020020135604051610ad391815260200190565b60405180910390a26001016109c5565b81610af157610af181610af5565b5050565b62461bcd60e51b600090815260206004526007602452600a808304818106603090810160081b83860601918390049283060160101b0166494e43230000300160c81b60448190526109129262494e4360e81b9162494e4391606490fd5b60008083601f840112610b6457600080fd5b50813567ffffffffffffffff811115610b7c57600080fd5b6020830191508360208260051b8501011115610b9757600080fd5b9250929050565b60008060208385031215610bb157600080fd5b823567ffffffffffffffff811115610bc857600080fd5b610bd485828601610b52565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b81811015610c1857835183529284019291840191600101610bfc565b50909695505050505050565b600060208284031215610c3657600080fd5b81356001600160a01b0381168114610c4d57600080fd5b9392505050565b60008060008060408587031215610c6a57600080fd5b843567ffffffffffffffff80821115610c8257600080fd5b610c8e88838901610b52565b90965094506020870135915080821115610ca757600080fd5b50610cb487828801610b52565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215610cfe57600080fd5b5051919050565b8082028115828204841417610d2a57634e487b7160e01b600052601160045260246000fd5b92915050565b600082610d4d57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220485a3842629f5a779ffef83c507e08f368dd562069691d150651aa2a8dd1620964736f6c63430008130033000000000000000000000000ce3292ca5abbdfa1db02142a67cffc708530675a
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061009e5760003560e01c806373f4af961161006657806373f4af96146101635780638129fc1c14610176578063d3284b8b1461017e578063f1ccc433146101a7578063f9b80da1146101ba57600080fd5b806323c452bc146100a3578063332aee01146100cc5780633c15c732146100fa57806343f747b71461010f5780636402b2c414610150575b600080fd5b6100b66100b1366004610b9e565b6101e1565b6040516100c39190610be0565b60405180910390f35b6100ec6100da366004610c24565b60036020526000908152604090205481565b6040519081526020016100c3565b61010d610108366004610c54565b610289565b005b61013861011d366004610c24565b6001602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016100c3565b61010d61015e366004610c54565b610466565b6100ec610171366004610c24565b61063c565b61010d610808565b61013861018c366004610c24565b6002602052600090815260409020546001600160a01b031681565b61010d6101b5366004610c54565b610915565b6101387f000000000000000000000000ce3292ca5abbdfa1db02142a67cffc708530675a81565b60608167ffffffffffffffff8111156101fc576101fc610cc0565b604051908082528060200260200182016040528015610225578160200160208202803683370190505b50905060005b828110156102825761025d84848381811061024857610248610cd6565b90506020020160208101906101719190610c24565b82828151811061026f5761026f610cd6565b602090810291909101015260010161022b565b5092915050565b6040516312d9a6ad60e01b81527f1e46cebd6689d8c64011118478db0c61a89aa2646c860df401de476fbf37898360048201523360248201527f000000000000000000000000ce3292ca5abbdfa1db02142a67cffc708530675a6001600160a01b0316906312d9a6ad90604401600060405180830381600087803b15801561031057600080fd5b505af1158015610324573d6000803e3d6000fd5b506103369250505083821460c8610ae3565b60005b8381101561045f5782828281811061035357610353610cd6565b90506020020160208101906103689190610c24565b6002600087878581811061037e5761037e610cd6565b90506020020160208101906103939190610c24565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b031916929091169190911790558484828181106103d6576103d6610cd6565b90506020020160208101906103eb9190610c24565b6001600160a01b03167f6513ff7375b3e5e1c5b28cb654c1eee78450348a1903e328ffcfad0a0b71ff1f84848481811061042757610427610cd6565b905060200201602081019061043c9190610c24565b6040516001600160a01b03909116815260200160405180910390a2600101610339565b5050505050565b6040516312d9a6ad60e01b81527f1e46cebd6689d8c64011118478db0c61a89aa2646c860df401de476fbf37898360048201523360248201527f000000000000000000000000ce3292ca5abbdfa1db02142a67cffc708530675a6001600160a01b0316906312d9a6ad90604401600060405180830381600087803b1580156104ed57600080fd5b505af1158015610501573d6000803e3d6000fd5b506105139250505083821460c8610ae3565b60005b8381101561045f5782828281811061053057610530610cd6565b90506020020160208101906105459190610c24565b6001600087878581811061055b5761055b610cd6565b90506020020160208101906105709190610c24565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b031916929091169190911790558484828181106105b3576105b3610cd6565b90506020020160208101906105c89190610c24565b6001600160a01b03167f7a6b4a9b50d0c1e3c8b51ea56e8316f9ba60f18293220c84cc131193241591eb84848481811061060457610604610cd6565b90506020020160208101906106199190610c24565b6040516001600160a01b03909116815260200160405180910390a2600101610516565b6001600160a01b03808216600090815260016020526040812054909182918291829182911661066f8115156102c4610ae3565b6040516339fa57cb60e11b81526001600160a01b0388811660048301528216906373f4af9690602401602060405180830381865afa9250505080156106d1575060408051601f3d908101601f191682019092526106ce91810190610cec565b60015b156106dd576001955092505b6001600160a01b0380881660009081526002602052604090205416801561076c576040516339fa57cb60e11b81526001600160a01b0389811660048301528216906373f4af9690602401602060405180830381865afa925050508015610760575060408051601f3d908101601f1916820190925261075d91810190610cec565b60015b1561076c576001955092505b61078086806107785750855b6102bc610ae3565b85801561078a5750845b156107ef576000808486106107a05784866107a3565b85855b6001600160a01b038c1660009081526003602052604090205491935091506107ec90836107d8670de0b6b3a764000085610d05565b6107e29190610d30565b11156102bd610ae3565b50505b856107fa57826107fc565b835b98975050505050505050565b600054610100900460ff16158080156108285750600054600160ff909116105b806108425750303b158015610842575060005460ff166001145b6108a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff1916600117905580156108cc576000805461ff0019166101001790555b8015610912576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6040516312d9a6ad60e01b81527f1e46cebd6689d8c64011118478db0c61a89aa2646c860df401de476fbf37898360048201523360248201527f000000000000000000000000ce3292ca5abbdfa1db02142a67cffc708530675a6001600160a01b0316906312d9a6ad90604401600060405180830381600087803b15801561099c57600080fd5b505af11580156109b0573d6000803e3d6000fd5b506109c29250505083821460c8610ae3565b60005b8381101561045f576109fc670de0b6b3a76400008484848181106109eb576109eb610cd6565b9050602002013510156102be610ae3565b828282818110610a0e57610a0e610cd6565b9050602002013560036000878785818110610a2b57610a2b610cd6565b9050602002016020810190610a409190610c24565b6001600160a01b03168152602081019190915260400160002055848482818110610a6c57610a6c610cd6565b9050602002016020810190610a819190610c24565b6001600160a01b03167fe4a60fd452b19d95d983d6dc6238c14e69c5d69ebc14b04887feee8bfa6800d3848484818110610abd57610abd610cd6565b90506020020135604051610ad391815260200190565b60405180910390a26001016109c5565b81610af157610af181610af5565b5050565b62461bcd60e51b600090815260206004526007602452600a808304818106603090810160081b83860601918390049283060160101b0166494e43230000300160c81b60448190526109129262494e4360e81b9162494e4391606490fd5b60008083601f840112610b6457600080fd5b50813567ffffffffffffffff811115610b7c57600080fd5b6020830191508360208260051b8501011115610b9757600080fd5b9250929050565b60008060208385031215610bb157600080fd5b823567ffffffffffffffff811115610bc857600080fd5b610bd485828601610b52565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b81811015610c1857835183529284019291840191600101610bfc565b50909695505050505050565b600060208284031215610c3657600080fd5b81356001600160a01b0381168114610c4d57600080fd5b9392505050565b60008060008060408587031215610c6a57600080fd5b843567ffffffffffffffff80821115610c8257600080fd5b610c8e88838901610b52565b90965094506020870135915080821115610ca757600080fd5b50610cb487828801610b52565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215610cfe57600080fd5b5051919050565b8082028115828204841417610d2a57634e487b7160e01b600052601160045260246000fd5b92915050565b600082610d4d57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220485a3842629f5a779ffef83c507e08f368dd562069691d150651aa2a8dd1620964736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ce3292ca5abbdfa1db02142a67cffc708530675a
-----Decoded View---------------
Arg [0] : _acm (address): 0xCE3292cA5AbbdFA1Db02142A67CFFc708530675a
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ce3292ca5abbdfa1db02142a67cffc708530675a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MNT
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.