Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions contracts/InverseApi3ReaderProxyV1.sol
Original file line number Diff line number Diff line change
@@ -1,34 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

import "./interfaces/IApi3ReaderProxyWithDappId.sol";
import "@api3/contracts/interfaces/IApi3ReaderProxy.sol";
import "./interfaces/IInverseApi3ReaderProxyV1.sol";

/// @title An immutable proxy contract that inverts the value returned by an
/// IApi3ReaderProxyWithDappId data feed
/// IApi3ReaderProxy data feed
/// @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 InverseApi3ReaderProxyV1 is IInverseApi3ReaderProxyV1 {
/// @notice IApi3ReaderProxyWithDappId contract address
/// @notice IApi3ReaderProxy contract address
address public immutable override proxy;

/// @notice dApp ID of the proxy
uint256 public immutable override dappId;

/// @param proxy_ IApi3ReaderProxyWithDappId contract address
/// @param proxy_ IApi3ReaderProxy contract address
constructor(address proxy_) {
if (proxy_ == address(0)) {
revert ZeroProxyAddress();
}
proxy = proxy_;
dappId = IApi3ReaderProxyWithDappId(proxy_).dappId();
}

/// @notice Returns the inverted value of the underlying
/// IApi3ReaderProxyWithDappId
/// @notice Returns the inverted value of the underlying IApi3ReaderProxy
/// @dev Calculates `int224(1e36) / baseValue`. The operation will revert if
/// `baseValue` is zero. If `baseValue` is non-zero but its absolute value is
/// greater than `1e36`, the result of the integer division will be `0`.
Expand All @@ -40,9 +35,8 @@ contract InverseApi3ReaderProxyV1 is IInverseApi3ReaderProxyV1 {
override
returns (int224 value, uint32 timestamp)
{
(int224 baseValue, uint32 baseTimestamp) = IApi3ReaderProxyWithDappId(
proxy
).read();
(int224 baseValue, uint32 baseTimestamp) = IApi3ReaderProxy(proxy)
.read();

if (baseValue == 0) {
revert DivisionByZero();
Expand Down
7 changes: 1 addition & 6 deletions contracts/NormalizedApi3ReaderProxyV1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ contract NormalizedApi3ReaderProxyV1 is INormalizedApi3ReaderProxyV1 {
/// @notice Chainlink AggregatorV2V3Interface contract address
address public immutable override feed;

/// @notice dApp ID of the proxy
uint256 public immutable override dappId;

/// @notice Pre-calculated factor for scaling the feed's value to 18
/// decimals.
int256 public immutable scalingFactor;
Expand All @@ -27,8 +24,7 @@ contract NormalizedApi3ReaderProxyV1 is INormalizedApi3ReaderProxyV1 {
bool public immutable isUpscaling;

/// @param feed_ The address of the Chainlink AggregatorV2V3Interface feed
/// @param dappId_ dApp ID of the proxy
constructor(address feed_, uint256 dappId_) {
constructor(address feed_) {
if (feed_ == address(0)) {
revert ZeroProxyAddress();
}
Expand All @@ -40,7 +36,6 @@ contract NormalizedApi3ReaderProxyV1 is INormalizedApi3ReaderProxyV1 {
revert NoNormalizationNeeded();
}
feed = feed_;
dappId = dappId_;
uint8 delta = feedDecimals_ > 18
? feedDecimals_ - 18
: 18 - feedDecimals_;
Expand Down
19 changes: 7 additions & 12 deletions contracts/PriceCappedApi3ReaderProxyV1.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

import "./interfaces/IApi3ReaderProxyWithDappId.sol";
import "@api3/contracts/interfaces/IApi3ReaderProxy.sol";
import "./interfaces/IPriceCappedApi3ReaderProxyV1.sol";

/**
Expand All @@ -21,19 +21,16 @@ import "./interfaces/IPriceCappedApi3ReaderProxyV1.sol";
* floored at 0 if `lowerBound_` is 0.
*/
contract PriceCappedApi3ReaderProxyV1 is IPriceCappedApi3ReaderProxyV1 {
/// @notice IApi3ReaderProxyWithDappId contract address
/// @notice IApi3ReaderProxy contract address
address public immutable override proxy;

/// @notice dApp ID of the proxy
uint256 public immutable override dappId;

/// @notice The minimum price (inclusive) that this proxy will report.
int224 public immutable override lowerBound;

/// @notice The maximum price (inclusive) that this proxy will report.
int224 public immutable override upperBound;

/// @param proxy_ IApi3ReaderProxyWithDappId contract address
/// @param proxy_ IApi3ReaderProxy contract address
/// @param lowerBound_ The minimum price (inclusive) this proxy will report
/// @param upperBound_ The maximum price (inclusive) this proxy will report
constructor(address proxy_, int224 lowerBound_, int224 upperBound_) {
Expand All @@ -47,13 +44,12 @@ contract PriceCappedApi3ReaderProxyV1 is IPriceCappedApi3ReaderProxyV1 {
revert UpperBoundMustBeGreaterOrEqualToLowerBound();
}
proxy = proxy_;
dappId = IApi3ReaderProxyWithDappId(proxy_).dappId();
lowerBound = lowerBound_;
upperBound = upperBound_;
}

/// @notice Reads the current value and timestamp from the underlying
/// `IApi3ReaderProxyWithDappId` and applies the price bounds.
/// `IApi3ReaderProxy` and applies the price bounds.
/// @dev If the `baseValue` from the underlying proxy is less than
/// `lowerBound`, then `lowerBound` is returned as the `value`. If
/// `baseValue` is greater than `upperBound`, then `upperBound` is returned.
Expand All @@ -67,9 +63,8 @@ contract PriceCappedApi3ReaderProxyV1 is IPriceCappedApi3ReaderProxyV1 {
override
returns (int224 value, uint32 timestamp)
{
(int224 baseValue, uint32 baseTimestamp) = IApi3ReaderProxyWithDappId(
proxy
).read();
(int224 baseValue, uint32 baseTimestamp) = IApi3ReaderProxy(proxy)
.read();

timestamp = baseTimestamp;

Expand All @@ -87,7 +82,7 @@ contract PriceCappedApi3ReaderProxyV1 is IPriceCappedApi3ReaderProxyV1 {
/// @return True if the base value is less than `lowerBound` or greater
/// than `upperBound`, false otherwise.
function isCapped() external view returns (bool) {
(int224 baseValue, ) = IApi3ReaderProxyWithDappId(proxy).read();
(int224 baseValue, ) = IApi3ReaderProxy(proxy).read();
return baseValue < lowerBound || baseValue > upperBound;
}

Expand Down
28 changes: 9 additions & 19 deletions contracts/ProductApi3ReaderProxyV1.sol
Original file line number Diff line number Diff line change
@@ -1,48 +1,38 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

import "./interfaces/IApi3ReaderProxyWithDappId.sol";
import "@api3/contracts/interfaces/IApi3ReaderProxy.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
/// IApi3ReaderProxy 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
/// @notice First IApi3ReaderProxy contract address
address public immutable override proxy1;

/// @notice Second IApi3ReaderProxyWithDappId contract address
/// @notice Second IApi3ReaderProxy 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
/// @param proxy1_ First IApi3ReaderProxy contract address
/// @param proxy2_ Second IApi3ReaderProxy 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
/// between two IApi3ReaderProxy 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
Expand All @@ -59,8 +49,8 @@ contract ProductApi3ReaderProxyV1 is IProductApi3ReaderProxyV1 {
override
returns (int224 value, uint32 timestamp)
{
(int224 value1, ) = IApi3ReaderProxyWithDappId(proxy1).read();
(int224 value2, ) = IApi3ReaderProxyWithDappId(proxy2).read();
(int224 value1, ) = IApi3ReaderProxy(proxy1).read();
(int224 value2, ) = IApi3ReaderProxy(proxy2).read();

value = int224((int256(value1) * int256(value2)) / 1e18);
timestamp = uint32(block.timestamp);
Expand Down
29 changes: 11 additions & 18 deletions contracts/adapters/ScaledApi3FeedProxyV1.sol
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

import "../interfaces/IApi3ReaderProxyWithDappId.sol";
import "@api3/contracts/interfaces/IApi3ReaderProxy.sol";
import "./interfaces/IScaledApi3FeedProxyV1.sol";

/// @title An immutable Chainlink AggregatorV2V3Interface feed contract that
/// scales the value of an IApi3ReaderProxyWithDappId data feed to a target
/// number of decimals
/// scales the value of an IApi3ReaderProxy data feed to a target number of
/// decimals
/// @dev This contract reads an `int224` value (assumed to be 18 decimals)
/// from the underlying `IApi3ReaderProxyWithDappId` and scales it to
///`targetDecimals`.
/// from the underlying `IApi3ReaderProxy` and scales it to `targetDecimals`.
/// The scaling arithmetic uses `int256` for intermediate results, allowing the
/// scaled value to exceed `int224` limits if upscaling significantly; it will
/// revert on `int256` overflow.
/// When downscaling, integer division (`proxyValue / scalingFactor`) is used,
/// which truncates and may lead to precision loss. Integrators must carefully
/// consider this potential precision loss for their specific use case.
contract ScaledApi3FeedProxyV1 is IScaledApi3FeedProxyV1 {

Check warning on line 18 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Missing @notice tag in contract 'ScaledApi3FeedProxyV1'

Check warning on line 18 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Missing @author tag in contract 'ScaledApi3FeedProxyV1'
/// @notice IApi3ReaderProxyWithDappId contract address
/// @notice IApi3ReaderProxy contract address
address public immutable override proxy;

/// @notice dApp ID of the proxy
uint256 public immutable override dappId;

/// @notice Pre-calculated factor for scaling the proxy's 18-decimal value
/// to `targetDecimals`.
int256 public immutable override scalingFactor;
Expand All @@ -34,10 +30,9 @@
/// @dev Target decimals for the scaled value.
uint8 private immutable targetDecimals;

/// @param proxy_ IApi3ReaderProxyWithDappId contract address
/// @param targetDecimals_ Decimals to scale the IApi3ReaderProxyWithDappId
/// value
/// @param proxy_ IApi3ReaderProxy contract address
/// @param targetDecimals_ Decimals to scale the IApi3ReaderProxy value
constructor(address proxy_, uint8 targetDecimals_) {

Check warning on line 35 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Missing @notice tag in function '<anonymous>'
if (proxy_ == address(0)) {
revert ZeroProxyAddress();
}
Expand All @@ -48,7 +43,6 @@
revert NoScalingNeeded();
}
proxy = proxy_;
dappId = IApi3ReaderProxyWithDappId(proxy_).dappId();
targetDecimals = targetDecimals_;
uint8 delta = targetDecimals_ > 18
? targetDecimals_ - 18
Expand All @@ -60,7 +54,7 @@
/// @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) {

Check warning on line 57 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Mismatch in @return names for function 'latestAnswer'. Expected: [value], Found: []

Check warning on line 57 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Missing @return tag in function 'latestAnswer'

Check warning on line 57 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Missing @notice tag in function 'latestAnswer'
(value, ) = _read();
}

Expand All @@ -70,7 +64,7 @@
/// 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()

Check warning on line 67 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Mismatch in @return names for function 'latestTimestamp'. Expected: [timestamp], Found: []

Check warning on line 67 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Missing @return tag in function 'latestTimestamp'

Check warning on line 67 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Missing @notice tag in function 'latestTimestamp'
external
view
override
Expand All @@ -80,7 +74,7 @@
}

/// @dev Api3 feeds are updated asynchronously and not in rounds
function latestRound() external pure override returns (uint256) {

Check warning on line 77 in contracts/adapters/ScaledApi3FeedProxyV1.sol

View workflow job for this annotation

GitHub Actions / lint-build-test

Missing @notice tag in function 'latestRound'
revert FunctionIsNotSupported();
}

Expand All @@ -94,7 +88,7 @@
revert FunctionIsNotSupported();
}

/// @dev Decimals used to scale the IApi3ReaderProxyWithDappId value
/// @dev Decimals used to scale the IApi3ReaderProxy value
function decimals() external view override returns (uint8) {
return targetDecimals;
}
Expand Down Expand Up @@ -143,7 +137,7 @@
updatedAt = startedAt;
}

/// @notice Reads a value from the underlying `IApi3ReaderProxyWithDappId`
/// @notice Reads a value from the underlying `IApi3ReaderProxy`
/// and scales it to `targetDecimals`.
/// @dev Reads from the underlying proxy and applies scaling to
/// `targetDecimals`. Upscaling uses multiplication; downscaling uses integer
Expand All @@ -152,9 +146,8 @@
/// @return value The scaled signed fixed-point value with `targetDecimals`.
/// @return timestamp The timestamp from the underlying proxy.
function _read() internal view returns (int256 value, uint32 timestamp) {
(int224 proxyValue, uint32 proxyTimestamp) = IApi3ReaderProxyWithDappId(
proxy
).read();
(int224 proxyValue, uint32 proxyTimestamp) = IApi3ReaderProxy(proxy)
.read();

value = isUpscaling
? proxyValue * scalingFactor
Expand Down
2 changes: 0 additions & 2 deletions contracts/adapters/interfaces/IScaledApi3FeedProxyV1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@ interface IScaledApi3FeedProxyV1 is AggregatorV2V3Interface {
function scalingFactor() external view returns (int256);

function isUpscaling() external view returns (bool);

function dappId() external view returns (uint256);
}
8 changes: 0 additions & 8 deletions contracts/interfaces/IApi3ReaderProxyWithDappId.sol

This file was deleted.

4 changes: 2 additions & 2 deletions contracts/interfaces/IInverseApi3ReaderProxyV1.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@api3/contracts/interfaces/IApi3ReaderProxy.sol";
import "../vendor/@chainlink/contracts@1.2.0/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol";
import "./IApi3ReaderProxyWithDappId.sol";

interface IInverseApi3ReaderProxyV1 is
IApi3ReaderProxyWithDappId,
IApi3ReaderProxy,
AggregatorV2V3Interface
{
error ZeroProxyAddress();
Expand Down
4 changes: 2 additions & 2 deletions contracts/interfaces/INormalizedApi3ReaderProxyV1.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@api3/contracts/interfaces/IApi3ReaderProxy.sol";
import "../vendor/@chainlink/contracts@1.2.0/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol";
import "./IApi3ReaderProxyWithDappId.sol";

interface INormalizedApi3ReaderProxyV1 is
IApi3ReaderProxyWithDappId,
IApi3ReaderProxy,
AggregatorV2V3Interface
{
error ZeroProxyAddress();
Expand Down
4 changes: 2 additions & 2 deletions contracts/interfaces/IPriceCappedApi3ReaderProxyV1.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@api3/contracts/interfaces/IApi3ReaderProxy.sol";
import "../vendor/@chainlink/contracts@1.2.0/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol";
import "./IApi3ReaderProxyWithDappId.sol";

interface IPriceCappedApi3ReaderProxyV1 is
IApi3ReaderProxyWithDappId,
IApi3ReaderProxy,
AggregatorV2V3Interface
{
error ZeroProxyAddress();
Expand Down
6 changes: 2 additions & 4 deletions contracts/interfaces/IProductApi3ReaderProxyV1.sol
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@api3/contracts/interfaces/IApi3ReaderProxy.sol";
import "../vendor/@chainlink/contracts@1.2.0/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol";
import "./IApi3ReaderProxyWithDappId.sol";

interface IProductApi3ReaderProxyV1 is
IApi3ReaderProxyWithDappId,
IApi3ReaderProxy,
AggregatorV2V3Interface
{
error ZeroProxyAddress();

error SameProxyAddress();

error DappIdMismatch();

error ZeroDenominator();

error FunctionIsNotSupported();
Expand Down
Loading