ETH Price: $2,940.19 (+0.51%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Amount:Between 1-100k
Reset Filter

Transaction Hash
Method
Block
From
To

There are no matching entries

Update your filters to view other transactions

Amount:Between 1-100k
Reset Filter

Advanced mode:
Parent Transaction Hash Method Block
From
To

There are no matching entries

Update your filters to view other transactions

View All Internal Transactions
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ChainlinkOracle

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.25;

import "../interfaces/oracles/IChainlinkOracle.sol";

import "../libraries/external/FullMath.sol";

contract ChainlinkOracle is IChainlinkOracle {
    /// @inheritdoc IChainlinkOracle
    uint256 public constant Q96 = 2 ** 96;

    /// @inheritdoc IChainlinkOracle
    mapping(address => address) public baseTokens;

    mapping(address => mapping(address => AggregatorData))
        private _aggregatorsData;

    /// @inheritdoc IChainlinkOracle
    function aggregatorsData(
        address vault,
        address token
    ) external view returns (AggregatorData memory) {
        return _aggregatorsData[vault][token];
    }

    /// @inheritdoc IChainlinkOracle
    function setBaseToken(address vault, address baseToken) external {
        IDefaultAccessControl(vault).requireAdmin(msg.sender);
        baseTokens[vault] = baseToken;
        emit ChainlinkOracleSetBaseToken(vault, baseToken, block.timestamp);
    }

    /// @inheritdoc IChainlinkOracle
    function setChainlinkOracles(
        address vault,
        address[] calldata tokens,
        AggregatorData[] calldata data_
    ) external {
        IDefaultAccessControl(vault).requireAdmin(msg.sender);
        if (tokens.length != data_.length) revert InvalidLength();
        for (uint256 i = 0; i < tokens.length; i++) {
            if (data_[i].aggregatorV3 == address(0)) continue;
            _validateAndGetPrice(data_[i]);
        }
        for (uint256 i = 0; i < tokens.length; i++) {
            _aggregatorsData[vault][tokens[i]] = data_[i];
        }
        emit ChainlinkOracleSetChainlinkOracles(
            vault,
            tokens,
            data_,
            block.timestamp
        );
    }

    function _validateAndGetPrice(
        AggregatorData memory data
    ) private view returns (uint256 answer, uint8 decimals) {
        if (data.aggregatorV3 == address(0)) revert AddressZero();
        (, int256 signedAnswer, , uint256 lastTimestamp, ) = IAggregatorV3(
            data.aggregatorV3
        ).latestRoundData();
        // The roundId and latestRound are not used in the validation process to ensure compatibility
        // with various custom aggregator implementations that may handle these parameters differently
        if (signedAnswer < 0) revert InvalidOracleData();
        answer = uint256(signedAnswer);
        if (block.timestamp - data.maxAge > lastTimestamp) revert StaleOracle();
        decimals = IAggregatorV3(data.aggregatorV3).decimals();
    }

    /// @inheritdoc IChainlinkOracle
    function getPrice(
        address vault,
        address token
    ) public view returns (uint256 answer, uint8 decimals) {
        return _validateAndGetPrice(_aggregatorsData[vault][token]);
    }

    /// @inheritdoc IPriceOracle
    function priceX96(
        address vault,
        address token
    ) external view returns (uint256 priceX96_) {
        if (vault == address(0)) revert AddressZero();
        if (token == address(0)) revert AddressZero();
        address baseToken = baseTokens[vault];
        if (baseToken == address(0)) revert AddressZero();
        if (token == baseToken) return Q96;
        (uint256 tokenPrice, uint8 decimals) = getPrice(vault, token);
        (uint256 baseTokenPrice, uint8 baseDecimals) = getPrice(
            vault,
            baseToken
        );

        priceX96_ = FullMath.mulDiv(
            tokenPrice *
                10 ** (baseDecimals + IERC20Metadata(baseToken).decimals()),
            Q96,
            baseTokenPrice * 10 ** (decimals + IERC20Metadata(token).decimals())
        );
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.25;

import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

import "../utils/IDefaultAccessControl.sol";
import "../external/chainlink/IAggregatorV3.sol";

import "./IPriceOracle.sol";

/**
 * @title IChainlinkOracle
 * @notice Interface defining a price oracle that uses Chainlink data.
 */
interface IChainlinkOracle is IPriceOracle {
    /// @dev Errors
    error AddressZero();
    error InvalidLength();
    error Forbidden();
    error StaleOracle();
    error InvalidOracleData();

    /// @notice Struct containing Chainlink oracle data.
    /// @param aggregatorV3 The address of the Chainlink aggregator.
    /// @param maxAge The maximum allowable age for an oracle result before it's considered stale.
    struct AggregatorData {
        address aggregatorV3;
        uint256 maxAge;
    }

    /**
     * @notice Returns the constant Q96 used for ratio calculations with 96-bit precision.
     * @return uint256 The value of Q96 (2^96) for ratio calculations.
     */
    function Q96() external view returns (uint256);

    /**
     * @notice Returns the Chainlink price aggregator address for a specific vault and token.
     * @param vault The address of the vault.
     * @param token The address of the token.
     * @return data The Chainlink oracle data for the token.
     */
    function aggregatorsData(
        address vault,
        address token
    ) external view returns (AggregatorData memory data);

    /**
     * @notice Returns the base token associated with a specific vault.
     * @param vault The address of the vault.
     * @return address of the base token.
     */
    function baseTokens(address vault) external view returns (address);

    /**
     * @notice Sets the base token for a specific vault.
     * @param vault The address of the vault to set the base token for.
     * @param baseToken The address of the base token to associate with the vault.
     */
    function setBaseToken(address vault, address baseToken) external;

    /**
     * @notice Sets Chainlink price oracles for a given vault and an array of tokens.
     * @param vault The address of the vault to associate the tokens and oracles with.
     * @param tokens An array of token addresses that require price data.
     * @param aggregatorsData An array of Chainlink oracle addresses set with max allowed ages for the tokens.
     * @dev Both arrays should have the same length.
     */
    function setChainlinkOracles(
        address vault,
        address[] memory tokens,
        AggregatorData[] memory aggregatorsData
    ) external;

    /**
     * @notice Retrieves the latest price for a specific token from a given vault's associated Chainlink oracle.
     * @param vault The address of the vault requesting the price.
     * @param token The address of the token to get the price for.
     * @return answer The latest price of the token.
     * @return decimals The number of decimals used by the Chainlink oracle for this price.
     * @dev Reverts with `StaleOracle` if the price data is too old.
     */
    function getPrice(
        address vault,
        address token
    ) external view returns (uint256 answer, uint8 decimals);

    /**
     * @notice Emitted when the base token is set for a specific vault in the Chainlink Oracle.
     * @param vault The address of the vault for which the base token is set.
     * @param baseToken The address of the base token set for the vault.
     * @param timestamp The timestamp when the base token is set.
     */
    event ChainlinkOracleSetBaseToken(
        address indexed vault,
        address baseToken,
        uint256 timestamp
    );

    /**
     * @notice Emitted when Chainlink oracles are set for a specific vault in the Chainlink Oracle.
     * @param vault The address of the vault for which Chainlink oracles are set.
     * @param tokens An array of token addresses for which Chainlink oracles are set.
     * @param aggregatorsData An array of Chainlink oracle addresses set with max allowed ages for the tokens.
     * @param timestamp The timestamp when Chainlink oracles are set.
     */
    event ChainlinkOracleSetChainlinkOracles(
        address indexed vault,
        address[] tokens,
        AggregatorData[] aggregatorsData,
        uint256 timestamp
    );
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
    /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
    function mulDiv(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        // diff: original lib works under 0.7.6 with overflows enabled
        unchecked {
            // 512-bit multiply [prod1 prod0] = a * b
            // Compute the product mod 2**256 and mod 2**256 - 1
            // then use the Chinese Remainder Theorem to reconstruct
            // the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2**256 + prod0
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(a, b, not(0))
                prod0 := mul(a, b)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division
            if (prod1 == 0) {
                require(denominator > 0);
                assembly {
                    result := div(prod0, denominator)
                }
                return result;
            }

            // Make sure the result is less than 2**256.
            // Also prevents denominator == 0
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0]
            // Compute remainder using mulmod
            uint256 remainder;
            assembly {
                remainder := mulmod(a, b, denominator)
            }
            // Subtract 256 bit number from 512 bit number
            assembly {
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator
            // Compute largest power of two divisor of denominator.
            // Always >= 1.
            // diff: original uint256 twos = -denominator & denominator;
            uint256 twos = uint256(-int256(denominator)) & denominator;
            // Divide denominator by power of two
            assembly {
                denominator := div(denominator, twos)
            }

            // Divide [prod1 prod0] by the factors of two
            assembly {
                prod0 := div(prod0, twos)
            }
            // Shift in bits from prod1 into prod0. For this we need
            // to flip `twos` such that it is 2**256 / twos.
            // If twos is zero, then it becomes one
            assembly {
                twos := add(div(sub(0, twos), twos), 1)
            }
            prod0 |= prod1 * twos;

            // Invert denominator mod 2**256
            // Now that denominator is an odd number, it has an inverse
            // modulo 2**256 such that denominator * inv = 1 mod 2**256.
            // Compute the inverse by starting with a seed that is correct
            // correct for four bits. That is, denominator * inv = 1 mod 2**4
            uint256 inv = (3 * denominator) ^ 2;
            // Now use Newton-Raphson iteration to improve the precision.
            // Thanks to Hensel's lifting lemma, this also works in modular
            // arithmetic, doubling the correct bits in each step.
            inv *= 2 - denominator * inv; // inverse mod 2**8
            inv *= 2 - denominator * inv; // inverse mod 2**16
            inv *= 2 - denominator * inv; // inverse mod 2**32
            inv *= 2 - denominator * inv; // inverse mod 2**64
            inv *= 2 - denominator * inv; // inverse mod 2**128
            inv *= 2 - denominator * inv; // inverse mod 2**256

            // Because the division is now exact we can divide by multiplying
            // with the modular inverse of denominator. This will give us the
            // correct result modulo 2**256. Since the precoditions guarantee
            // that the outcome is less than 2**256, this is the final result.
            // We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inv;
            return result;
        }
    }

    /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    function mulDivRoundingUp(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        // diff: original lib works under 0.7.6 with overflows enabled
        unchecked {
            result = mulDiv(a, b, denominator);
            if (mulmod(a, b, denominator) > 0) {
                require(result < type(uint256).max);
                result++;
            }
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol";

/// @notice This is a default access control with 3 roles:
///
/// - ADMIN: allowed to do anything
/// - ADMIN_DELEGATE: allowed to do anything except assigning ADMIN and ADMIN_DELEGATE roles
/// - OPERATOR: low-privileged role, generally keeper or some other bot
interface IDefaultAccessControl is IAccessControlEnumerable {
    error Forbidden();
    error AddressZero();

    function OPERATOR() external view returns (bytes32);

    function ADMIN_ROLE() external view returns (bytes32);

    function ADMIN_DELEGATE_ROLE() external view returns (bytes32);

    /// @notice Checks that the address is contract admin.
    /// @param who Address to check
    /// @return `true` if who is admin, `false` otherwise
    function isAdmin(address who) external view returns (bool);

    /// @notice Checks that the address is contract admin.
    /// @param who Address to check
    /// @return `true` if who is operator, `false` otherwise
    function isOperator(address who) external view returns (bool);

    /// @notice Checks that the address is contract admin.
    /// @param who Address to check
    /// @dev throws Forbbiden() if the sender does not have the admin or admin_delegate role
    function requireAdmin(address who) external view;

    /// @notice Checks that the address is contract admin.
    /// @param who Address to check
    /// @dev throws Forbbiden() if the sender has no roles
    function requireAtLeastOperator(address who) external view;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

interface IAggregatorV3 {
    function decimals() external view returns (uint8);

    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
}

File 7 of 10 : IPriceOracle.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.25;

/**
 * @title IPriceOracle
 * @notice Interface defining a standard price oracle that provides token prices in 96-bit precision.
 */
interface IPriceOracle {
    /**
     * @notice Returns the price of a specific token relative to the base token of the given vault, expressed in 96-bit precision.
     * @param vault The address of the vault requesting the price.
     * @param token The address of the token to calculate the price for.
     * @return priceX96_ The price of the token relative to the base token, using 96-bit precision.
     * @dev Implementations should ensure prices are accurate and may involve external oracle data.
     *      Reverts with an appropriate error if the price cannot be provided.
     */
    function priceX96(
        address vault,
        address token
    ) external view returns (uint256 priceX96_);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "../IAccessControl.sol";

/**
 * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
 */
interface IAccessControlEnumerable is IAccessControl {
    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) external view returns (address);

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@symbiotic/=lib/core/src/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200,
    "details": {
      "yul": true,
      "yulDetails": {
        "stackAllocation": true
      }
    }
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"Forbidden","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"InvalidOracleData","type":"error"},{"inputs":[],"name":"StaleOracle","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"baseToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ChainlinkOracleSetBaseToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"components":[{"internalType":"address","name":"aggregatorV3","type":"address"},{"internalType":"uint256","name":"maxAge","type":"uint256"}],"indexed":false,"internalType":"struct IChainlinkOracle.AggregatorData[]","name":"aggregatorsData","type":"tuple[]"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ChainlinkOracleSetChainlinkOracles","type":"event"},{"inputs":[],"name":"Q96","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"aggregatorsData","outputs":[{"components":[{"internalType":"address","name":"aggregatorV3","type":"address"},{"internalType":"uint256","name":"maxAge","type":"uint256"}],"internalType":"struct IChainlinkOracle.AggregatorData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"baseTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"answer","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"priceX96","outputs":[{"internalType":"uint256","name":"priceX96_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"baseToken","type":"address"}],"name":"setBaseToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"components":[{"internalType":"address","name":"aggregatorV3","type":"address"},{"internalType":"uint256","name":"maxAge","type":"uint256"}],"internalType":"struct IChainlinkOracle.AggregatorData[]","name":"data_","type":"tuple[]"}],"name":"setChainlinkOracles","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052348015600f57600080fd5b50610da48061001f6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80634ef7f1f41161005b5780634ef7f1f4146101185780635ba208f71461012d578063ac41865a14610140578063e6f03d1d1461016a57600080fd5b806302eba0941461008257806323adf0ed146100c857806340792465146100ff575b600080fd5b6100ab6100903660046108e4565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100db6100d6366004610901565b61017d565b6040805182516001600160a01b0316815260209283015192810192909252016100bf565b61010a600160601b81565b6040519081526020016100bf565b61012b610126366004610901565b6101cf565b005b61012b61013b36600461097f565b610290565b61015361014e366004610901565b610476565b6040805192835260ff9091166020830152016100bf565b61010a610178366004610901565b6104cc565b604080518082018252600080825260209182018190526001600160a01b038581168252600180845284832086831684528452918490208451808601909552805490911684520154908201525b92915050565b604051632abb908560e11b81523360048201526001600160a01b03831690635577210a9060240160006040518083038186803b15801561020e57600080fd5b505afa158015610222573d6000803e3d6000fd5b505050506001600160a01b038281166000818152602081815260409182902080546001600160a01b03191694861694851790558151938452429084015290917fb6506fd1712cc8abb65a6f88ec7441df50f4e7e4aea7e99230816c3567b5d8c1910160405180910390a25050565b604051632abb908560e11b81523360048201526001600160a01b03861690635577210a9060240160006040518083038186803b1580156102cf57600080fd5b505afa1580156102e3573d6000803e3d6000fd5b50505083821490506103085760405163251f56a160e21b815260040160405180910390fd5b60005b8381101561038657600083838381811061032757610327610a33565b61033d92602060409092020190810191506108e4565b6001600160a01b03161461037e5761037b83838381811061036057610360610a33565b9050604002018036038101906103769190610a49565b6106b8565b50505b60010161030b565b5060005b83811015610425578282828181106103a4576103a4610a33565b90506040020160016000886001600160a01b03166001600160a01b0316815260200190815260200160002060008787858181106103e3576103e3610a33565b90506020020160208101906103f891906108e4565b6001600160a01b03168152602081019190915260400160002061041b8282610aaf565b505060010161038a565b50846001600160a01b03167f6cde280d4e0537a3e3575c6e4c3f9f0eee9ddda245b128f36a5c8c2d7b9b24ff8585858542604051610467959493929190610ae5565b60405180910390a25050505050565b6001600160a01b038083166000908152600160208181526040808420868616855282528084208151808301909252805490951681529390910154908301529081906104c0906106b8565b915091505b9250929050565b60006001600160a01b0383166104f557604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b03821661051c57604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b03808416600090815260208190526040902054168061055557604051639fabe1c160e01b815260040160405180910390fd5b806001600160a01b0316836001600160a01b03160361057b57600160601b9150506101c9565b6000806105888686610476565b915091506000806105998886610476565b915091506106ac856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106029190610b90565b61060c9083610bc9565b61061790600a610cc6565b6106219086610cd5565b600160601b896001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106889190610b90565b6106929087610bc9565b61069d90600a610cc6565b6106a79086610cd5565b610819565b98975050505050505050565b805160009081906001600160a01b03166106e557604051639fabe1c160e01b815260040160405180910390fd5b60008084600001516001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190610d0b565b509350509250506000821215610777576040516378de663960e11b815260040160405180910390fd5b8193508085602001514261078b9190610d5b565b11156107aa576040516388cce42960e01b815260040160405180910390fd5b84600001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108109190610b90565b92505050915091565b6000808060001985870985870292508281108382030391505080600003610852576000841161084757600080fd5b5082900490506108c5565b80841161085e57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b6001600160a01b03811681146108e157600080fd5b50565b6000602082840312156108f657600080fd5b81356108c5816108cc565b6000806040838503121561091457600080fd5b823561091f816108cc565b9150602083013561092f816108cc565b809150509250929050565b60008083601f84011261094c57600080fd5b50813567ffffffffffffffff81111561096457600080fd5b6020830191508360208260061b85010111156104c557600080fd5b60008060008060006060868803121561099757600080fd5b85356109a2816108cc565b9450602086013567ffffffffffffffff808211156109bf57600080fd5b818801915088601f8301126109d357600080fd5b8135818111156109e257600080fd5b8960208260051b85010111156109f757600080fd5b602083019650809550506040880135915080821115610a1557600080fd5b50610a228882890161093a565b969995985093965092949392505050565b634e487b7160e01b600052603260045260246000fd5b600060408284031215610a5b57600080fd5b6040516040810181811067ffffffffffffffff82111715610a8c57634e487b7160e01b600052604160045260246000fd5b6040528235610a9a816108cc565b81526020928301359281019290925250919050565b8135610aba816108cc565b81546001600160a01b0319166001600160a01b03919091161781556020919091013560019190910155565b6060808252810185905260008660808301825b88811015610b28578235610b0b816108cc565b6001600160a01b0316825260209283019290910190600101610af8565b5083810360208581019190915286825291508690820160005b87811015610b79578235610b54816108cc565b6001600160a01b03168252828401358483015260409283019290910190600101610b41565b508093505050508260408301529695505050505050565b600060208284031215610ba257600080fd5b815160ff811681146108c557600080fd5b634e487b7160e01b600052601160045260246000fd5b60ff81811683821601908111156101c9576101c9610bb3565b600181815b80851115610c1d578160001904821115610c0357610c03610bb3565b80851615610c1057918102915b93841c9390800290610be7565b509250929050565b600082610c34575060016101c9565b81610c41575060006101c9565b8160018114610c575760028114610c6157610c7d565b60019150506101c9565b60ff841115610c7257610c72610bb3565b50506001821b6101c9565b5060208310610133831016604e8410600b8410161715610ca0575081810a6101c9565b610caa8383610be2565b8060001904821115610cbe57610cbe610bb3565b029392505050565b60006108c560ff841683610c25565b80820281158282048414176101c9576101c9610bb3565b805169ffffffffffffffffffff81168114610d0657600080fd5b919050565b600080600080600060a08688031215610d2357600080fd5b610d2c86610cec565b9450602086015193506040860151925060608601519150610d4f60808701610cec565b90509295509295909350565b818103818111156101c9576101c9610bb356fea2646970667358221220466c550cd636c178b808515e41aa16b9b8933bf6d16288170067f614098605fa64736f6c63430008190033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80634ef7f1f41161005b5780634ef7f1f4146101185780635ba208f71461012d578063ac41865a14610140578063e6f03d1d1461016a57600080fd5b806302eba0941461008257806323adf0ed146100c857806340792465146100ff575b600080fd5b6100ab6100903660046108e4565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100db6100d6366004610901565b61017d565b6040805182516001600160a01b0316815260209283015192810192909252016100bf565b61010a600160601b81565b6040519081526020016100bf565b61012b610126366004610901565b6101cf565b005b61012b61013b36600461097f565b610290565b61015361014e366004610901565b610476565b6040805192835260ff9091166020830152016100bf565b61010a610178366004610901565b6104cc565b604080518082018252600080825260209182018190526001600160a01b038581168252600180845284832086831684528452918490208451808601909552805490911684520154908201525b92915050565b604051632abb908560e11b81523360048201526001600160a01b03831690635577210a9060240160006040518083038186803b15801561020e57600080fd5b505afa158015610222573d6000803e3d6000fd5b505050506001600160a01b038281166000818152602081815260409182902080546001600160a01b03191694861694851790558151938452429084015290917fb6506fd1712cc8abb65a6f88ec7441df50f4e7e4aea7e99230816c3567b5d8c1910160405180910390a25050565b604051632abb908560e11b81523360048201526001600160a01b03861690635577210a9060240160006040518083038186803b1580156102cf57600080fd5b505afa1580156102e3573d6000803e3d6000fd5b50505083821490506103085760405163251f56a160e21b815260040160405180910390fd5b60005b8381101561038657600083838381811061032757610327610a33565b61033d92602060409092020190810191506108e4565b6001600160a01b03161461037e5761037b83838381811061036057610360610a33565b9050604002018036038101906103769190610a49565b6106b8565b50505b60010161030b565b5060005b83811015610425578282828181106103a4576103a4610a33565b90506040020160016000886001600160a01b03166001600160a01b0316815260200190815260200160002060008787858181106103e3576103e3610a33565b90506020020160208101906103f891906108e4565b6001600160a01b03168152602081019190915260400160002061041b8282610aaf565b505060010161038a565b50846001600160a01b03167f6cde280d4e0537a3e3575c6e4c3f9f0eee9ddda245b128f36a5c8c2d7b9b24ff8585858542604051610467959493929190610ae5565b60405180910390a25050505050565b6001600160a01b038083166000908152600160208181526040808420868616855282528084208151808301909252805490951681529390910154908301529081906104c0906106b8565b915091505b9250929050565b60006001600160a01b0383166104f557604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b03821661051c57604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b03808416600090815260208190526040902054168061055557604051639fabe1c160e01b815260040160405180910390fd5b806001600160a01b0316836001600160a01b03160361057b57600160601b9150506101c9565b6000806105888686610476565b915091506000806105998886610476565b915091506106ac856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106029190610b90565b61060c9083610bc9565b61061790600a610cc6565b6106219086610cd5565b600160601b896001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106889190610b90565b6106929087610bc9565b61069d90600a610cc6565b6106a79086610cd5565b610819565b98975050505050505050565b805160009081906001600160a01b03166106e557604051639fabe1c160e01b815260040160405180910390fd5b60008084600001516001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190610d0b565b509350509250506000821215610777576040516378de663960e11b815260040160405180910390fd5b8193508085602001514261078b9190610d5b565b11156107aa576040516388cce42960e01b815260040160405180910390fd5b84600001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108109190610b90565b92505050915091565b6000808060001985870985870292508281108382030391505080600003610852576000841161084757600080fd5b5082900490506108c5565b80841161085e57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b6001600160a01b03811681146108e157600080fd5b50565b6000602082840312156108f657600080fd5b81356108c5816108cc565b6000806040838503121561091457600080fd5b823561091f816108cc565b9150602083013561092f816108cc565b809150509250929050565b60008083601f84011261094c57600080fd5b50813567ffffffffffffffff81111561096457600080fd5b6020830191508360208260061b85010111156104c557600080fd5b60008060008060006060868803121561099757600080fd5b85356109a2816108cc565b9450602086013567ffffffffffffffff808211156109bf57600080fd5b818801915088601f8301126109d357600080fd5b8135818111156109e257600080fd5b8960208260051b85010111156109f757600080fd5b602083019650809550506040880135915080821115610a1557600080fd5b50610a228882890161093a565b969995985093965092949392505050565b634e487b7160e01b600052603260045260246000fd5b600060408284031215610a5b57600080fd5b6040516040810181811067ffffffffffffffff82111715610a8c57634e487b7160e01b600052604160045260246000fd5b6040528235610a9a816108cc565b81526020928301359281019290925250919050565b8135610aba816108cc565b81546001600160a01b0319166001600160a01b03919091161781556020919091013560019190910155565b6060808252810185905260008660808301825b88811015610b28578235610b0b816108cc565b6001600160a01b0316825260209283019290910190600101610af8565b5083810360208581019190915286825291508690820160005b87811015610b79578235610b54816108cc565b6001600160a01b03168252828401358483015260409283019290910190600101610b41565b508093505050508260408301529695505050505050565b600060208284031215610ba257600080fd5b815160ff811681146108c557600080fd5b634e487b7160e01b600052601160045260246000fd5b60ff81811683821601908111156101c9576101c9610bb3565b600181815b80851115610c1d578160001904821115610c0357610c03610bb3565b80851615610c1057918102915b93841c9390800290610be7565b509250929050565b600082610c34575060016101c9565b81610c41575060006101c9565b8160018114610c575760028114610c6157610c7d565b60019150506101c9565b60ff841115610c7257610c72610bb3565b50506001821b6101c9565b5060208310610133831016604e8410600b8410161715610ca0575081810a6101c9565b610caa8383610be2565b8060001904821115610cbe57610cbe610bb3565b029392505050565b60006108c560ff841683610c25565b80820281158282048414176101c9576101c9610bb3565b805169ffffffffffffffffffff81168114610d0657600080fd5b919050565b600080600080600060a08688031215610d2357600080fd5b610d2c86610cec565b9450602086015193506040860151925060608601519150610d4f60808701610cec565b90509295509295909350565b818103818111156101c9576101c9610bb356fea2646970667358221220466c550cd636c178b808515e41aa16b9b8933bf6d16288170067f614098605fa64736f6c63430008190033

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
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.