Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
Minimal Proxy Contract for 0x87275b34b6c55ee722e66751fe4590f5c2aca82c
Contract Name:
ChainlinkV3Oracle
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
1234567891011121314151617181920212223242526// SPDX-License-Identifier: GPL-2.0-or-laterpragma solidity 0.8.28;import {Initializable} from "openzeppelin5-upgradeable/proxy/utils/Initializable.sol";import {IERC20Metadata} from "openzeppelin5/token/ERC20/extensions/IERC20Metadata.sol";import {AggregatorV3Interface} from "chainlink/v0.8/interfaces/AggregatorV3Interface.sol";import {ISiloOracle} from "silo-core/contracts/interfaces/ISiloOracle.sol";import {OracleNormalization} from "../lib/OracleNormalization.sol";import {ChainlinkV3OracleConfig} from "./ChainlinkV3OracleConfig.sol";import {IChainlinkV3Oracle} from "../interfaces/IChainlinkV3Oracle.sol";contract ChainlinkV3Oracle is IChainlinkV3Oracle, ISiloOracle, Initializable {ChainlinkV3OracleConfig public oracleConfig;/// @custom:oz-upgrades-unsafe-allow constructorconstructor() {_disableInitializers();}/// @notice validation of config is checked in factory, therefore you should not deploy and initialize directly/// use factory always.function initialize(ChainlinkV3OracleConfig _configAddress) external virtual initializer {oracleConfig = _configAddress;emit ChainlinkV3ConfigDeployed(_configAddress);}
1234567891011121314151617181920212223242526// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)pragma solidity ^0.8.20;/*** @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.** The initialization functions use a version number. Once a version number is used, it is consumed and cannot be* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in* case an upgrade adds a module that needs to be initialized.** For example:** [.hljs-theme-light.nopadding]* ```solidity* contract MyToken is ERC20Upgradeable {* function initialize() initializer public {* __ERC20_init("MyToken", "MTK");* }* }** contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
1234567891011121314151617181920212223242526// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)pragma solidity ^0.8.20;import {IERC20} from "../IERC20.sol";/*** @dev Interface for the optional metadata functions from the ERC-20 standard.*/interface IERC20Metadata is IERC20 {/*** @dev Returns the name of the token.*/function name() external view returns (string memory);/*** @dev Returns the symbol of the token.*/function symbol() external view returns (string memory);/*** @dev Returns the decimals places of the token.*/function decimals() external view returns (uint8);}
12345678910111213141516171819// SPDX-License-Identifier: MITpragma solidity ^0.8.0;interface AggregatorV3Interface {function decimals() external view returns (uint8);function description() external view returns (string memory);function version() external view returns (uint256);function getRoundData(uint80 _roundId) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);function latestRoundData()externalviewreturns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);}
12345678910111213141516171819// SPDX-License-Identifier: MITpragma solidity >=0.5.0;interface ISiloOracle {/// @notice Hook function to call before `quote` function reads price/// @dev This hook function can be used to change state right before the price is read. For example it can be used/// for curve read only reentrancy protection. In majority of implementations this will be an empty function./// WARNING: reverts are propagated to Silo so if `beforeQuote` reverts, Silo reverts as well./// @param _baseToken Address of priced tokenfunction beforeQuote(address _baseToken) external;/// @return quoteAmount Returns quote price for _baseAmount of _baseToken/// @param _baseAmount Amount of priced token/// @param _baseToken Address of priced tokenfunction quote(uint256 _baseAmount, address _baseToken) external view returns (uint256 quoteAmount);/// @return address of token in which quote (price) is denominatedfunction quoteToken() external view returns (address);}
1234567891011121314151617181920212223242526// SPDX-License-Identifier: GPL-2.0-or-laterpragma solidity ^0.8.20;import {IERC20Metadata} from "openzeppelin5/token/ERC20/extensions/IERC20Metadata.sol";import {TokenHelper} from "silo-core/contracts/lib/TokenHelper.sol";/// @notice please read carefully unchecked comments, there are some requirements tht must be met in order to not/// over/under flow/// @dev Rounding error policy./// We're always rounding down by using build-in solidity way for division.////// During normalization we're executing division by `_normalizationDivider` (unless there is multiplicator)/// and `_secondPrice` (in case second price exist). You can expect rounding errors to be in exclusive range of (0, 1)/// when doing division. What does it means? This means, that you can be short by up to 1 wei on result./// eg. when normalising 12_345 (value with 3 decimals) to 2 decimals representation you lose last digit and end result/// will be 12_34./// What are consequences for protocol?/// Eg. if 987 of tokens A is worth 12.34 tokens B (after normalization), by losing 0.005 we made tokens A worth a bit/// more than they really are. If we would round up, then tokens A would be a bit less expensive./// Keep in mind we are talking tiny values. There is no argument that can tell which approach is correct./// Considering that prices themselves are changing constantly (if you think about it, they are just random numbers/// close to previous value) and even TWAP price can be manipulated up to some level, if we compare this to rounding/// error, the rounding error has no meaning at all./// Most important part is: how are we using prices in Silo and how rounding error affects the system?/// We're using prices to calculate LTV. We're deciding how much of token you can borrow but once you borrow you need to/// repay that amount (plus interest). Price of the token has no influence on how much you repay.
1234567891011121314151617181920212223242526// SPDX-License-Identifier: GPL-2.0-or-laterpragma solidity 0.8.28;import {IERC20Metadata} from "openzeppelin5/token/ERC20/extensions/IERC20Metadata.sol";import {AggregatorV3Interface} from "chainlink/v0.8/interfaces/AggregatorV3Interface.sol";import {ISiloOracle} from "silo-core/contracts/interfaces/ISiloOracle.sol";import {IChainlinkV3Oracle} from "../interfaces/IChainlinkV3Oracle.sol";import {Layer1OracleConfig} from "../_common/Layer1OracleConfig.sol";contract ChainlinkV3OracleConfig is Layer1OracleConfig {/// @dev Chainlink aggregatorAggregatorV3Interface internal immutable _AGGREGATOR; // solhint-disable-line var-name-mixedcase/// @dev secondary Chainlink aggregator to convert price to quoteAggregatorV3Interface internal immutable _SECONDARY_AGGREGATOR; // solhint-disable-line var-name-mixedcase/// @dev Threshold used to determine if the price returned by the _SECONDARY_AGGREGATOR is validuint256 internal immutable _SECONDARY_HEARTBEAT; // solhint-disable-line var-name-mixedcase/// @dev this can be set to true to convert primary price into price denominated in quote/// assuming that both AGGREGATORS providing price in the same tokenbool internal immutable _CONVERT_TO_QUOTE; // solhint-disable-line var-name-mixedcase/// @dev all verification should be done by factoryconstructor(IChainlinkV3Oracle.ChainlinkV3DeploymentConfig memory _config,
1234567891011121314151617181920212223242526// SPDX-License-Identifier: MITpragma solidity >=0.8.0;import {IERC20Metadata} from "openzeppelin5/token/ERC20/extensions/IERC20Metadata.sol";import {AggregatorV3Interface} from "chainlink/v0.8/interfaces/AggregatorV3Interface.sol";import {ChainlinkV3OracleConfig} from "../chainlinkV3/ChainlinkV3OracleConfig.sol";interface IChainlinkV3Oracle {/// @dev config based on which new oracle will be deployed/// @notice there is no way to check if aggregators match tokens, so it is users job to verify config./// @param primaryAggregator used to read price from chainlink, if it can not provide price in quote token,/// then you have to setup secondary one that will do the job/// @param secondaryAggregator if set, it is used translate primary price into quote price eg:/// primary price is ABC/USD and secondary is ETH/USD, then result will be price in ABC/ETH/// @param baseToken base token address, it must have decimals() method available/// @param quoteToken quote toke address, it must have decimals() method available/// @param primaryHeartbeat heartbeat of primary price/// @param secondaryHeartbeat heartbeat of secondary pricestruct ChainlinkV3DeploymentConfig {IERC20Metadata baseToken;IERC20Metadata quoteToken;AggregatorV3Interface primaryAggregator;uint32 primaryHeartbeat;AggregatorV3Interface secondaryAggregator;uint32 secondaryHeartbeat;}
1234567891011121314151617181920212223242526// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)pragma solidity ^0.8.20;/*** @dev Interface of the ERC-20 standard as defined in the ERC.*/interface IERC20 {/*** @dev Emitted when `value` tokens are moved from one account (`from`) to* another (`to`).** Note that `value` may be zero.*/event Transfer(address indexed from, address indexed to, uint256 value);/*** @dev Emitted when the allowance of a `spender` for an `owner` is set by* a call to {approve}. `value` is the new allowance.*/event Approval(address indexed owner, address indexed spender, uint256 value);/*** @dev Returns the value of tokens in existence.*/
1234567891011121314151617181920212223242526// SPDX-License-Identifier: BUSL-1.1pragma solidity ^0.8.28;import {IERC20Metadata} from "openzeppelin5/token/ERC20/extensions/IERC20Metadata.sol";import {IsContract} from "./IsContract.sol";library TokenHelper {uint256 private constant _BYTES32_SIZE = 32;error TokenIsNotAContract();function assertAndGetDecimals(address _token) internal view returns (uint256) {(bool hasMetadata, bytes memory data) =_tokenMetadataCall(_token, abi.encodeCall(IERC20Metadata.decimals, ()));// decimals() is optional in the ERC20 standard, so if metadata is not accessible// we assume there are no decimals and use 0.if (!hasMetadata) {return 0;}return abi.decode(data, (uint8));}/// @dev Returns the symbol for the provided ERC20 token.
1234567891011121314151617181920212223242526// SPDX-License-Identifier: MITpragma solidity 0.8.28;import {IERC20Metadata} from "openzeppelin5/token/ERC20/extensions/IERC20Metadata.sol";/// @notice to keep config contract size low (this is the one that will be deployed each time)/// factory contract take over verification. You should not deploy or use config that was not created by factory./// @dev This is common config for Layer1 oraclesabstract contract Layer1OracleConfig {/// @dev price must be updated at least once every `_HEARTBEAT` seconds, otherwise something is wronguint256 internal immutable _HEARTBEAT; // solhint-disable-line var-name-mixedcase/// @dev constant used for normalising priceuint256 internal immutable _DECIMALS_NORMALIZATION_DIVIDER; // solhint-disable-line var-name-mixedcase/// @dev constant used for normalising priceuint256 internal immutable _DECIMALS_NORMALIZATION_MULTIPLIER; // solhint-disable-line var-name-mixedcaseIERC20Metadata internal immutable _BASE_TOKEN; // solhint-disable-line var-name-mixedcaseIERC20Metadata internal immutable _QUOTE_TOKEN; // solhint-disable-line var-name-mixedcase/// @dev all verification should be done by factoryconstructor(IERC20Metadata _baseToken,IERC20Metadata _quoteToken,uint256 _heartbeat,
1234567891011121314151617181920212223242526// SPDX-License-Identifier: BUSL-1.1pragma solidity ^0.8.24;library IsContract {/*** @dev Returns true if `account` is a contract.** [IMPORTANT]* ====* It is unsafe to assume that an address for which this function returns* false is an externally-owned account (EOA) and not a contract.** Among others, `isContract` will return false for the following* types of addresses:** - an externally-owned account* - a contract in construction* - an address where a contract will be created* - an address where a contract lived, but was destroyed** Furthermore, `isContract` will also return true if the target contract within* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,* which only has an effect at the end of a transaction.* ====** [IMPORTANT]
1234567891011121314151617181920212223242526{"remappings": ["forge-std/=gitmodules/forge-std/src/","silo-foundry-utils/=gitmodules/silo-foundry-utils/contracts/","properties/=gitmodules/crytic/properties/contracts/","silo-core/=silo-core/","silo-oracles/=silo-oracles/","silo-vaults/=silo-vaults/","ve-silo/=ve-silo/","@openzeppelin/=gitmodules/openzeppelin-contracts-5/contracts/","morpho-blue/=gitmodules/morpho-blue/src/","openzeppelin5/=gitmodules/openzeppelin-contracts-5/contracts/","openzeppelin5-upgradeable/=gitmodules/openzeppelin-contracts-upgradeable-5/contracts/","chainlink/=gitmodules/chainlink/contracts/src/","chainlink-ccip/=gitmodules/chainlink-ccip/contracts/src/","uniswap/=gitmodules/uniswap/","@uniswap/v3-core/=gitmodules/uniswap/v3-core/","balancer-labs/v2-solidity-utils/=external/balancer-v2-monorepo/pkg/solidity-utils/contracts/","balancer-labs/v2-interfaces/=external/balancer-v2-monorepo/pkg/interfaces/contracts/","balancer-labs/v2-liquidity-mining/=external/balancer-v2-monorepo/pkg/liquidity-mining/contracts/","@balancer-labs/=node_modules/@balancer-labs/","@ensdomains/=node_modules/@ensdomains/","@openzeppelin/contracts-upgradeable/=gitmodules/openzeppelin-contracts-upgradeable-5/contracts/","@openzeppelin/contracts/=gitmodules/openzeppelin-contracts-5/contracts/","@solidity-parser/=node_modules/@solidity-parser/","ERC4626/=gitmodules/crytic/properties/lib/ERC4626/contracts/",
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"AggregatorsAreTheSame","type":"error"},{"inputs":[],"name":"AssetNotSupported","type":"error"},{"inputs":[],"name":"BaseAmountOverflow","type":"error"},{"inputs":[],"name":"InvalidEthAggregatorDecimals","type":"error"},{"inputs":[],"name":"InvalidEthHeartbeat","type":"error"},{"inputs":[],"name":"InvalidHeartbeat","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidPrice","type":"error"},{"inputs":[],"name":"InvalidSecondPrice","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"QuoteTokenNotMatchEth","type":"error"},{"inputs":[],"name":"TokensAreTheSame","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"contract AggregatorV3Interface","name":"aggregator","type":"address"}],"name":"AggregatorDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ChainlinkV3OracleConfig","name":"configAddress","type":"address"}],"name":"ChainlinkV3ConfigDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"contract AggregatorV3Interface","name":"aggregator","type":"address"},{"indexed":false,"internalType":"bool","name":"convertToQuote","type":"bool"}],"name":"NewAggregator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"heartbeat","type":"uint256"}],"name":"NewHeartbeat","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"heartbeat","type":"uint256"}],"name":"NewQuoteAggregatorHeartbeat","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"beforeQuote","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bool","name":"_primary","type":"bool"}],"name":"getAggregatorPrice","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ChainlinkV3OracleConfig","name":"_configAddress","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracleConfig","outputs":[{"internalType":"contract ChainlinkV3OracleConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_baseAmount","type":"uint256"},{"internalType":"address","name":"_baseToken","type":"address"}],"name":"quote","outputs":[{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quoteToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.