Skip to content

Commit 94ae5e9

Browse files
committed
DFP-1: Silent Truncation on int224 Cast without Bounds Checks
1 parent 3503ca8 commit 94ae5e9

File tree

3 files changed

+12
-17
lines changed

3 files changed

+12
-17
lines changed

contracts/InverseApi3ReaderProxyV1.sol

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ contract InverseApi3ReaderProxyV1 is IInverseApi3ReaderProxyV1 {
2424
}
2525

2626
/// @notice Returns the inverted value of the underlying IApi3ReaderProxy
27-
/// @dev This inverts the 18-decimal fixed-point value using 1e36 / value.
28-
/// The operation will revert if `baseValue` is zero (division by zero) or if
29-
/// `baseValue` is so small (yet non-zero) that the resulting inverted value
30-
/// would overflow the `int224` type.
27+
/// @dev The operation will revert if `baseValue` is zero (division by zero).
3128
/// @return value Inverted value of the underlying proxy
3229
/// @return timestamp Timestamp of the underlying proxy
3330
function read()
@@ -39,7 +36,7 @@ contract InverseApi3ReaderProxyV1 is IInverseApi3ReaderProxyV1 {
3936
(int224 baseValue, uint32 baseTimestamp) = IApi3ReaderProxy(proxy)
4037
.read();
4138

42-
value = int224((1e36) / int256(baseValue));
39+
value = int224(1e36) / baseValue;
4340
timestamp = baseTimestamp;
4441
}
4542

contracts/NormalizedApi3ReaderProxyV1.sol

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,9 @@ contract NormalizedApi3ReaderProxyV1 is INormalizedApi3ReaderProxyV1 {
4545

4646
/// @notice Returns the price of the underlying Chainlink feed normalized to
4747
/// 18 decimals.
48-
/// @dev Fetches an `int256` answer from the Chainlink feed and scales it
49-
/// to 18 decimals using pre-calculated factors. The result is cast to
50-
/// `int224` to conform to the `IApi3ReaderProxy` interface.
51-
/// IMPORTANT: If the normalized `int256` value is outside the `int224`
52-
/// range, this cast causes silent truncation and data loss. Deployers
53-
/// must verify that the source feed's characteristics (value magnitude
54-
/// and original decimals) ensure the 18-decimal normalized value fits
55-
/// `int224`. Scaling arithmetic (prior to cast) reverts on `int256`
56-
/// overflow.
48+
/// @dev Fetches and scales the Chainlink feed's `int256` answer.
49+
/// The scaled `int256` result is then cast to `int224`. This cast is
50+
/// unchecked for gas optimization and may silently truncate.
5751
/// @return value The normalized signed fixed-point value with 18 decimals
5852
/// @return timestamp The updatedAt timestamp of the feed
5953
function read()

contracts/ProductApi3ReaderProxyV1.sol

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,13 @@ contract ProductApi3ReaderProxyV1 is IProductApi3ReaderProxyV1 {
3333

3434
/// @notice Returns the current value and timestamp of the rate composition
3535
/// between two IApi3ReaderProxy proxies by multiplying their values
36-
/// @dev There is a risk of multiplication overflowing if the result exceeds
37-
/// `int256` bounds. The returned timestamp is `block.timestamp`, marking
38-
/// when this newly derived product value was computed on-chain.
36+
/// @dev Calculates product as `(int256(value1) * int256(value2)) / 1e18`.
37+
/// The initial multiplication `int256(value1) * int256(value2)` will revert
38+
/// on `int256` overflow. The final `int256` result of the full expression
39+
/// is then cast to `int224`. This cast is unchecked for gas optimization
40+
/// and may silently truncate if the result exceeds `int224` limits.
41+
/// The returned timestamp is `block.timestamp`, marking when this newly
42+
/// derived product value was computed on-chain.
3943
/// Timestamps from underlying `IApi3ReaderProxy` feeds are not aggregated.
4044
/// Their diverse nature (see `IApi3ReaderProxy` interface for details like
4145
/// off-chain origins or varying update cadences) makes aggregation complex

0 commit comments

Comments
 (0)