ETH Price: $3,217.15 (-2.14%)

Contract

0x1Dc89c28e59d142688D65Bd7b22C4Fd40C2cC06d
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Chainlink Or...213704582024-12-10 6:57:1141 days ago1733813831IN
0x1Dc89c28...40C2cC06d
0 ETH0.0017600512.56304527
Set Base Token213704572024-12-10 6:56:5941 days ago1733813819IN
0x1Dc89c28...40C2cC06d
0 ETH0.0007143512.5894977
Set Chainlink Or...213060022024-12-01 6:55:1150 days ago1733036111IN
0x1Dc89c28...40C2cC06d
0 ETH0.001056617.53574702
Set Base Token213060012024-12-01 6:54:5950 days ago1733036099IN
0x1Dc89c28...40C2cC06d
0 ETH0.000416417.33873137
Set Chainlink Or...205354562024-08-15 17:15:11158 days ago1723742111IN
0x1Dc89c28...40C2cC06d
0 ETH0.000633944.52104351
Set Base Token205354552024-08-15 17:14:59158 days ago1723742099IN
0x1Dc89c28...40C2cC06d
0 ETH0.000269734.75328925
Set Chainlink Or...205349732024-08-15 15:37:59158 days ago1723736279IN
0x1Dc89c28...40C2cC06d
0 ETH0.000937466.68622068
Set Base Token205349722024-08-15 15:37:47158 days ago1723736267IN
0x1Dc89c28...40C2cC06d
0 ETH0.000379686.6922029
Set Chainlink Or...205348662024-08-15 15:16:23158 days ago1723734983IN
0x1Dc89c28...40C2cC06d
0 ETH0.000484617.1220307
Set Base Token205348652024-08-15 15:16:11158 days ago1723734971IN
0x1Dc89c28...40C2cC06d
0 ETH0.000381596.72506215
Set Chainlink Or...205347292024-08-15 14:48:59158 days ago1723733339IN
0x1Dc89c28...40C2cC06d
0 ETH0.000380295.58891409
Set Base Token205347282024-08-15 14:48:47158 days ago1723733327IN
0x1Dc89c28...40C2cC06d
0 ETH0.000324555.71979281
Set Chainlink Or...205279502024-08-14 16:05:23159 days ago1723651523IN
0x1Dc89c28...40C2cC06d
0 ETH0.000510187.49723035
Set Base Token205279342024-08-14 16:02:11159 days ago1723651331IN
0x1Dc89c28...40C2cC06d
0 ETH0.000399757.04430958
Set Chainlink Or...201766942024-06-26 15:14:59208 days ago1719414899IN
0x1Dc89c28...40C2cC06d
0 ETH0.0015981411.39739897
Set Base Token201766922024-06-26 15:14:35208 days ago1719414875IN
0x1Dc89c28...40C2cC06d
0 ETH0.0007386613.01661467
Set Chainlink Or...201765692024-06-26 14:49:47208 days ago1719413387IN
0x1Dc89c28...40C2cC06d
0 ETH0.0021109215.05436552
Set Base Token201765682024-06-26 14:49:35208 days ago1719413375IN
0x1Dc89c28...40C2cC06d
0 ETH0.0008550315.06717099
Set Chainlink Or...201759122024-06-26 12:37:59208 days ago1719405479IN
0x1Dc89c28...40C2cC06d
0 ETH0.000604014.30759283
Set Base Token201759112024-06-26 12:37:47208 days ago1719405467IN
0x1Dc89c28...40C2cC06d
0 ETH0.000261784.61319112
Set Chainlink Or...201757702024-06-26 12:09:23208 days ago1719403763IN
0x1Dc89c28...40C2cC06d
0 ETH0.001009367.19841182
Set Base Token201757692024-06-26 12:09:11208 days ago1719403751IN
0x1Dc89c28...40C2cC06d
0 ETH0.000419867.39867593
Set Chainlink Or...201756532024-06-26 11:45:59208 days ago1719402359IN
0x1Dc89c28...40C2cC06d
0 ETH0.000350232.49772589
Set Base Token201756522024-06-26 11:45:47208 days ago1719402347IN
0x1Dc89c28...40C2cC06d
0 ETH0.000141282.48976074
Set Chainlink Or...201633232024-06-24 18:26:35210 days ago1719253595IN
0x1Dc89c28...40C2cC06d
0 ETH0.0008850113.00644835
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216707822025-01-21 5:29:5924 mins ago1737437399
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705862025-01-21 4:50:231 hr ago1737435023
0x1Dc89c28...40C2cC06d
0 ETH
216705572025-01-21 4:44:351 hr ago1737434675
0x1Dc89c28...40C2cC06d
0 ETH
216704212025-01-21 4:17:111 hr ago1737433031
0x1Dc89c28...40C2cC06d
0 ETH
216702342025-01-21 3:39:472 hrs ago1737430787
0x1Dc89c28...40C2cC06d
0 ETH
216702342025-01-21 3:39:472 hrs ago1737430787
0x1Dc89c28...40C2cC06d
0 ETH
View All Internal Transactions
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
File 1 of 8 : ChainlinkOracle.sol
// 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,
            Q96,
            baseTokenPrice * 10 ** decimals
        );
    }
}

File 2 of 8 : IChainlinkOracle.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.25;

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
    );
}

File 3 of 8 : FullMath.sol
// 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++;
            }
        }
    }
}

File 4 of 8 : IDefaultAccessControl.sol
// 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;
}

File 5 of 8 : IAggregatorV3.sol
// 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 6 of 8 : 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_);
}

File 7 of 8 : IAccessControlEnumerable.sol
// 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);
}

File 8 of 8 : IAccessControl.sol
// 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/",
    "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

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

6080604052348015600f57600080fd5b50610cb48061001f6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80634ef7f1f41161005b5780634ef7f1f4146101185780635ba208f71461012d578063ac41865a14610140578063e6f03d1d1461016a57600080fd5b806302eba0941461008257806323adf0ed146100c857806340792465146100ff575b600080fd5b6100ab61009036600461080d565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100db6100d636600461082a565b61017d565b6040805182516001600160a01b0316815260209283015192810192909252016100bf565b61010a600160601b81565b6040519081526020016100bf565b61012b61012636600461082a565b6101cf565b005b61012b61013b3660046108a8565b610290565b61015361014e36600461082a565b610476565b6040805192835260ff9091166020830152016100bf565b61010a61017836600461082a565b6104cc565b604080518082018252600080825260209182018190526001600160a01b038581168252600180845284832086831684528452918490208451808601909552805490911684520154908201525b92915050565b604051632abb908560e11b81523360048201526001600160a01b03831690635577210a9060240160006040518083038186803b15801561020e57600080fd5b505afa158015610222573d6000803e3d6000fd5b505050506001600160a01b038281166000818152602081815260409182902080546001600160a01b03191694861694851790558151938452429084015290917fb6506fd1712cc8abb65a6f88ec7441df50f4e7e4aea7e99230816c3567b5d8c1910160405180910390a25050565b604051632abb908560e11b81523360048201526001600160a01b03861690635577210a9060240160006040518083038186803b1580156102cf57600080fd5b505afa1580156102e3573d6000803e3d6000fd5b50505083821490506103085760405163251f56a160e21b815260040160405180910390fd5b60005b838110156103865760008383838181106103275761032761095c565b61033d926020604090920201908101915061080d565b6001600160a01b03161461037e5761037b8383838181106103605761036061095c565b9050604002018036038101906103769190610972565b6105e1565b50505b60010161030b565b5060005b83811015610425578282828181106103a4576103a461095c565b90506040020160016000886001600160a01b03166001600160a01b0316815260200190815260200160002060008787858181106103e3576103e361095c565b90506020020160208101906103f8919061080d565b6001600160a01b03168152602081019190915260400160002061041b82826109d8565b505060010161038a565b50846001600160a01b03167f6cde280d4e0537a3e3575c6e4c3f9f0eee9ddda245b128f36a5c8c2d7b9b24ff8585858542604051610467959493929190610a0e565b60405180910390a25050505050565b6001600160a01b038083166000908152600160208181526040808420868616855282528084208151808301909252805490951681529390910154908301529081906104c0906105e1565b915091505b9250929050565b60006001600160a01b0383166104f557604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b03821661051c57604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b03808416600090815260208190526040902054168061055557604051639fabe1c160e01b815260040160405180910390fd5b806001600160a01b0316836001600160a01b03160361057b57600160601b9150506101c9565b6000806105888686610476565b915091506000806105998886610476565b90925090506105d56105ac82600a610bb3565b6105b69086610bc2565b600160601b6105c686600a610bb3565b6105d09086610bc2565b610742565b98975050505050505050565b805160009081906001600160a01b031661060e57604051639fabe1c160e01b815260040160405180910390fd5b60008084600001516001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610653573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106779190610bf8565b5093505092505060008212156106a0576040516378de663960e11b815260040160405180910390fd5b819350808560200151426106b49190610c48565b11156106d3576040516388cce42960e01b815260040160405180910390fd5b84600001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610715573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107399190610c5b565b92505050915091565b600080806000198587098587029250828110838203039150508060000361077b576000841161077057600080fd5b5082900490506107ee565b80841161078757600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b6001600160a01b038116811461080a57600080fd5b50565b60006020828403121561081f57600080fd5b81356107ee816107f5565b6000806040838503121561083d57600080fd5b8235610848816107f5565b91506020830135610858816107f5565b809150509250929050565b60008083601f84011261087557600080fd5b50813567ffffffffffffffff81111561088d57600080fd5b6020830191508360208260061b85010111156104c557600080fd5b6000806000806000606086880312156108c057600080fd5b85356108cb816107f5565b9450602086013567ffffffffffffffff808211156108e857600080fd5b818801915088601f8301126108fc57600080fd5b81358181111561090b57600080fd5b8960208260051b850101111561092057600080fd5b60208301965080955050604088013591508082111561093e57600080fd5b5061094b88828901610863565b969995985093965092949392505050565b634e487b7160e01b600052603260045260246000fd5b60006040828403121561098457600080fd5b6040516040810181811067ffffffffffffffff821117156109b557634e487b7160e01b600052604160045260246000fd5b60405282356109c3816107f5565b81526020928301359281019290925250919050565b81356109e3816107f5565b81546001600160a01b0319166001600160a01b03919091161781556020919091013560019190910155565b6060808252810185905260008660808301825b88811015610a51578235610a34816107f5565b6001600160a01b0316825260209283019290910190600101610a21565b5083810360208581019190915286825291508690820160005b87811015610aa2578235610a7d816107f5565b6001600160a01b03168252828401358483015260409283019290910190600101610a6a565b508093505050508260408301529695505050505050565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115610b0a578160001904821115610af057610af0610ab9565b80851615610afd57918102915b93841c9390800290610ad4565b509250929050565b600082610b21575060016101c9565b81610b2e575060006101c9565b8160018114610b445760028114610b4e57610b6a565b60019150506101c9565b60ff841115610b5f57610b5f610ab9565b50506001821b6101c9565b5060208310610133831016604e8410600b8410161715610b8d575081810a6101c9565b610b978383610acf565b8060001904821115610bab57610bab610ab9565b029392505050565b60006107ee60ff841683610b12565b80820281158282048414176101c9576101c9610ab9565b805169ffffffffffffffffffff81168114610bf357600080fd5b919050565b600080600080600060a08688031215610c1057600080fd5b610c1986610bd9565b9450602086015193506040860151925060608601519150610c3c60808701610bd9565b90509295509295909350565b818103818111156101c9576101c9610ab9565b600060208284031215610c6d57600080fd5b815160ff811681146107ee57600080fdfea26469706673582212203510fe0ca3523441c206457750a2516cd264eec4c21592cb9728bf3d1396b21164736f6c63430008190033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80634ef7f1f41161005b5780634ef7f1f4146101185780635ba208f71461012d578063ac41865a14610140578063e6f03d1d1461016a57600080fd5b806302eba0941461008257806323adf0ed146100c857806340792465146100ff575b600080fd5b6100ab61009036600461080d565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100db6100d636600461082a565b61017d565b6040805182516001600160a01b0316815260209283015192810192909252016100bf565b61010a600160601b81565b6040519081526020016100bf565b61012b61012636600461082a565b6101cf565b005b61012b61013b3660046108a8565b610290565b61015361014e36600461082a565b610476565b6040805192835260ff9091166020830152016100bf565b61010a61017836600461082a565b6104cc565b604080518082018252600080825260209182018190526001600160a01b038581168252600180845284832086831684528452918490208451808601909552805490911684520154908201525b92915050565b604051632abb908560e11b81523360048201526001600160a01b03831690635577210a9060240160006040518083038186803b15801561020e57600080fd5b505afa158015610222573d6000803e3d6000fd5b505050506001600160a01b038281166000818152602081815260409182902080546001600160a01b03191694861694851790558151938452429084015290917fb6506fd1712cc8abb65a6f88ec7441df50f4e7e4aea7e99230816c3567b5d8c1910160405180910390a25050565b604051632abb908560e11b81523360048201526001600160a01b03861690635577210a9060240160006040518083038186803b1580156102cf57600080fd5b505afa1580156102e3573d6000803e3d6000fd5b50505083821490506103085760405163251f56a160e21b815260040160405180910390fd5b60005b838110156103865760008383838181106103275761032761095c565b61033d926020604090920201908101915061080d565b6001600160a01b03161461037e5761037b8383838181106103605761036061095c565b9050604002018036038101906103769190610972565b6105e1565b50505b60010161030b565b5060005b83811015610425578282828181106103a4576103a461095c565b90506040020160016000886001600160a01b03166001600160a01b0316815260200190815260200160002060008787858181106103e3576103e361095c565b90506020020160208101906103f8919061080d565b6001600160a01b03168152602081019190915260400160002061041b82826109d8565b505060010161038a565b50846001600160a01b03167f6cde280d4e0537a3e3575c6e4c3f9f0eee9ddda245b128f36a5c8c2d7b9b24ff8585858542604051610467959493929190610a0e565b60405180910390a25050505050565b6001600160a01b038083166000908152600160208181526040808420868616855282528084208151808301909252805490951681529390910154908301529081906104c0906105e1565b915091505b9250929050565b60006001600160a01b0383166104f557604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b03821661051c57604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b03808416600090815260208190526040902054168061055557604051639fabe1c160e01b815260040160405180910390fd5b806001600160a01b0316836001600160a01b03160361057b57600160601b9150506101c9565b6000806105888686610476565b915091506000806105998886610476565b90925090506105d56105ac82600a610bb3565b6105b69086610bc2565b600160601b6105c686600a610bb3565b6105d09086610bc2565b610742565b98975050505050505050565b805160009081906001600160a01b031661060e57604051639fabe1c160e01b815260040160405180910390fd5b60008084600001516001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610653573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106779190610bf8565b5093505092505060008212156106a0576040516378de663960e11b815260040160405180910390fd5b819350808560200151426106b49190610c48565b11156106d3576040516388cce42960e01b815260040160405180910390fd5b84600001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610715573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107399190610c5b565b92505050915091565b600080806000198587098587029250828110838203039150508060000361077b576000841161077057600080fd5b5082900490506107ee565b80841161078757600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b6001600160a01b038116811461080a57600080fd5b50565b60006020828403121561081f57600080fd5b81356107ee816107f5565b6000806040838503121561083d57600080fd5b8235610848816107f5565b91506020830135610858816107f5565b809150509250929050565b60008083601f84011261087557600080fd5b50813567ffffffffffffffff81111561088d57600080fd5b6020830191508360208260061b85010111156104c557600080fd5b6000806000806000606086880312156108c057600080fd5b85356108cb816107f5565b9450602086013567ffffffffffffffff808211156108e857600080fd5b818801915088601f8301126108fc57600080fd5b81358181111561090b57600080fd5b8960208260051b850101111561092057600080fd5b60208301965080955050604088013591508082111561093e57600080fd5b5061094b88828901610863565b969995985093965092949392505050565b634e487b7160e01b600052603260045260246000fd5b60006040828403121561098457600080fd5b6040516040810181811067ffffffffffffffff821117156109b557634e487b7160e01b600052604160045260246000fd5b60405282356109c3816107f5565b81526020928301359281019290925250919050565b81356109e3816107f5565b81546001600160a01b0319166001600160a01b03919091161781556020919091013560019190910155565b6060808252810185905260008660808301825b88811015610a51578235610a34816107f5565b6001600160a01b0316825260209283019290910190600101610a21565b5083810360208581019190915286825291508690820160005b87811015610aa2578235610a7d816107f5565b6001600160a01b03168252828401358483015260409283019290910190600101610a6a565b508093505050508260408301529695505050505050565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115610b0a578160001904821115610af057610af0610ab9565b80851615610afd57918102915b93841c9390800290610ad4565b509250929050565b600082610b21575060016101c9565b81610b2e575060006101c9565b8160018114610b445760028114610b4e57610b6a565b60019150506101c9565b60ff841115610b5f57610b5f610ab9565b50506001821b6101c9565b5060208310610133831016604e8410600b8410161715610b8d575081810a6101c9565b610b978383610acf565b8060001904821115610bab57610bab610ab9565b029392505050565b60006107ee60ff841683610b12565b80820281158282048414176101c9576101c9610ab9565b805169ffffffffffffffffffff81168114610bf357600080fd5b919050565b600080600080600060a08688031215610c1057600080fd5b610c1986610bd9565b9450602086015193506040860151925060608601519150610c3c60808701610bd9565b90509295509295909350565b818103818111156101c9576101c9610ab9565b600060208284031215610c6d57600080fd5b815160ff811681146107ee57600080fdfea26469706673582212203510fe0ca3523441c206457750a2516cd264eec4c21592cb9728bf3d1396b21164736f6c63430008190033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.