Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
ProductApi3ReaderProxyV1
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 1000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;
import "./interfaces/IApi3ReaderProxyWithDappId.sol";
import "./interfaces/IProductApi3ReaderProxyV1.sol";
/// @title An immutable proxy contract that is used to read a composition of two
/// IApi3ReaderProxyWithDappId data feeds by multiplying their values
/// @dev This contract implements the AggregatorV2V3Interface to be compatible
/// with Chainlink aggregators. This allows the contract to be used as a drop-in
/// replacement for Chainlink aggregators in existing dApps.
/// Refer to https://github.com/api3dao/migrate-from-chainlink-to-api3 for more
/// information about the Chainlink interface implementation.
contract ProductApi3ReaderProxyV1 is IProductApi3ReaderProxyV1 {
/// @notice First IApi3ReaderProxyWithDappId contract address
address public immutable override proxy1;
/// @notice Second IApi3ReaderProxyWithDappId contract address
address public immutable override proxy2;
/// @notice The dApp ID of the two proxies
uint256 public immutable override dappId;
/// @param proxy1_ First IApi3ReaderProxyWithDappId contract address
/// @param proxy2_ Second IApi3ReaderProxyWithDappId contract address
constructor(address proxy1_, address proxy2_) {
if (proxy1_ == address(0) || proxy2_ == address(0)) {
revert ZeroProxyAddress();
}
if (proxy1_ == proxy2_) {
revert SameProxyAddress();
}
uint256 dappId1 = IApi3ReaderProxyWithDappId(proxy1_).dappId();
uint256 dappId2 = IApi3ReaderProxyWithDappId(proxy2_).dappId();
if (dappId1 != dappId2) {
revert DappIdMismatch();
}
proxy1 = proxy1_;
proxy2 = proxy2_;
dappId = dappId1;
}
/// @notice Returns the current value and timestamp of the rate composition
/// between two IApi3ReaderProxyWithDappId proxies by multiplying their
/// values
/// @dev Calculates product as `(int256(value1) * int256(value2)) / 1e18`.
/// The initial multiplication `int256(value1) * int256(value2)` may revert
/// on `int256` overflow. The final `int256` result of the full expression
/// is then cast to `int224`. This cast is unchecked for gas optimization
/// and may silently truncate if the result exceeds `int224` limits.
/// The returned timestamp is `block.timestamp`, reflecting the on-chain
/// computation time of the product. Underlying feed timestamps are not
/// aggregated due to complexity and potential for misinterpretation.
/// @return value Value of the product of the two proxies
/// @return timestamp Timestamp of the current block
function read()
public
view
override
returns (int224 value, uint32 timestamp)
{
(int224 value1, ) = IApi3ReaderProxyWithDappId(proxy1).read();
(int224 value2, ) = IApi3ReaderProxyWithDappId(proxy2).read();
value = int224((int256(value1) * int256(value2)) / 1e18);
timestamp = uint32(block.timestamp);
}
/// @dev AggregatorV2V3Interface users are already responsible with
/// validating the values that they receive (e.g., revert if the spot price
/// of an asset is negative). Therefore, this contract omits validation.
function latestAnswer() external view override returns (int256 value) {
(value, ) = read();
}
/// @dev A Chainlink feed contract returns the block timestamp at which the
/// feed was last updated. On the other hand, an Api3 feed timestamp
/// denotes the point in time at which the first-party oracles signed the
/// data used to do the last update. We find this to be a reasonable
/// approximation, considering that usually the timestamp is only used to
/// check if the last update is stale.
function latestTimestamp()
external
view
override
returns (uint256 timestamp)
{
(, timestamp) = read();
}
/// @dev Api3 feeds are updated asynchronously and not in rounds
function latestRound() external pure override returns (uint256) {
revert FunctionIsNotSupported();
}
/// @dev Functions that use the round ID as an argument are not supported
function getAnswer(uint256) external pure override returns (int256) {
revert FunctionIsNotSupported();
}
/// @dev Functions that use the round ID as an argument are not supported
function getTimestamp(uint256) external pure override returns (uint256) {
revert FunctionIsNotSupported();
}
/// @dev Api3 feeds always use 18 decimals
function decimals() external pure override returns (uint8) {
return 18;
}
/// @dev Underlying proxies dApp ID and dAPI name act as the description, and
/// this is left empty to save gas on contract deployment
function description() external pure override returns (string memory) {
return "";
}
/// @dev A unique version is chosen to easily check if an unverified
/// contract that acts as a Chainlink feed is a ProductApi3ReaderProxyV1
function version() external pure override returns (uint256) {
return 4914;
}
/// @dev Functions that use the round ID as an argument are not supported
function getRoundData(
uint80
)
external
pure
override
returns (uint80, int256, uint256, uint256, uint80)
{
revert FunctionIsNotSupported();
}
/// @dev Rounds IDs are returned as `0` as invalid values.
/// Similar to `latestAnswer()`, we leave the validation of the returned
/// value to the caller.
function latestRoundData()
external
view
override
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
roundId = answeredInRound = 0;
(answer, startedAt) = read();
updatedAt = startedAt;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Interface of the proxy contract that is used to read a specific API3
/// data feed
/// @notice While reading API3 data feeds, users are strongly recommended to
/// use this interface to interact with data feed-specific proxy contracts,
/// rather than accessing the underlying contracts directly
interface IApi3ReaderProxy {
/// @notice Returns the current value and timestamp of the API3 data feed
/// associated with the proxy contract
/// @dev The user is responsible for validating the returned data. For
/// example, if `value` is the spot price of an asset, it would be
/// reasonable to reject values that are not positive.
/// `timestamp` does not necessarily refer to a timestamp of the chain that
/// the read proxy is deployed on. Considering that it may refer to an
/// off-chain time (such as the system time of the data sources, or the
/// timestamp of another chain), the user should not expect it to be
/// strictly bounded by `block.timestamp`.
/// Considering that the read proxy contract may be upgradeable, the user
/// should not assume any hard guarantees about the behavior in general.
/// For example, even though it may sound reasonable to expect `timestamp`
/// to never decrease over time and the current implementation of the proxy
/// contract guarantees it, technically, an upgrade can cause `timestamp`
/// to decrease. Therefore, the user should be able to handle any change in
/// behavior, which may include reverting gracefully.
/// @return value Data feed value
/// @return timestamp Data feed timestamp
function read() external view returns (int224 value, uint32 timestamp);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;
import "@api3/contracts/interfaces/IApi3ReaderProxy.sol";
interface IApi3ReaderProxyWithDappId is IApi3ReaderProxy {
function dappId() external view returns (uint256);
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../vendor/@chainlink/[email protected]/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol"; import "./IApi3ReaderProxyWithDappId.sol"; interface IProductApi3ReaderProxyV1 is IApi3ReaderProxyWithDappId, AggregatorV2V3Interface { error ZeroProxyAddress(); error SameProxyAddress(); error DappIdMismatch(); error ZeroDenominator(); error FunctionIsNotSupported(); function proxy1() external view returns (address); function proxy2() external view returns (address); }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// solhint-disable-next-line interface-starts-with-i
interface AggregatorInterface {
function latestAnswer() external view returns (int256);
function latestTimestamp() external view returns (uint256);
function latestRound() external view returns (uint256);
function getAnswer(uint256 roundId) external view returns (int256);
function getTimestamp(uint256 roundId) external view returns (uint256);
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {AggregatorInterface} from "./AggregatorInterface.sol";
import {AggregatorV3Interface} from "./AggregatorV3Interface.sol";
// solhint-disable-next-line interface-starts-with-i
interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// solhint-disable-next-line interface-starts-with-i
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()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}{
"optimizer": {
"enabled": true,
"runs": 1000
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"proxy1_","type":"address"},{"internalType":"address","name":"proxy2_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DappIdMismatch","type":"error"},{"inputs":[],"name":"FunctionIsNotSupported","type":"error"},{"inputs":[],"name":"SameProxyAddress","type":"error"},{"inputs":[],"name":"ZeroDenominator","type":"error"},{"inputs":[],"name":"ZeroProxyAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"int256","name":"current","type":"int256"},{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"updatedAt","type":"uint256"}],"name":"AnswerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"startedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"startedAt","type":"uint256"}],"name":"NewRound","type":"event"},{"inputs":[],"name":"dappId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getAnswer","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint80","name":"","type":"uint80"}],"name":"getRoundData","outputs":[{"internalType":"uint80","name":"","type":"uint80"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint80","name":"","type":"uint80"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"latestAnswer","outputs":[{"internalType":"int256","name":"value","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestTimestamp","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"read","outputs":[{"internalType":"int224","name":"value","type":"int224"},{"internalType":"uint32","name":"timestamp","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
60e060405234801561001057600080fd5b5060405161083f38038061083f83398101604081905261002f916101c0565b6001600160a01b038216158061004c57506001600160a01b038116155b1561006a57604051635d0b813f60e11b815260040160405180910390fd5b806001600160a01b0316826001600160a01b03160361009c5760405163117eed8360e31b815260040160405180910390fd5b6000826001600160a01b0316639de0eb046040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061010091906101f3565b90506000826001600160a01b0316639de0eb046040518163ffffffff1660e01b8152600401602060405180830381865afa158015610142573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061016691906101f3565b905080821461018857604051631f23f29f60e01b815260040160405180910390fd5b506001600160a01b03928316608052911660a05260c05261020c565b80516001600160a01b03811681146101bb57600080fd5b919050565b600080604083850312156101d357600080fd5b6101dc836101a4565b91506101ea602084016101a4565b90509250929050565b60006020828403121561020557600080fd5b5051919050565b60805160a05160c0516105f6610249600039600061023401526000818161016f015261031e0152600081816101bb015261028b01526105f66000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80637dc93bb01161008c5780639de0eb04116100665780639de0eb041461022f578063b5ab58dc14610256578063b633620c14610256578063feaf968c1461026957600080fd5b80637dc93bb0146101b65780638205bf6a146101dd5780639a6fc8f5146101e557600080fd5b806357de26a4116100c857806357de26a414610121578063668a0f02146101485780637284e416146101505780637d7a2fd11461016a57600080fd5b8063313ce567146100ef57806350d25bcd1461010357806354fd4d5014610119575b600080fd5b604051601281526020015b60405180910390f35b61010b610271565b6040519081526020016100fa565b61133261010b565b610129610284565b60408051601b9390930b835263ffffffff9091166020830152016100fa565b61010b6103dc565b604080516020810182526000815290516100fa9190610455565b6101917f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fa565b6101917f000000000000000000000000000000000000000000000000000000000000000081565b61010b6103f7565b6101f86101f33660046104a3565b61040d565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016100fa565b61010b7f000000000000000000000000000000000000000000000000000000000000000081565b61010b6102643660046104d6565b6103dc565b6101f861042e565b600061027b610284565b50601b0b919050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166357de26a46040518163ffffffff1660e01b81526004016040805180830381865afa1580156102f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031791906104ef565b50905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166357de26a46040518163ffffffff1660e01b81526004016040805180830381865afa158015610386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103aa91906104ef565b509050670de0b6b3a764000081601b0b83601b0b6103c8919061054e565b6103d29190610584565b9442945092505050565b6000604051631fc30cb960e01b815260040160405180910390fd5b6000610401610284565b63ffffffff1692915050565b6000806000806000604051631fc30cb960e01b815260040160405180910390fd5b60008080808061043c610284565b9596601b9190910b9563ffffffff169450849350909150565b602081526000825180602084015260005b818110156104835760208186018101516040868401015201610466565b506000604082850101526040601f19601f83011684010191505092915050565b6000602082840312156104b557600080fd5b813569ffffffffffffffffffff811681146104cf57600080fd5b9392505050565b6000602082840312156104e857600080fd5b5035919050565b6000806040838503121561050257600080fd5b825180601b0b811461051357600080fd5b602084015190925063ffffffff8116811461052d57600080fd5b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b80820260008212600160ff1b8414161561056a5761056a610538565b818105831482151761057e5761057e610538565b92915050565b6000826105a157634e487b7160e01b600052601260045260246000fd5b600160ff1b8214600019841416156105bb576105bb610538565b50059056fea2646970667358221220779003252004998ba3107e7fb072163e2e41a6d909ab0d9c90f03d27b23657ab64736f6c634300081b0033000000000000000000000000b4dcf173558de885a9365a7addaaf1f6329905f20000000000000000000000008059fc11d8b0de9575213793d6b222ba7233a658
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c80637dc93bb01161008c5780639de0eb04116100665780639de0eb041461022f578063b5ab58dc14610256578063b633620c14610256578063feaf968c1461026957600080fd5b80637dc93bb0146101b65780638205bf6a146101dd5780639a6fc8f5146101e557600080fd5b806357de26a4116100c857806357de26a414610121578063668a0f02146101485780637284e416146101505780637d7a2fd11461016a57600080fd5b8063313ce567146100ef57806350d25bcd1461010357806354fd4d5014610119575b600080fd5b604051601281526020015b60405180910390f35b61010b610271565b6040519081526020016100fa565b61133261010b565b610129610284565b60408051601b9390930b835263ffffffff9091166020830152016100fa565b61010b6103dc565b604080516020810182526000815290516100fa9190610455565b6101917f0000000000000000000000008059fc11d8b0de9575213793d6b222ba7233a65881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fa565b6101917f000000000000000000000000b4dcf173558de885a9365a7addaaf1f6329905f281565b61010b6103f7565b6101f86101f33660046104a3565b61040d565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016100fa565b61010b7f000000000000000000000000000000000000000000000000000000000000000181565b61010b6102643660046104d6565b6103dc565b6101f861042e565b600061027b610284565b50601b0b919050565b60008060007f000000000000000000000000b4dcf173558de885a9365a7addaaf1f6329905f273ffffffffffffffffffffffffffffffffffffffff166357de26a46040518163ffffffff1660e01b81526004016040805180830381865afa1580156102f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031791906104ef565b50905060007f0000000000000000000000008059fc11d8b0de9575213793d6b222ba7233a65873ffffffffffffffffffffffffffffffffffffffff166357de26a46040518163ffffffff1660e01b81526004016040805180830381865afa158015610386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103aa91906104ef565b509050670de0b6b3a764000081601b0b83601b0b6103c8919061054e565b6103d29190610584565b9442945092505050565b6000604051631fc30cb960e01b815260040160405180910390fd5b6000610401610284565b63ffffffff1692915050565b6000806000806000604051631fc30cb960e01b815260040160405180910390fd5b60008080808061043c610284565b9596601b9190910b9563ffffffff169450849350909150565b602081526000825180602084015260005b818110156104835760208186018101516040868401015201610466565b506000604082850101526040601f19601f83011684010191505092915050565b6000602082840312156104b557600080fd5b813569ffffffffffffffffffff811681146104cf57600080fd5b9392505050565b6000602082840312156104e857600080fd5b5035919050565b6000806040838503121561050257600080fd5b825180601b0b811461051357600080fd5b602084015190925063ffffffff8116811461052d57600080fd5b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b80820260008212600160ff1b8414161561056a5761056a610538565b818105831482151761057e5761057e610538565b92915050565b6000826105a157634e487b7160e01b600052601260045260246000fd5b600160ff1b8214600019841416156105bb576105bb610538565b50059056fea2646970667358221220779003252004998ba3107e7fb072163e2e41a6d909ab0d9c90f03d27b23657ab64736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b4dcf173558de885a9365a7addaaf1f6329905f20000000000000000000000008059fc11d8b0de9575213793d6b222ba7233a658
-----Decoded View---------------
Arg [0] : proxy1_ (address): 0xb4dcF173558DE885a9365A7adDAaf1F6329905F2
Arg [1] : proxy2_ (address): 0x8059Fc11D8b0de9575213793d6b222bA7233a658
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b4dcf173558de885a9365a7addaaf1f6329905f2
Arg [1] : 0000000000000000000000008059fc11d8b0de9575213793d6b222ba7233a658
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.