Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PriceRegistry
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 26000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol";
import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol";
import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol";
import {Internal} from "./libraries/Internal.sol";
import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol";
import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableSet.sol";
/// @notice The PriceRegistry contract responsibility is to store the current gas price in USD for a given destination chain,
/// and the price of a token in USD allowing the owner or priceUpdater to update this value.
contract PriceRegistry is IPriceRegistry, OwnerIsCreator, ITypeAndVersion {
using EnumerableSet for EnumerableSet.AddressSet;
using USDPriceWith18Decimals for uint224;
error TokenNotSupported(address token);
error ChainNotSupported(uint64 chain);
error OnlyCallableByUpdaterOrOwner();
error StaleGasPrice(uint64 destChainSelector, uint256 threshold, uint256 timePassed);
error StaleTokenPrice(address token, uint256 threshold, uint256 timePassed);
error InvalidStalenessThreshold();
event PriceUpdaterSet(address indexed priceUpdater);
event PriceUpdaterRemoved(address indexed priceUpdater);
event FeeTokenAdded(address indexed feeToken);
event FeeTokenRemoved(address indexed feeToken);
event UsdPerUnitGasUpdated(uint64 indexed destChain, uint256 value, uint256 timestamp);
event UsdPerTokenUpdated(address indexed token, uint256 value, uint256 timestamp);
// solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
string public constant override typeAndVersion = "PriceRegistry 1.2.0";
/// @dev The gas price per unit of gas for a given destination chain, in USD with 18 decimals.
/// Multiple gas prices can be encoded into the same value. Each price takes {Internal.GAS_PRICE_BITS} bits.
/// For example, if Optimism is the destination chain, gas price can include L1 base fee and L2 gas price.
/// Logic to parse the price components is chain-specific, and should live in OnRamp.
/// @dev Price of 1e18 is 1 USD. Examples:
/// Very Expensive: 1 unit of gas costs 1 USD -> 1e18
/// Expensive: 1 unit of gas costs 0.1 USD -> 1e17
/// Cheap: 1 unit of gas costs 0.000001 USD -> 1e12
mapping(uint64 destChainSelector => Internal.TimestampedPackedUint224 price)
private s_usdPerUnitGasByDestChainSelector;
/// @dev The price, in USD with 18 decimals, per 1e18 of the smallest token denomination.
/// @dev Price of 1e18 represents 1 USD per 1e18 token amount.
/// 1 USDC = 1.00 USD per full token, each full token is 1e6 units -> 1 * 1e18 * 1e18 / 1e6 = 1e30
/// 1 ETH = 2,000 USD per full token, each full token is 1e18 units -> 2000 * 1e18 * 1e18 / 1e18 = 2_000e18
/// 1 LINK = 5.00 USD per full token, each full token is 1e18 units -> 5 * 1e18 * 1e18 / 1e18 = 5e18
mapping(address token => Internal.TimestampedPackedUint224 price) private s_usdPerToken;
// Price updaters are allowed to update the prices.
EnumerableSet.AddressSet private s_priceUpdaters;
// Subset of tokens which prices tracked by this registry which are fee tokens.
EnumerableSet.AddressSet private s_feeTokens;
// The amount of time a price can be stale before it is considered invalid.
uint32 private immutable i_stalenessThreshold;
constructor(address[] memory priceUpdaters, address[] memory feeTokens, uint32 stalenessThreshold) {
_applyPriceUpdatersUpdates(priceUpdaters, new address[](0));
_applyFeeTokensUpdates(feeTokens, new address[](0));
if (stalenessThreshold == 0) revert InvalidStalenessThreshold();
i_stalenessThreshold = stalenessThreshold;
}
// ================================================================
// │ Price calculations │
// ================================================================
// @inheritdoc IPriceRegistry
function getTokenPrice(address token) public view override returns (Internal.TimestampedPackedUint224 memory) {
return s_usdPerToken[token];
}
// @inheritdoc IPriceRegistry
function getValidatedTokenPrice(address token) external view override returns (uint224) {
return _getValidatedTokenPrice(token);
}
// @inheritdoc IPriceRegistry
function getTokenPrices(
address[] calldata tokens
) external view override returns (Internal.TimestampedPackedUint224[] memory) {
uint256 length = tokens.length;
Internal.TimestampedPackedUint224[] memory tokenPrices = new Internal.TimestampedPackedUint224[](length);
for (uint256 i = 0; i < length; ++i) {
tokenPrices[i] = getTokenPrice(tokens[i]);
}
return tokenPrices;
}
/// @notice Get the staleness threshold.
/// @return stalenessThreshold The staleness threshold.
function getStalenessThreshold() external view returns (uint128) {
return i_stalenessThreshold;
}
// @inheritdoc IPriceRegistry
function getDestinationChainGasPrice(
uint64 destChainSelector
) external view override returns (Internal.TimestampedPackedUint224 memory) {
return s_usdPerUnitGasByDestChainSelector[destChainSelector];
}
function getTokenAndGasPrices(
address token,
uint64 destChainSelector
) external view override returns (uint224 tokenPrice, uint224 gasPriceValue) {
Internal.TimestampedPackedUint224 memory gasPrice = s_usdPerUnitGasByDestChainSelector[destChainSelector];
// We do allow a gas price of 0, but no stale or unset gas prices
if (gasPrice.timestamp == 0) revert ChainNotSupported(destChainSelector);
uint256 timePassed = block.timestamp - gasPrice.timestamp;
if (timePassed > i_stalenessThreshold) revert StaleGasPrice(destChainSelector, i_stalenessThreshold, timePassed);
return (_getValidatedTokenPrice(token), gasPrice.value);
}
/// @inheritdoc IPriceRegistry
/// @dev this function assumes that no more than 1e59 dollars are sent as payment.
/// If more is sent, the multiplication of feeTokenAmount and feeTokenValue will overflow.
/// Since there isn't even close to 1e59 dollars in the world economy this is safe.
function convertTokenAmount(
address fromToken,
uint256 fromTokenAmount,
address toToken
) external view override returns (uint256) {
/// Example:
/// fromTokenAmount: 1e18 // 1 ETH
/// ETH: 2_000e18
/// LINK: 5e18
/// return: 1e18 * 2_000e18 / 5e18 = 400e18 (400 LINK)
return (fromTokenAmount * _getValidatedTokenPrice(fromToken)) / _getValidatedTokenPrice(toToken);
}
/// @notice Gets the token price for a given token and revert if the token is either
/// not supported or the price is stale.
/// @param token The address of the token to get the price for
/// @return the token price
function _getValidatedTokenPrice(address token) internal view returns (uint224) {
Internal.TimestampedPackedUint224 memory tokenPrice = s_usdPerToken[token];
if (tokenPrice.timestamp == 0 || tokenPrice.value == 0) revert TokenNotSupported(token);
uint256 timePassed = block.timestamp - tokenPrice.timestamp;
if (timePassed > i_stalenessThreshold) revert StaleTokenPrice(token, i_stalenessThreshold, timePassed);
return tokenPrice.value;
}
// ================================================================
// │ Fee tokens │
// ================================================================
/// @notice Get the list of fee tokens.
/// @return The tokens set as fee tokens.
function getFeeTokens() external view returns (address[] memory) {
return s_feeTokens.values();
}
/// @notice Add and remove tokens from feeTokens set.
/// @param feeTokensToAdd The addresses of the tokens which are now considered fee tokens
/// and can be used to calculate fees.
/// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens.
function applyFeeTokensUpdates(
address[] memory feeTokensToAdd,
address[] memory feeTokensToRemove
) external onlyOwner {
_applyFeeTokensUpdates(feeTokensToAdd, feeTokensToRemove);
}
/// @notice Add and remove tokens from feeTokens set.
/// @param feeTokensToAdd The addresses of the tokens which are now considered fee tokens
/// and can be used to calculate fees.
/// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens.
function _applyFeeTokensUpdates(address[] memory feeTokensToAdd, address[] memory feeTokensToRemove) private {
for (uint256 i = 0; i < feeTokensToAdd.length; ++i) {
if (s_feeTokens.add(feeTokensToAdd[i])) {
emit FeeTokenAdded(feeTokensToAdd[i]);
}
}
for (uint256 i = 0; i < feeTokensToRemove.length; ++i) {
if (s_feeTokens.remove(feeTokensToRemove[i])) {
emit FeeTokenRemoved(feeTokensToRemove[i]);
}
}
}
// ================================================================
// │ Price updates │
// ================================================================
// @inheritdoc IPriceRegistry
function updatePrices(Internal.PriceUpdates calldata priceUpdates) external override requireUpdaterOrOwner {
uint256 tokenUpdatesLength = priceUpdates.tokenPriceUpdates.length;
for (uint256 i = 0; i < tokenUpdatesLength; ++i) {
Internal.TokenPriceUpdate memory update = priceUpdates.tokenPriceUpdates[i];
s_usdPerToken[update.sourceToken] = Internal.TimestampedPackedUint224({
value: update.usdPerToken,
timestamp: uint32(block.timestamp)
});
emit UsdPerTokenUpdated(update.sourceToken, update.usdPerToken, block.timestamp);
}
uint256 gasUpdatesLength = priceUpdates.gasPriceUpdates.length;
for (uint256 i = 0; i < gasUpdatesLength; ++i) {
Internal.GasPriceUpdate memory update = priceUpdates.gasPriceUpdates[i];
s_usdPerUnitGasByDestChainSelector[update.destChainSelector] = Internal.TimestampedPackedUint224({
value: update.usdPerUnitGas,
timestamp: uint32(block.timestamp)
});
emit UsdPerUnitGasUpdated(update.destChainSelector, update.usdPerUnitGas, block.timestamp);
}
}
// ================================================================
// │ Access │
// ================================================================
/// @notice Get the list of price updaters.
/// @return The price updaters.
function getPriceUpdaters() external view returns (address[] memory) {
return s_priceUpdaters.values();
}
/// @notice Adds new priceUpdaters and remove existing ones.
/// @param priceUpdatersToAdd The addresses of the priceUpdaters that are now allowed
/// to send fee updates.
/// @param priceUpdatersToRemove The addresses of the priceUpdaters that are no longer allowed
/// to send fee updates.
function applyPriceUpdatersUpdates(
address[] memory priceUpdatersToAdd,
address[] memory priceUpdatersToRemove
) external onlyOwner {
_applyPriceUpdatersUpdates(priceUpdatersToAdd, priceUpdatersToRemove);
}
/// @notice Adds new priceUpdaters and remove existing ones.
/// @param priceUpdatersToAdd The addresses of the priceUpdaters that are now allowed
/// to send fee updates.
/// @param priceUpdatersToRemove The addresses of the priceUpdaters that are no longer allowed
/// to send fee updates.
function _applyPriceUpdatersUpdates(
address[] memory priceUpdatersToAdd,
address[] memory priceUpdatersToRemove
) private {
for (uint256 i = 0; i < priceUpdatersToAdd.length; ++i) {
if (s_priceUpdaters.add(priceUpdatersToAdd[i])) {
emit PriceUpdaterSet(priceUpdatersToAdd[i]);
}
}
for (uint256 i = 0; i < priceUpdatersToRemove.length; ++i) {
if (s_priceUpdaters.remove(priceUpdatersToRemove[i])) {
emit PriceUpdaterRemoved(priceUpdatersToRemove[i]);
}
}
}
/// @notice Require that the caller is the owner or a fee updater.
modifier requireUpdaterOrOwner() {
if (msg.sender != owner() && !s_priceUpdaters.contains(msg.sender)) revert OnlyCallableByUpdaterOrOwner();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ITypeAndVersion {
function typeAndVersion() external pure returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Internal} from "../libraries/Internal.sol";
interface IPriceRegistry {
/// @notice Update the price for given tokens and gas prices for given chains.
/// @param priceUpdates The price updates to apply.
function updatePrices(Internal.PriceUpdates memory priceUpdates) external;
/// @notice Get the `tokenPrice` for a given token.
/// @param token The token to get the price for.
/// @return tokenPrice The tokenPrice for the given token.
function getTokenPrice(address token) external view returns (Internal.TimestampedPackedUint224 memory);
/// @notice Get the `tokenPrice` for a given token, checks if the price is valid.
/// @param token The token to get the price for.
/// @return tokenPrice The tokenPrice for the given token if it exists and is valid.
function getValidatedTokenPrice(address token) external view returns (uint224);
/// @notice Get the `tokenPrice` for an array of tokens.
/// @param tokens The tokens to get prices for.
/// @return tokenPrices The tokenPrices for the given tokens.
function getTokenPrices(address[] calldata tokens) external view returns (Internal.TimestampedPackedUint224[] memory);
/// @notice Get an encoded `gasPrice` for a given destination chain ID.
/// The 224-bit result encodes necessary gas price components.
/// On L1 chains like Ethereum or Avax, the only component is the gas price.
/// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability.
/// On future chains, there could be more or differing price components.
/// PriceRegistry does not contain chain-specific logic to parse destination chain price components.
/// @param destChainSelector The destination chain to get the price for.
/// @return gasPrice The encoded gasPrice for the given destination chain ID.
function getDestinationChainGasPrice(
uint64 destChainSelector
) external view returns (Internal.TimestampedPackedUint224 memory);
/// @notice Gets the fee token price and the gas price, both denominated in dollars.
/// @param token The source token to get the price for.
/// @param destChainSelector The destination chain to get the gas price for.
/// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit.
/// @return gasPrice The price of gas in 1e18 dollars per base unit.
function getTokenAndGasPrices(
address token,
uint64 destChainSelector
) external view returns (uint224 tokenPrice, uint224 gasPrice);
/// @notice Convert a given token amount to target token amount.
/// @param fromToken The given token address.
/// @param fromTokenAmount The given token amount.
/// @param toToken The target token address.
/// @return toTokenAmount The target token amount.
function convertTokenAmount(
address fromToken,
uint256 fromTokenAmount,
address toToken
) external view returns (uint256 toTokenAmount);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {ConfirmedOwner} from "./ConfirmedOwner.sol";
/// @title The OwnerIsCreator contract
/// @notice A contract with helpers for basic contract ownership.
contract OwnerIsCreator is ConfirmedOwner {
constructor() ConfirmedOwner(msg.sender) {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Client} from "./Client.sol";
import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol";
// Library for CCIP internal definitions common to multiple contracts.
library Internal {
/// @dev The minimum amount of gas to perform the call with exact gas.
/// We include this in the offramp so that we can redeploy to adjust it
/// should a hardfork change the gas costs of relevant opcodes in callWithExactGas.
uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5_000;
// @dev We limit return data to a selector plus 4 words. This is to avoid
// malicious contracts from returning large amounts of data and causing
// repeated out-of-gas scenarios.
uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32;
/// @notice A collection of token price and gas price updates.
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct PriceUpdates {
TokenPriceUpdate[] tokenPriceUpdates;
GasPriceUpdate[] gasPriceUpdates;
}
/// @notice Token price in USD.
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct TokenPriceUpdate {
address sourceToken; // Source token
uint224 usdPerToken; // 1e18 USD per smallest unit of token
}
/// @notice Gas price for a given chain in USD, its value may contain tightly packed fields.
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct GasPriceUpdate {
uint64 destChainSelector; // Destination chain selector
uint224 usdPerUnitGas; // 1e18 USD per smallest unit (e.g. wei) of destination chain gas
}
/// @notice A timestamped uint224 value that can contain several tightly packed fields.
struct TimestampedPackedUint224 {
uint224 value; // ───────╮ Value in uint224, packed.
uint32 timestamp; // ────╯ Timestamp of the most recent price update.
}
/// @dev Gas price is stored in 112-bit unsigned int. uint224 can pack 2 prices.
/// When packing L1 and L2 gas prices, L1 gas price is left-shifted to the higher-order bits.
/// Using uint8 type, which cannot be higher than other bit shift operands, to avoid shift operand type warning.
uint8 public constant GAS_PRICE_BITS = 112;
struct PoolUpdate {
address token; // The IERC20 token address
address pool; // The token pool address
}
/// @notice Report that is submitted by the execution DON at the execution phase.
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct ExecutionReport {
EVM2EVMMessage[] messages;
// Contains a bytes array for each message, each inner bytes array contains bytes per transferred token
bytes[][] offchainTokenData;
bytes32[] proofs;
uint256 proofFlagBits;
}
/// @notice The cross chain message that gets committed to EVM chains.
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct EVM2EVMMessage {
uint64 sourceChainSelector; // ─────────╮ the chain selector of the source chain, note: not chainId
address sender; // ─────────────────────╯ sender address on the source chain
address receiver; // ───────────────────╮ receiver address on the destination chain
uint64 sequenceNumber; // ──────────────╯ sequence number, not unique across lanes
uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution
bool strict; // ────────────────────────╮ DEPRECATED
uint64 nonce; // │ nonce for this lane for this sender, not unique across senders/lanes
address feeToken; // ───────────────────╯ fee token
uint256 feeTokenAmount; // fee token amount
bytes data; // arbitrary data payload supplied by the message sender
Client.EVMTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer
bytes[] sourceTokenData; // array of token pool return values, one per token
bytes32 messageId; // a hash of the message data
}
/// @dev EVM2EVMMessage struct has 13 fields, including 3 variable arrays.
/// Each variable array takes 1 more slot to store its length.
/// When abi encoded, excluding array contents,
/// EVM2EVMMessage takes up a fixed number of 16 lots, 32 bytes each.
/// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 17.
uint256 public constant MESSAGE_FIXED_BYTES = 32 * 17;
/// @dev Each token transfer adds 1 EVMTokenAmount and 1 bytes.
/// When abiEncoded, each EVMTokenAmount takes 2 slots, each bytes takes 2 slots, excl bytes contents
uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 4;
function _toAny2EVMMessage(
EVM2EVMMessage memory original,
Client.EVMTokenAmount[] memory destTokenAmounts
) internal pure returns (Client.Any2EVMMessage memory message) {
message = Client.Any2EVMMessage({
messageId: original.messageId,
sourceChainSelector: original.sourceChainSelector,
sender: abi.encode(original.sender),
data: original.data,
destTokenAmounts: destTokenAmounts
});
}
bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256("EVM2EVMMessageHashV2");
function _hash(EVM2EVMMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) {
// Fixed-size message fields are included in nested hash to reduce stack pressure.
// This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers.
return
keccak256(
abi.encode(
MerkleMultiProof.LEAF_DOMAIN_SEPARATOR,
metadataHash,
keccak256(
abi.encode(
original.sender,
original.receiver,
original.sequenceNumber,
original.gasLimit,
original.strict,
original.nonce,
original.feeToken,
original.feeTokenAmount
)
),
keccak256(original.data),
keccak256(abi.encode(original.tokenAmounts)),
keccak256(abi.encode(original.sourceTokenData))
)
);
}
/// @notice Enum listing the possible message execution states within
/// the offRamp contract.
/// UNTOUCHED never executed
/// IN_PROGRESS currently being executed, used a replay protection
/// SUCCESS successfully executed. End state
/// FAILURE unsuccessfully executed, manual execution is now enabled.
/// @dev RMN depends on this enum, if changing, please notify the RMN maintainers.
enum MessageExecutionState {
UNTOUCHED,
IN_PROGRESS,
SUCCESS,
FAILURE
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
library USDPriceWith18Decimals {
/// @notice Takes a price in USD, with 18 decimals per 1e18 token amount,
/// and amount of the smallest token denomination,
/// calculates the value in USD with 18 decimals.
/// @param tokenPrice The USD price of the token.
/// @param tokenAmount Amount of the smallest token denomination.
/// @return USD value with 18 decimals.
/// @dev this function assumes that no more than 1e59 US dollar worth of token is passed in.
/// If more is sent, this function will overflow and revert.
/// Since there isn't even close to 1e59 dollars, this is ok for all legit tokens.
function _calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) {
/// LINK Example:
/// tokenPrice: 8e18 -> $8/LINK, as 1e18 token amount is 1 LINK, worth 8 USD, or 8e18 with 18 decimals
/// tokenAmount: 2e18 -> 2 LINK
/// result: 8e18 * 2e18 / 1e18 -> 16e18 with 18 decimals = $16
/// USDC Example:
/// tokenPrice: 1e30 -> $1/USDC, as 1e18 token amount is 1e12 USDC, worth 1e12 USD, or 1e30 with 18 decimals
/// tokenAmount: 5e6 -> 5 USDC
/// result: 1e30 * 5e6 / 1e18 -> 5e18 with 18 decimals = $5
return (tokenPrice * tokenAmount) / 1e18;
}
/// @notice Takes a price in USD, with 18 decimals per 1e18 token amount,
/// and USD value with 18 decimals,
/// calculates amount of the smallest token denomination.
/// @param tokenPrice The USD price of the token.
/// @param usdValue USD value with 18 decimals.
/// @return Amount of the smallest token denomination.
function _calcTokenAmountFromUSDValue(uint224 tokenPrice, uint256 usdValue) internal pure returns (uint256) {
/// LINK Example:
/// tokenPrice: 8e18 -> $8/LINK, as 1e18 token amount is 1 LINK, worth 8 USD, or 8e18 with 18 decimals
/// usdValue: 16e18 -> $16
/// result: 16e18 * 1e18 / 8e18 -> 2e18 = 2 LINK
/// USDC Example:
/// tokenPrice: 1e30 -> $1/USDC, as 1e18 token amount is 1e12 USDC, worth 1e12 USD, or 1e30 with 18 decimals
/// usdValue: 5e18 -> $5
/// result: 5e18 * 1e18 / 1e30 -> 5e6 = 5 USDC
return (usdValue * 1e18) / tokenPrice;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol";
/**
* @title The ConfirmedOwner contract
* @notice A contract with helpers for basic contract ownership.
*/
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// End consumer library.
library Client {
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct EVMTokenAmount {
address token; // token address on the local chain.
uint256 amount; // Amount of tokens.
}
struct Any2EVMMessage {
bytes32 messageId; // MessageId corresponding to ccipSend on source.
uint64 sourceChainSelector; // Source chain selector.
bytes sender; // abi.decode(sender) if coming from an EVM chain.
bytes data; // payload sent in original message.
EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation.
}
// If extraArgs is empty bytes, the default is 200k gas limit.
struct EVM2AnyMessage {
bytes receiver; // abi.encode(receiver address) for dest EVM chains
bytes data; // Data payload
EVMTokenAmount[] tokenAmounts; // Token transfers
address feeToken; // Address of feeToken. address(0) means you will send msg.value.
bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1)
}
// bytes4(keccak256("CCIP EVMExtraArgsV1"));
bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9;
struct EVMExtraArgsV1 {
uint256 gasLimit;
}
function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
library MerkleMultiProof {
/// @notice Leaf domain separator, should be used as the first 32 bytes of a leaf's preimage.
bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000;
/// @notice Internal domain separator, should be used as the first 32 bytes of an internal node's preiimage.
bytes32 internal constant INTERNAL_DOMAIN_SEPARATOR =
0x0000000000000000000000000000000000000000000000000000000000000001;
uint256 internal constant MAX_NUM_HASHES = 256;
error InvalidProof();
error LeavesCannotBeEmpty();
/// @notice Computes the root based on provided pre-hashed leaf nodes in
/// leaves, internal nodes in proofs, and using proofFlagBits' i-th bit to
/// determine if an element of proofs or one of the previously computed leafs
/// or internal nodes will be used for the i-th hash.
/// @param leaves Should be pre-hashed and the first 32 bytes of a leaf's
/// preimage should match LEAF_DOMAIN_SEPARATOR.
/// @param proofs The hashes to be used instead of a leaf hash when the proofFlagBits
/// indicates a proof should be used.
/// @param proofFlagBits A single uint256 of which each bit indicates whether a leaf or
/// a proof needs to be used in a hash operation.
/// @dev the maximum number of hash operations it set to 256. Any input that would require
/// more than 256 hashes to get to a root will revert.
/// @dev For given input `leaves` = [a,b,c] `proofs` = [D] and `proofFlagBits` = 5
/// totalHashes = 3 + 1 - 1 = 3
/// ** round 1 **
/// proofFlagBits = (5 >> 0) & 1 = true
/// hashes[0] = hashPair(a, b)
/// (leafPos, hashPos, proofPos) = (2, 0, 0);
///
/// ** round 2 **
/// proofFlagBits = (5 >> 1) & 1 = false
/// hashes[1] = hashPair(D, c)
/// (leafPos, hashPos, proofPos) = (3, 0, 1);
///
/// ** round 3 **
/// proofFlagBits = (5 >> 2) & 1 = true
/// hashes[2] = hashPair(hashes[0], hashes[1])
/// (leafPos, hashPos, proofPos) = (3, 2, 1);
///
/// i = 3 and no longer < totalHashes. The algorithm is done
/// return hashes[totalHashes - 1] = hashes[2]; the last hash we computed.
// We mark this function as internal to force it to be inlined in contracts
// that use it, but semantically it is public.
// solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
function merkleRoot(
bytes32[] memory leaves,
bytes32[] memory proofs,
uint256 proofFlagBits
) internal pure returns (bytes32) {
unchecked {
uint256 leavesLen = leaves.length;
uint256 proofsLen = proofs.length;
if (leavesLen == 0) revert LeavesCannotBeEmpty();
if (!(leavesLen <= MAX_NUM_HASHES + 1 && proofsLen <= MAX_NUM_HASHES + 1)) revert InvalidProof();
uint256 totalHashes = leavesLen + proofsLen - 1;
if (!(totalHashes <= MAX_NUM_HASHES)) revert InvalidProof();
if (totalHashes == 0) {
return leaves[0];
}
bytes32[] memory hashes = new bytes32[](totalHashes);
(uint256 leafPos, uint256 hashPos, uint256 proofPos) = (0, 0, 0);
for (uint256 i = 0; i < totalHashes; ++i) {
// Checks if the bit flag signals the use of a supplied proof or a leaf/previous hash.
bytes32 a;
if (proofFlagBits & (1 << i) == (1 << i)) {
// Use a leaf or a previously computed hash.
if (leafPos < leavesLen) {
a = leaves[leafPos++];
} else {
a = hashes[hashPos++];
}
} else {
// Use a supplied proof.
a = proofs[proofPos++];
}
// The second part of the hashed pair is never a proof as hashing two proofs would result in a
// hash that can already be computed offchain.
bytes32 b;
if (leafPos < leavesLen) {
b = leaves[leafPos++];
} else {
b = hashes[hashPos++];
}
if (!(hashPos <= i)) revert InvalidProof();
hashes[i] = _hashPair(a, b);
}
if (!(hashPos == totalHashes - 1 && leafPos == leavesLen && proofPos == proofsLen)) revert InvalidProof();
// Return the last hash.
return hashes[totalHashes - 1];
}
}
/// @notice Hashes two bytes32 objects in their given order, prepended by the
/// INTERNAL_DOMAIN_SEPARATOR.
function _hashInternalNode(bytes32 left, bytes32 right) private pure returns (bytes32 hash) {
return keccak256(abi.encode(INTERNAL_DOMAIN_SEPARATOR, left, right));
}
/// @notice Hashes two bytes32 objects. The order is taken into account,
/// using the lower value first.
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _hashInternalNode(a, b) : _hashInternalNode(b, a);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IOwnable} from "../interfaces/IOwnable.sol";
/**
* @title The ConfirmedOwner contract
* @notice A contract with helpers for basic contract ownership.
*/
contract ConfirmedOwnerWithProposal is IOwnable {
address private s_owner;
address private s_pendingOwner;
event OwnershipTransferRequested(address indexed from, address indexed to);
event OwnershipTransferred(address indexed from, address indexed to);
constructor(address newOwner, address pendingOwner) {
// solhint-disable-next-line custom-errors
require(newOwner != address(0), "Cannot set owner to zero");
s_owner = newOwner;
if (pendingOwner != address(0)) {
_transferOwnership(pendingOwner);
}
}
/**
* @notice Allows an owner to begin transferring ownership to a new address,
* pending.
*/
function transferOwnership(address to) public override onlyOwner {
_transferOwnership(to);
}
/**
* @notice Allows an ownership transfer to be completed by the recipient.
*/
function acceptOwnership() external override {
// solhint-disable-next-line custom-errors
require(msg.sender == s_pendingOwner, "Must be proposed owner");
address oldOwner = s_owner;
s_owner = msg.sender;
s_pendingOwner = address(0);
emit OwnershipTransferred(oldOwner, msg.sender);
}
/**
* @notice Get the current owner
*/
function owner() public view override returns (address) {
return s_owner;
}
/**
* @notice validate, transfer ownership, and emit relevant events
*/
function _transferOwnership(address to) private {
// solhint-disable-next-line custom-errors
require(to != msg.sender, "Cannot transfer to self");
s_pendingOwner = to;
emit OwnershipTransferRequested(s_owner, to);
}
/**
* @notice validate access
*/
function _validateOwnership() internal view {
// solhint-disable-next-line custom-errors
require(msg.sender == s_owner, "Only callable by owner");
}
/**
* @notice Reverts if called by anyone other than the contract owner.
*/
modifier onlyOwner() {
_validateOwnership();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOwnable {
function owner() external returns (address);
function transferOwnership(address recipient) external;
function acceptOwnership() external;
}{
"remappings": [
"ds-test/=foundry-lib/forge-std/lib/ds-test/src/",
"forge-std/=foundry-lib/forge-std/src/",
"@openzeppelin/=node_modules/@openzeppelin/",
"hardhat/=node_modules/hardhat/",
"@eth-optimism/=node_modules/@eth-optimism/",
"@arbitrum/=node_modules/@arbitrum/",
"@offchainlabs/=node_modules/@offchainlabs/",
"@scroll-tech/=node_modules/@scroll-tech/",
"@zksync/=node_modules/@zksync/"
],
"optimizer": {
"enabled": true,
"runs": 26000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address[]","name":"priceUpdaters","type":"address[]"},{"internalType":"address[]","name":"feeTokens","type":"address[]"},{"internalType":"uint32","name":"stalenessThreshold","type":"uint32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint64","name":"chain","type":"uint64"}],"name":"ChainNotSupported","type":"error"},{"inputs":[],"name":"InvalidStalenessThreshold","type":"error"},{"inputs":[],"name":"OnlyCallableByUpdaterOrOwner","type":"error"},{"inputs":[{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"uint256","name":"timePassed","type":"uint256"}],"name":"StaleGasPrice","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"uint256","name":"timePassed","type":"uint256"}],"name":"StaleTokenPrice","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"TokenNotSupported","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feeToken","type":"address"}],"name":"FeeTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feeToken","type":"address"}],"name":"FeeTokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"priceUpdater","type":"address"}],"name":"PriceUpdaterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"priceUpdater","type":"address"}],"name":"PriceUpdaterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UsdPerTokenUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"destChain","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UsdPerUnitGasUpdated","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"feeTokensToAdd","type":"address[]"},{"internalType":"address[]","name":"feeTokensToRemove","type":"address[]"}],"name":"applyFeeTokensUpdates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"priceUpdatersToAdd","type":"address[]"},{"internalType":"address[]","name":"priceUpdatersToRemove","type":"address[]"}],"name":"applyPriceUpdatersUpdates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"address","name":"toToken","type":"address"}],"name":"convertTokenAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"destChainSelector","type":"uint64"}],"name":"getDestinationChainGasPrice","outputs":[{"components":[{"internalType":"uint224","name":"value","type":"uint224"},{"internalType":"uint32","name":"timestamp","type":"uint32"}],"internalType":"struct Internal.TimestampedPackedUint224","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPriceUpdaters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStalenessThreshold","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint64","name":"destChainSelector","type":"uint64"}],"name":"getTokenAndGasPrices","outputs":[{"internalType":"uint224","name":"tokenPrice","type":"uint224"},{"internalType":"uint224","name":"gasPriceValue","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getTokenPrice","outputs":[{"components":[{"internalType":"uint224","name":"value","type":"uint224"},{"internalType":"uint32","name":"timestamp","type":"uint32"}],"internalType":"struct Internal.TimestampedPackedUint224","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getTokenPrices","outputs":[{"components":[{"internalType":"uint224","name":"value","type":"uint224"},{"internalType":"uint32","name":"timestamp","type":"uint32"}],"internalType":"struct Internal.TimestampedPackedUint224[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getValidatedTokenPrice","outputs":[{"internalType":"uint224","name":"","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"sourceToken","type":"address"},{"internalType":"uint224","name":"usdPerToken","type":"uint224"}],"internalType":"struct Internal.TokenPriceUpdate[]","name":"tokenPriceUpdates","type":"tuple[]"},{"components":[{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"uint224","name":"usdPerUnitGas","type":"uint224"}],"internalType":"struct Internal.GasPriceUpdate[]","name":"gasPriceUpdates","type":"tuple[]"}],"internalType":"struct Internal.PriceUpdates","name":"priceUpdates","type":"tuple"}],"name":"updatePrices","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a06040523480156200001157600080fd5b506040516200227f3803806200227f8339810160408190526200003491620006fe565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000133565b5050604080516000815260208101909152620000dd91508490620001de565b604080516000815260208101909152620000f99083906200033a565b8063ffffffff166000036200012157604051631151410960e11b815260040160405180910390fd5b63ffffffff1660805250620007fa9050565b336001600160a01b038216036200018d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b825181101562000289576200021d83828151811062000204576200020462000786565b602002602001015160046200049160201b90919060201c565b15620002765782818151811062000238576200023862000786565b60200260200101516001600160a01b03167f34a02290b7920078c19f58e94b78c77eb9cc10195b20676e19bd3b82085893b860405160405180910390a25b6200028181620007b2565b9050620001e1565b5060005b81518110156200033557620002c9828281518110620002b057620002b062000786565b60200260200101516004620004b160201b90919060201c565b156200032257818181518110620002e457620002e462000786565b60200260200101516001600160a01b03167fff7dbb85c77ca68ca1f894d6498570e3d5095cd19466f07ee8d222b337e4068c60405160405180910390a25b6200032d81620007b2565b90506200028d565b505050565b60005b8251811015620003e5576200037983828151811062000360576200036062000786565b602002602001015160066200049160201b90919060201c565b15620003d25782818151811062000394576200039462000786565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b620003dd81620007b2565b90506200033d565b5060005b81518110156200033557620004258282815181106200040c576200040c62000786565b60200260200101516006620004b160201b90919060201c565b156200047e5781818151811062000440576200044062000786565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6200048981620007b2565b9050620003e9565b6000620004a8836001600160a01b038416620004c8565b90505b92915050565b6000620004a8836001600160a01b0384166200051a565b60008181526001830160205260408120546200051157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004ab565b506000620004ab565b600081815260018301602052604081205480156200061357600062000541600183620007ce565b85549091506000906200055790600190620007ce565b9050818114620005c35760008660000182815481106200057b576200057b62000786565b9060005260206000200154905080876000018481548110620005a157620005a162000786565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620005d757620005d7620007e4565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004ab565b6000915050620004ab565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200064c57600080fd5b919050565b600082601f8301126200066357600080fd5b815160206001600160401b03808311156200068257620006826200061e565b8260051b604051601f19603f83011681018181108482111715620006aa57620006aa6200061e565b604052938452858101830193838101925087851115620006c957600080fd5b83870191505b84821015620006f357620006e38262000634565b83529183019190830190620006cf565b979650505050505050565b6000806000606084860312156200071457600080fd5b83516001600160401b03808211156200072c57600080fd5b6200073a8783880162000651565b945060208601519150808211156200075157600080fd5b50620007608682870162000651565b925050604084015163ffffffff811681146200077b57600080fd5b809150509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201620007c757620007c76200079c565b5060010190565b81810381811115620004ab57620004ab6200079c565b634e487b7160e01b600052603160045260246000fd5b608051611a4d62000832600039600081816102eb01528181610acd01528181610b3601528181610c970152610d0c0152611a4d6000f3fe608060405234801561001057600080fd5b50600436106100ff5760003560e01c80637afac32211610097578063cdc73d5111610066578063cdc73d511461032a578063d02641a014610332578063f2fde38b146103d4578063ffdb4b37146103e757600080fd5b80637afac322146102a65780638da5cb5b146102b9578063a6c94a73146102e1578063bfcd45661461031557600080fd5b80634ab35b0b116100d35780634ab35b0b146101a8578063514e8cff146101e857806352877af01461028b57806379ba50971461029e57600080fd5b806241e5be14610104578063181f5a771461012a5780633937306f1461017357806345ac924d14610188575b600080fd5b6101176101123660046113bd565b61042f565b6040519081526020015b60405180910390f35b6101666040518060400160405280601381526020017f5072696365526567697374727920312e322e300000000000000000000000000081525081565b60405161012191906113f9565b610186610181366004611465565b61049b565b005b61019b6101963660046114a0565b6107bf565b6040516101219190611515565b6101bb6101b6366004611590565b610893565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610121565b61027e6101f63660046115c3565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b60405161012191906115de565b610186610299366004611731565b61089e565b6101866108b4565b6101866102b4366004611731565b6109b6565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610121565b60405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610121565b61031d6109c8565b6040516101219190611795565b61031d6109d9565b61027e610340366004611590565b60408051808201909152600080825260208201525073ffffffffffffffffffffffffffffffffffffffff166000908152600360209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6101866103e2366004611590565b6109e5565b6103fa6103f53660046117ef565b6109f9565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610121565b600061043a82610b84565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661046185610b84565b610489907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685611851565b6104939190611868565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906104cb57506104c9600433610d48565b155b15610502576040517f46f0815400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061050e82806118a3565b9050905060005b8181101561066057600061052984806118a3565b838181106105395761053961190b565b90506040020180360381019061054f9190611966565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600390975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926106479290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250610659816119a3565b9050610515565b50600061067060208401846118a3565b9050905060005b818110156107b957600061068e60208601866118a3565b8381811061069e5761069e61190b565b9050604002018036038101906106b491906119db565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600290975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926107a09290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a2506107b2816119a3565b9050610677565b50505050565b60608160008167ffffffffffffffff8111156107dd576107dd611619565b60405190808252806020026020018201604052801561082257816020015b60408051808201909152600080825260208201528152602001906001900390816107fb5790505b50905060005b828110156108885761085a8686838181106108455761084561190b565b90506020020160208101906103409190611590565b82828151811061086c5761086c61190b565b602002602001018190525080610881906119a3565b9050610828565b509150505b92915050565b600061088d82610b84565b6108a6610d7a565b6108b08282610dfd565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461093a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6109be610d7a565b6108b08282610f59565b60606109d460046110b0565b905090565b60606109d460066110b0565b6109ed610d7a565b6109f6816110bd565b50565b67ffffffffffffffff811660009081526002602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203610ab1576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610931565b6000816020015163ffffffff1642610ac991906119fe565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115610b6a576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610931565b610b7386610b84565b9151919350909150505b9250929050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff16918101829052901580610c2c575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15610c7b576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610931565b6000816020015163ffffffff1642610c9391906119fe565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115610d40576040517fc65fdfca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610931565b505192915050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dfb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610931565b565b60005b8251811015610ea857610e36838281518110610e1e57610e1e61190b565b602002602001015160046111b290919063ffffffff16565b15610e9857828181518110610e4d57610e4d61190b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f34a02290b7920078c19f58e94b78c77eb9cc10195b20676e19bd3b82085893b860405160405180910390a25b610ea1816119a3565b9050610e00565b5060005b8151811015610f5457610ee2828281518110610eca57610eca61190b565b602002602001015160046111d490919063ffffffff16565b15610f4457818181518110610ef957610ef961190b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fff7dbb85c77ca68ca1f894d6498570e3d5095cd19466f07ee8d222b337e4068c60405160405180910390a25b610f4d816119a3565b9050610eac565b505050565b60005b825181101561100457610f92838281518110610f7a57610f7a61190b565b602002602001015160066111b290919063ffffffff16565b15610ff457828181518110610fa957610fa961190b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b610ffd816119a3565b9050610f5c565b5060005b8151811015610f545761103e8282815181106110265761102661190b565b602002602001015160066111d490919063ffffffff16565b156110a0578181815181106110555761105561190b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6110a9816119a3565b9050611008565b60606000610d73836111f6565b3373ffffffffffffffffffffffffffffffffffffffff82160361113c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610931565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000610d738373ffffffffffffffffffffffffffffffffffffffff8416611252565b6000610d738373ffffffffffffffffffffffffffffffffffffffff84166112a1565b60608160000180548060200260200160405190810160405280929190818152602001828054801561124657602002820191906000526020600020905b815481526020019060010190808311611232575b50505050509050919050565b60008181526001830160205260408120546112995750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561088d565b50600061088d565b6000818152600183016020526040812054801561138a5760006112c56001836119fe565b85549091506000906112d9906001906119fe565b905081811461133e5760008660000182815481106112f9576112f961190b565b906000526020600020015490508087600001848154811061131c5761131c61190b565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061134f5761134f611a11565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061088d565b600091505061088d565b803573ffffffffffffffffffffffffffffffffffffffff811681146113b857600080fd5b919050565b6000806000606084860312156113d257600080fd5b6113db84611394565b9250602084013591506113f060408501611394565b90509250925092565b600060208083528351808285015260005b818110156114265785810183015185820160400152820161140a565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561147757600080fd5b813567ffffffffffffffff81111561148e57600080fd5b820160408185031215610d7357600080fd5b600080602083850312156114b357600080fd5b823567ffffffffffffffff808211156114cb57600080fd5b818501915085601f8301126114df57600080fd5b8135818111156114ee57600080fd5b8660208260051b850101111561150357600080fd5b60209290920196919550909350505050565b602080825282518282018190526000919060409081850190868401855b828110156115835761157384835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101611532565b5091979650505050505050565b6000602082840312156115a257600080fd5b610d7382611394565b803567ffffffffffffffff811681146113b857600080fd5b6000602082840312156115d557600080fd5b610d73826115ab565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff16908201526040810161088d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561166b5761166b611619565b60405290565b600082601f83011261168257600080fd5b8135602067ffffffffffffffff8083111561169f5761169f611619565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811084821117156116e2576116e2611619565b60405293845285810183019383810192508785111561170057600080fd5b83870191505b848210156117265761171782611394565b83529183019190830190611706565b979650505050505050565b6000806040838503121561174457600080fd5b823567ffffffffffffffff8082111561175c57600080fd5b61176886838701611671565b9350602085013591508082111561177e57600080fd5b5061178b85828601611671565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156117e357835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016117b1565b50909695505050505050565b6000806040838503121561180257600080fd5b61180b83611394565b9150611819602084016115ab565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761088d5761088d611822565b60008261189e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126118d857600080fd5b83018035915067ffffffffffffffff8211156118f357600080fd5b6020019150600681901b3603821315610b7d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146113b857600080fd5b60006040828403121561197857600080fd5b611980611648565b61198983611394565b81526119976020840161193a565b60208201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036119d4576119d4611822565b5060010190565b6000604082840312156119ed57600080fd5b6119f5611648565b611989836115ab565b8181038181111561088d5761088d611822565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000015f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000d6a6ba37faac229b9665e86739ca501401f5a940000000000000000000000000fc00000000000000000000000000000000000006
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ff5760003560e01c80637afac32211610097578063cdc73d5111610066578063cdc73d511461032a578063d02641a014610332578063f2fde38b146103d4578063ffdb4b37146103e757600080fd5b80637afac322146102a65780638da5cb5b146102b9578063a6c94a73146102e1578063bfcd45661461031557600080fd5b80634ab35b0b116100d35780634ab35b0b146101a8578063514e8cff146101e857806352877af01461028b57806379ba50971461029e57600080fd5b806241e5be14610104578063181f5a771461012a5780633937306f1461017357806345ac924d14610188575b600080fd5b6101176101123660046113bd565b61042f565b6040519081526020015b60405180910390f35b6101666040518060400160405280601381526020017f5072696365526567697374727920312e322e300000000000000000000000000081525081565b60405161012191906113f9565b610186610181366004611465565b61049b565b005b61019b6101963660046114a0565b6107bf565b6040516101219190611515565b6101bb6101b6366004611590565b610893565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610121565b61027e6101f63660046115c3565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b60405161012191906115de565b610186610299366004611731565b61089e565b6101866108b4565b6101866102b4366004611731565b6109b6565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610121565b60405163ffffffff7f0000000000000000000000000000000000000000000000000000000000015f90168152602001610121565b61031d6109c8565b6040516101219190611795565b61031d6109d9565b61027e610340366004611590565b60408051808201909152600080825260208201525073ffffffffffffffffffffffffffffffffffffffff166000908152600360209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6101866103e2366004611590565b6109e5565b6103fa6103f53660046117ef565b6109f9565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610121565b600061043a82610b84565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661046185610b84565b610489907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685611851565b6104939190611868565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906104cb57506104c9600433610d48565b155b15610502576040517f46f0815400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061050e82806118a3565b9050905060005b8181101561066057600061052984806118a3565b838181106105395761053961190b565b90506040020180360381019061054f9190611966565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600390975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926106479290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250610659816119a3565b9050610515565b50600061067060208401846118a3565b9050905060005b818110156107b957600061068e60208601866118a3565b8381811061069e5761069e61190b565b9050604002018036038101906106b491906119db565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600290975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926107a09290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a2506107b2816119a3565b9050610677565b50505050565b60608160008167ffffffffffffffff8111156107dd576107dd611619565b60405190808252806020026020018201604052801561082257816020015b60408051808201909152600080825260208201528152602001906001900390816107fb5790505b50905060005b828110156108885761085a8686838181106108455761084561190b565b90506020020160208101906103409190611590565b82828151811061086c5761086c61190b565b602002602001018190525080610881906119a3565b9050610828565b509150505b92915050565b600061088d82610b84565b6108a6610d7a565b6108b08282610dfd565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461093a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6109be610d7a565b6108b08282610f59565b60606109d460046110b0565b905090565b60606109d460066110b0565b6109ed610d7a565b6109f6816110bd565b50565b67ffffffffffffffff811660009081526002602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203610ab1576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610931565b6000816020015163ffffffff1642610ac991906119fe565b90507f0000000000000000000000000000000000000000000000000000000000015f9063ffffffff16811115610b6a576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f0000000000000000000000000000000000000000000000000000000000015f9016602482015260448101829052606401610931565b610b7386610b84565b9151919350909150505b9250929050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff16918101829052901580610c2c575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15610c7b576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610931565b6000816020015163ffffffff1642610c9391906119fe565b90507f0000000000000000000000000000000000000000000000000000000000015f9063ffffffff16811115610d40576040517fc65fdfca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015263ffffffff7f0000000000000000000000000000000000000000000000000000000000015f9016602482015260448101829052606401610931565b505192915050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dfb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610931565b565b60005b8251811015610ea857610e36838281518110610e1e57610e1e61190b565b602002602001015160046111b290919063ffffffff16565b15610e9857828181518110610e4d57610e4d61190b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f34a02290b7920078c19f58e94b78c77eb9cc10195b20676e19bd3b82085893b860405160405180910390a25b610ea1816119a3565b9050610e00565b5060005b8151811015610f5457610ee2828281518110610eca57610eca61190b565b602002602001015160046111d490919063ffffffff16565b15610f4457818181518110610ef957610ef961190b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fff7dbb85c77ca68ca1f894d6498570e3d5095cd19466f07ee8d222b337e4068c60405160405180910390a25b610f4d816119a3565b9050610eac565b505050565b60005b825181101561100457610f92838281518110610f7a57610f7a61190b565b602002602001015160066111b290919063ffffffff16565b15610ff457828181518110610fa957610fa961190b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b610ffd816119a3565b9050610f5c565b5060005b8151811015610f545761103e8282815181106110265761102661190b565b602002602001015160066111d490919063ffffffff16565b156110a0578181815181106110555761105561190b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6110a9816119a3565b9050611008565b60606000610d73836111f6565b3373ffffffffffffffffffffffffffffffffffffffff82160361113c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610931565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000610d738373ffffffffffffffffffffffffffffffffffffffff8416611252565b6000610d738373ffffffffffffffffffffffffffffffffffffffff84166112a1565b60608160000180548060200260200160405190810160405280929190818152602001828054801561124657602002820191906000526020600020905b815481526020019060010190808311611232575b50505050509050919050565b60008181526001830160205260408120546112995750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561088d565b50600061088d565b6000818152600183016020526040812054801561138a5760006112c56001836119fe565b85549091506000906112d9906001906119fe565b905081811461133e5760008660000182815481106112f9576112f961190b565b906000526020600020015490508087600001848154811061131c5761131c61190b565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061134f5761134f611a11565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061088d565b600091505061088d565b803573ffffffffffffffffffffffffffffffffffffffff811681146113b857600080fd5b919050565b6000806000606084860312156113d257600080fd5b6113db84611394565b9250602084013591506113f060408501611394565b90509250925092565b600060208083528351808285015260005b818110156114265785810183015185820160400152820161140a565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561147757600080fd5b813567ffffffffffffffff81111561148e57600080fd5b820160408185031215610d7357600080fd5b600080602083850312156114b357600080fd5b823567ffffffffffffffff808211156114cb57600080fd5b818501915085601f8301126114df57600080fd5b8135818111156114ee57600080fd5b8660208260051b850101111561150357600080fd5b60209290920196919550909350505050565b602080825282518282018190526000919060409081850190868401855b828110156115835761157384835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101611532565b5091979650505050505050565b6000602082840312156115a257600080fd5b610d7382611394565b803567ffffffffffffffff811681146113b857600080fd5b6000602082840312156115d557600080fd5b610d73826115ab565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff16908201526040810161088d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561166b5761166b611619565b60405290565b600082601f83011261168257600080fd5b8135602067ffffffffffffffff8083111561169f5761169f611619565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811084821117156116e2576116e2611619565b60405293845285810183019383810192508785111561170057600080fd5b83870191505b848210156117265761171782611394565b83529183019190830190611706565b979650505050505050565b6000806040838503121561174457600080fd5b823567ffffffffffffffff8082111561175c57600080fd5b61176886838701611671565b9350602085013591508082111561177e57600080fd5b5061178b85828601611671565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156117e357835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016117b1565b50909695505050505050565b6000806040838503121561180257600080fd5b61180b83611394565b9150611819602084016115ab565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761088d5761088d611822565b60008261189e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126118d857600080fd5b83018035915067ffffffffffffffff8211156118f357600080fd5b6020019150600681901b3603821315610b7d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146113b857600080fd5b60006040828403121561197857600080fd5b611980611648565b61198983611394565b81526119976020840161193a565b60208201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036119d4576119d4611822565b5060010190565b6000604082840312156119ed57600080fd5b6119f5611648565b611989836115ab565b8181038181111561088d5761088d611822565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000015f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000d6a6ba37faac229b9665e86739ca501401f5a940000000000000000000000000fc00000000000000000000000000000000000006
-----Decoded View---------------
Arg [0] : priceUpdaters (address[]):
Arg [1] : feeTokens (address[]): 0xd6A6ba37fAaC229B9665E86739ca501401f5a940,0xFC00000000000000000000000000000000000006
Arg [2] : stalenessThreshold (uint32): 90000
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 0000000000000000000000000000000000000000000000000000000000015f90
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [5] : 000000000000000000000000d6a6ba37faac229b9665e86739ca501401f5a940
Arg [6] : 000000000000000000000000fc00000000000000000000000000000000000006
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.