Correct Chainlink decimal scaling in secure lending example

This commit is contained in:
Rudy Celekli
2026-09-29 20:08:39 -04:00
parent 765be42358
commit 82425f3fe3
@@ -150,6 +150,12 @@ contract SecureLending {
AggregatorV3Interface immutable priceFeed;
uint256 constant MAX_ORACLE_STALENESS = 1 hours;
constructor(address feed) {
priceFeed = AggregatorV3Interface(feed);
}
// amount uses the collateral token's base units. With a USD/token feed,
// the result is USD scaled by the collateral token's decimal count.
function getCollateralValue(uint256 amount) public view returns (uint256) {
(
uint80 roundId,
@@ -164,11 +170,24 @@ contract SecureLending {
require(updatedAt > block.timestamp - MAX_ORACLE_STALENESS, "Stale price");
require(answeredInRound >= roundId, "Incomplete round");
return (amount * uint256(price)) / priceFeed.decimals();
uint8 feedDecimals = priceFeed.decimals();
require(feedDecimals <= 77, "Unsupported feed decimals");
// decimals() is the number of decimal places, not the scale factor.
return (amount * uint256(price)) / (10 ** uint256(feedDecimals));
}
}
```
Before comparing collateral value with debt, normalize both to the same unit.
For one 18-decimal token (`amount = 1e18`) priced at $2,000 by an 8-decimal
feed (`price = 2000e8`), this function returns `2000e18`, not `25000000000e18`.
A 6-decimal token produces `2000e6`; converting that to a debt asset's base
units is a separate step. Test both scales and a zero-decimal feed, which must
not divide by zero. Solidity's checked multiplication still reverts on extreme
products; production code should use a reviewed full-precision `mulDiv` if its
supported input range can overflow. Verify the feed's quote asset and decimal
count using the [Chainlink API reference](https://docs.chain.link/data-feeds/api-reference).
### Access Control Audit Checklist
```markdown
# Access Control Audit Checklist