22pragma solidity ^ 0.8.27 ;
33
44import "@api3/contracts/interfaces/IApi3ReaderProxy.sol " ;
5- import "../ProxyUtils.sol " ;
65import "./interfaces/IScaledApi3FeedProxyV1.sol " ;
76
87/// @title An immutable Chainlink AggregatorV2V3Interface feed contract that
@@ -11,8 +10,6 @@ import "./interfaces/IScaledApi3FeedProxyV1.sol";
1110/// @dev This contract assumes the source proxy always returns values with
1211/// 18 decimals (as all IApi3ReaderProxy-compatible proxies do)
1312contract ScaledApi3FeedProxyV1 is IScaledApi3FeedProxyV1 {
14- using ProxyUtils for int256 ;
15-
1613 /// @notice IApi3ReaderProxy contract address
1714 address public immutable override proxy;
1815
@@ -118,19 +115,31 @@ contract ScaledApi3FeedProxyV1 is IScaledApi3FeedProxyV1 {
118115 updatedAt = startedAt;
119116 }
120117
121- /// @notice Reads from the IApi3ReaderProxy value and scales it to target
122- /// decimals
123- /// @dev Casting the scaled value to int224 might cause an overflow but this
124- /// is preferable to checking the value for overflows in every read due to
125- /// gas overhead
126- function _read ()
127- internal
128- view
129- returns (int256 scaledValue , uint32 timestamp )
130- {
131- (int256 value , uint32 proxyTimestamp ) = IApi3ReaderProxy (proxy).read ();
132-
133- scaledValue = int224 (value.scaleValue (18 , targetDecimals));
118+ /// @notice Reads a value from the underlying `IApi3ReaderProxy` and
119+ /// scales it to `targetDecimals`.
120+ /// @dev Reads an `int224` value (assumed to be 18 decimals) from the
121+ /// underlying `IApi3ReaderProxy` and scales it to `targetDecimals`.
122+ /// The initial `int224` proxy value is widened to `int256` before scaling.
123+ /// The scaling arithmetic (`value * factor` or `value / factor`) is then
124+ /// performed using `int256` types. This allows the scaled result to exceed
125+ /// the `int224` range, provided it fits within `int256`.
126+ /// Arithmetic operations will revert on overflow or underflow
127+ /// (e.g., if `value * factor` exceeds `type(int256).max`).
128+ /// @return value The scaled signed fixed-point value with `targetDecimals`.
129+ /// @return timestamp The timestamp from the underlying proxy.
130+ function _read () internal view returns (int256 value , uint32 timestamp ) {
131+ (int224 proxyValue , uint32 proxyTimestamp ) = IApi3ReaderProxy (proxy)
132+ .read ();
133+
134+ value = proxyValue;
134135 timestamp = proxyTimestamp;
136+
137+ if (18 != targetDecimals) {
138+ uint8 delta = 18 > targetDecimals
139+ ? 18 - targetDecimals
140+ : targetDecimals - 18 ;
141+ int256 factor = int256 (10 ** uint256 (delta));
142+ value = 18 < targetDecimals ? value * factor : value / factor;
143+ }
135144 }
136145}
0 commit comments