PR: #35 (feat/10-chainlink-pricecache)
Commit: 5c36873
File: crates/charon-scanner/src/oracle.rs, CachedPrice struct and refresh()
Problem: CachedPrice.price stores raw latestRoundData() answer without decimal normalization. All five configured BSC feeds return 8-decimal values. CachedPrice carries .decimals field but provides no normalization method, and type-level rustdoc makes no mention of expected consumer scale.
Venus getUnderlyingPrice() returns prices scaled to 10^(36 - underlyingDecimals):
- 18-decimal tokens (WBNB, WETH): effective scale = 1e18 per USD
- 8-decimal tokens (BTCB): effective scale = 1e28 per USD
Profit calculator pairing Venus collateral value (WBNB balance in 1e18 units) with raw Chainlink BNB price (e.g., 3e11 for $300 in 8 decimals) without scaling computes USD value 10^10 times too small. Every liquidation appears unprofitable; bot skips all opportunities.
Naive scaling by 1e18 without accounting for 8-decimal feed overshoots by 1e10.
Risk: Silent mispricing — bot never executes (too small) or sizes incorrectly (too large). No runtime error, no log warning.
Fix:
impl CachedPrice {
pub fn scaled_to(&self, target_decimals: u8) -> U256 {
let diff = target_decimals.abs_diff(self.decimals);
let factor = U256::from(10u64).pow(U256::from(diff));
if target_decimals >= self.decimals {
self.price * factor
} else {
self.price / factor
}
}
}
Document in struct rustdoc that price is raw feed-native decimals. Unit test scaled_to(18) on 8-decimal answer. Update all consumers to call scaled_to() with appropriate target before arithmetic.
PR: #35 (feat/10-chainlink-pricecache)
Commit: 5c36873
File: crates/charon-scanner/src/oracle.rs,
CachedPricestruct andrefresh()Problem:
CachedPrice.pricestores rawlatestRoundData()answer without decimal normalization. All five configured BSC feeds return 8-decimal values.CachedPricecarries.decimalsfield but provides no normalization method, and type-level rustdoc makes no mention of expected consumer scale.Venus
getUnderlyingPrice()returns prices scaled to10^(36 - underlyingDecimals):Profit calculator pairing Venus collateral value (WBNB balance in 1e18 units) with raw Chainlink BNB price (e.g., 3e11 for $300 in 8 decimals) without scaling computes USD value 10^10 times too small. Every liquidation appears unprofitable; bot skips all opportunities.
Naive scaling by 1e18 without accounting for 8-decimal feed overshoots by 1e10.
Risk: Silent mispricing — bot never executes (too small) or sizes incorrectly (too large). No runtime error, no log warning.
Fix:
Document in struct rustdoc that
priceis raw feed-native decimals. Unit testscaled_to(18)on 8-decimal answer. Update all consumers to callscaled_to()with appropriate target before arithmetic.