Y2k Finance contest - teawaterwire's results

A suite of structured products for assessing pegged asset risk.

General Information

Platform: Code4rena

Start Date: 14/09/2022

Pot Size: $50,000 USDC

Total HM: 25

Participants: 110

Period: 5 days

Judge: hickuphh3

Total Solo HM: 9

Id: 162

League: ETH

Y2k Finance

Findings Distribution

Researcher Performance

Rank: 91/110

Findings: 1

Award: $36.61

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

36.6124 USDC - $36.61

Labels

bug
duplicate
3 (High Risk)
satisfactory

External Links

Lines of code

https://github.com/code-423n4/2022-09-y2k-finance/blob/2175c044af98509261e4147edeb48e1036773771/src/oracles/PegOracle.sol#L78

Vulnerability details

Impact

in PegOracle.sol latestRoundData : hardcoded multiplication by 10000 and division by 1000000 can cause a wrong price being returned if decimals of the price feed is not 8.

Proof of Concept

let's say we want to use Chainlink price feeds that use 18 decimals (which is the case for ETH quoted feeds): we replace priceFeed1.decimals() by 18 here: https://github.com/code-423n4/2022-09-y2k-finance/blob/2175c044af98509261e4147edeb48e1036773771/src/oracles/PegOracle.sol#L73

then running the test forge test --match-test testPegOracleMarketCreation --fork-url https://arb1.arbitrum.io/rpc -vv

is returning an error OraclePriceZero()

--

less likely to happen, but if the decimals amount is 15 then no errors are returned and the oracle price is wrong (running the same command) :

strike price: 995555555555555555 oracle price: 90000000000 strike price: 975555555555555555 oracle price: 90000000000 strike price: 955555555555555555 oracle price: 90000000000

Tools Used

foundry's forge

using PegOracle's own decimals to scale the numerator of the division is a robust fix, and a simplication

function latestRoundData() public view returns ( uint80 roundID, int256 nowPrice, uint256 startedAt, uint256 timeStamp, uint80 answeredInRound ) { ( uint80 roundID1, int256 price1, uint256 startedAt1, uint256 timeStamp1, uint80 answeredInRound1 ) = priceFeed1.latestRoundData(); int256 price2 = getOracle2_Price(); if (price1 > price2) { nowPrice = (price2 * int256(10**decimals)) / price1; } else { nowPrice = (price1 * int256(10**decimals)) / price2; } return (roundID1, nowPrice, startedAt1, timeStamp1, answeredInRound1); }

#1 - HickupHH3

2022-11-03T13:54:52Z

dup #195

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter