Skip to content

Commit e70c71f

Browse files
committed
DFP-4: Precision Loss on Value Downscaling
1 parent 2ff87d9 commit e70c71f

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

contracts/adapters/ScaledApi3FeedProxyV1.sol

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ import "./interfaces/IScaledApi3FeedProxyV1.sol";
77
/// @title An immutable Chainlink AggregatorV2V3Interface feed contract that
88
/// scales the value of an IApi3ReaderProxy data feed to a target number of
99
/// decimals
10-
/// @dev This contract assumes the source proxy always returns values with
11-
/// 18 decimals (as all IApi3ReaderProxy-compatible proxies do)
10+
/// @dev This contract reads an `int224` value (assumed to be 18 decimals)
11+
/// from the underlying `IApi3ReaderProxy` and scales it to `targetDecimals`.
12+
/// The scaling arithmetic uses `int256` for intermediate results, allowing the
13+
/// scaled value to exceed `int224` limits if upscaling significantly; it will
14+
/// revert on `int256` overflow.
15+
/// When downscaling, integer division (`proxyValue / scalingFactor`) is used,
16+
/// which truncates and may lead to precision loss. Integrators must carefully
17+
/// consider this potential precision loss for their specific use case.
1218
contract ScaledApi3FeedProxyV1 is IScaledApi3FeedProxyV1 {
1319
/// @notice IApi3ReaderProxy contract address
1420
address public immutable override proxy;
@@ -133,15 +139,10 @@ contract ScaledApi3FeedProxyV1 is IScaledApi3FeedProxyV1 {
133139

134140
/// @notice Reads a value from the underlying `IApi3ReaderProxy` and
135141
/// scales it to `targetDecimals`.
136-
/// @dev Reads an `int224` value (assumed to be 18 decimals) from the
137-
/// underlying `IApi3ReaderProxy`. This value is then scaled to
138-
/// `targetDecimals` using pre-calculated factors. The scaling arithmetic
139-
/// (e.g., `proxyValue * scalingFactor`) involves an `int224` (`proxyValue`)
140-
/// and an `int256` (`scalingFactor`). `proxyValue` is implicitly promoted
141-
/// to `int256` for this operation, resulting in an `int256` value.
142-
/// This allows the scaled result to exceed the `int224` range, provided
143-
/// it fits within `int256`. Arithmetic operations will revert on `int256`
144-
/// overflow. The function returns the scaled value as an `int256`.
142+
/// @dev Reads from the underlying proxy and applies scaling to
143+
/// `targetDecimals`. Upscaling uses multiplication; downscaling uses integer
144+
/// division (which truncates). All scaling arithmetic is performed using
145+
/// `int256`.
145146
/// @return value The scaled signed fixed-point value with `targetDecimals`.
146147
/// @return timestamp The timestamp from the underlying proxy.
147148
function _read() internal view returns (int256 value, uint32 timestamp) {

0 commit comments

Comments
 (0)