Salty.IO - VAD37's results

An Ethereum-based DEX with zero swap fees, yield-generating Automatic Arbitrage, and a native WBTC/WETH backed stablecoin.

General Information

Platform: Code4rena

Start Date: 16/01/2024

Pot Size: $80,000 USDC

Total HM: 37

Participants: 178

Period: 14 days

Judge: Picodes

Total Solo HM: 4

Id: 320

League: ETH

Salty.IO

Findings Distribution

Researcher Performance

Rank: 39/178

Findings: 1

Award: $372.80

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Findings Information

🌟 Selected for report: israeladelaja

Also found by: PENGUN, VAD37, jasonxiale

Labels

bug
2 (Med Risk)
disagree with severity
downgraded by judge
satisfactory
sponsor confirmed
edited-by-warden
duplicate-486

Awards

372.7994 USDC - $372.80

External Links

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/price_feed/CoreChainlinkFeed.sol#L44-L49 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/stable/CollateralAndLiquidity.sol#L221-L236

Vulnerability details

Chainlink offchain oracle refresh price exactly every 60 minutes. And CoreChainlinkFeed ignore chainlink feed if its price stale more than 60 minutes.

Looking at etherscan transactions, It is very easy to find chainlink feed price submission is delayed by a few blocks. Causing price updating longer than 60 minutes by 10-20 seconds a few times per day.

So each day on some specific blocks, chainlink price is ignored. The protocol expect chainlink and uniswap oracle to be available at all time.

The oracle price always average 2 out of 3 different and closest oracle price. Which most of the time are chainlink and uniswap TWAP. With chainlink out of the picture, the fallback safety are CoreSaltyFeed oracle and 7% price different between oracle protection.

CoreSaltyFeed work similar to uniswapV2 reserve price. It can be manipulated if have enough token to swap.

This open up a single block window to manipulate oracle price by maximum 3.5%. When chainlink submit price late by 1 block, the oracle manipulated to return wrong price. Then next block with chainlink back online, oracle now return correct price. Enable arbitrage oracle profit.

Impact

Oracle price feed is used for stable coin USDS collateral. Attacker can borrow more USDS with manipulated oracle in one block then sell it back in next block for possible 3.5% profit.

Proof of Concept

Here is a sample contract of a chainlink aggregator update price to oracle feed. https://etherscan.io/address/0xE62B71cf983019BFf55bC83B48601ce8419650CC

It update price every 60 minutes exactly, when there is no big price movement, otherwise it update price immediately for every 0.5% price change. Most of the time, the timestamp aggregate between 2 rounds is exactly 60 minutes. And then there is a few times, the timestamp different is more than 60 minutes.

Look at timestamp of these 2 transactions from above contract: https://etherscan.io/tx/0xc39df382dc6d8b137f92f15f8a10d777c9eed960ce885bc5333d936d6e39da86 https://etherscan.io/tx/0xbdf4ac46502a12f18a75aa279e469a1d159e792b909b823203e2df28bae3d9ed

Both transmit to refresh price to oracle, it show the block.timestamp different is more than 60 minutes. 03:55:47 AM +UTC vs 02:55:35 AM +UTC. And this is normal for price refresh, chainlink refresh price on-chain every hour.

So by frontrun chainlink oracle price submission on slow block every hour, CoreChainlinkFeed will return 0 price because answerDelay > 60 minutes.

PriceAggregator will relied average price of CoreUniswapFeed and CoreSaltyFeed price feed.

For CoreSaltyFeed, price can be manipulated. Its mechanism work similar to uniswapV2 price reserve. Details is omitted here. Just by having enough token to swap, price can drop in favor of attacker.

If CoreSaltyFeed drop by 7% in comparision with uniswap TWAP, PriceAggregator still accept feed as reasonable. So now we have WBTC/USDS price drop 3.5% in single block transaction. This allow user more borrow power. Borrow with unfair price. https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/stable/CollateralAndLiquidity.sol#L99 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/stable/CollateralAndLiquidity.sol#L275 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/stable/CollateralAndLiquidity.sol#L221-L236

Hopefully next block, chainlink will submit new price and chainlink timestamp it reset. With CoreChainlinkFeed back online. PriceAggregator will use Chainlink and uniswap TWAP as the best price.

Attacker now just have to repay and profit from oracle manipulation.

Tools Used

Manual

https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/price_feed/CoreChainlinkFeed.sol#L44-L49

max answer delay should be 61-70 minutes instead of 60 minutes.

Assessed type

Oracle

#0 - c4-judge

2024-02-02T16:16:59Z

Picodes marked the issue as primary issue

#1 - c4-sponsor

2024-02-08T11:50:43Z

othernet-global marked the issue as disagree with severity

#2 - c4-sponsor

2024-02-08T11:50:48Z

othernet-global (sponsor) confirmed

#3 - othernet-global

2024-02-17T22:54:15Z

#4 - c4-judge

2024-02-19T11:43:41Z

Picodes changed the severity to 2 (Med Risk)

#5 - c4-judge

2024-02-19T11:44:00Z

Picodes marked issue #486 as primary and marked this issue as a duplicate of 486

#6 - c4-judge

2024-02-21T16:55:50Z

Picodes marked the issue as satisfactory

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