MNT Price: $0.72 (+3.45%)

Contract

0x7928419135cE5427858F0F5c0cbA3151b9b14f81
 

Overview

MNT Balance

Mantle Mainnet Network LogoMantle Mainnet Network LogoMantle Mainnet Network Logo0 MNT

MNT Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
InitOracle

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// 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]);
        }
    }
}

File 2 of 9 : UnderACM.sol
// 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);
    }
}

File 3 of 9 : InitErrors.sol
// 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;
}

File 4 of 9 : UncheckedIncrement.sol
// 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);
        }
    }
}

Settings
{
  "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

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"}]

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


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.