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
Rank: 33/178
Findings: 1
Award: $425.50
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: peanuts
Also found by: 0xAsen, 0xHelium, 0xSmartContract, 0xepley, DedOhWale, K42, LinKenji, Sathish9098, ZanyBonzy, catellatech, fouzantanveer, foxb868, hassanshakeel13, hunter_w3b, jauvany, kaveyjoe, kinda_very_good, klau5, niroh, rspadi, yongskiws
425.4976 USDC - $425.50
Salty.IO is building a decentralized exchange that aims to offer zero fee swaps, yield generation from automatic arbitrage, and a native stablecoin called USDS collateralized by WBTC/WETH.
The system is governed by a DAO where SALT token holders vote on parameters and upgrades. No special admin access exists. Pools.sol implements the AMM DEX logic with arbitrage done atomically at swap time to yield profits. USDS.sol manages stablecoin collateral ratios, liquidations, and redemptions.
Incentives focus on distributing arbitrage yields to liquidity providers and SALT stakers to drive adoption. The goal is ultimately a self-sustaining platform lacking centralized points of failure.
Key Risks
Liquidity Bootstrapping: As an AMM, Salty.IO requires external liquidity to function efficiently. Without incentives attracting liquidity in a circular way, high swap costs could prevent profitability.
Technical: The smart contract system is complex. Subtle logical errors or bugs could disrupt core functionality around swaps, yields, or the USDS peg. Rigorous testing is critical.
Price Manipulation: Asset valuations originate from external Chainlink and Uniswap price oracles. Market volatility could be amplified by manipulated oracles.
Governance: The DAO introduces risks around proposal attacks, improper parameter changes, and funds mismanagement. Timelocks and process controls are important.
Summary
Salty.IO brings innovative architecture but has complexity risks. Prioritizing liquidity incentives and strong technical audit practices will help mitigate issues in core areas like AMM swaps, price oracles, and governance.
The core price feed contracts are PriceAggregator.sol
and its associated IPriceFeed
implementations (CoreUniswapFeed
, CoreChainlinkFeed
etc.) The main vulnerabilities stem from:
Centralized Price Feeds
If an attacker compromises the private keys of the admin or DAO governing the price feed contracts, they could switch the underlying oracles to a malicious one. For example:
function setPriceFeed(uint id, IPriceFeed feed) onlyOwner external { // Set manipulated feed }
This would allow manipulating BTC and ETH prices.
Oracle Manipulation
Even without keys, manipulating the existing Uniswap TWAP or Chainlink feeds via flash loans could provide false arbitrage and liquidation opportunities. For example spamming the DEX pools prior to snapshot timestamps.
Asset Correlation
The Uniswap and Chainlink oracles rely on proper USD valuation of their quote assets like WBTC, WETH etc. If stable or synthetic assets like USDT/USDC are manipulated, so would be the BTC/ETH prices.
Mitigations
The key arbitrage calculations occur in ArbitrageSearch.sol
which is called from Pools.sol
on every swap event.
When a user swap between two tokens occurs, _attemptArbitrage()
is triggered:
function swap( IERC20 tokenIn, IERC20 tokenOut, uint amountIn ) external { // Place user swap uint arbitrageProfit = _attemptArbitrage( tokenIn, tokenOut, amountIn ); } function _attemptArbitrage( IERC20 tokenIn, IERC20 tokenOut, uint amountIn ) internal returns (uint profit) { // Calculate and perform arbitrage }
The issue lies in the sequential order - the user swap occurs first, then arbitrage is checked.
This means miners or mempool frontrunners aware of pending swaps could take the following actions:
Even if the user swap reverts, the frontrunner keeps any profits.
Mitigations involve:
The key liquidation entry point is the liquidateUser()
function. An attacker could potentially manipulate state before calling this in several ways:
Frontrunning Legitimate Liquidations
If an attacker sees a pending TX to liquidate an undercollateralized position, they could attempt to frontrun it and liquidate first. This would steal some profits and prevent the proper liquidation.
Manipulating Oracle Prices
If an attacker temporarily pushes collateral asset prices much lower, solvent positions would falsely appear undercollateralized. This could enable unwarranted liquidations.
Boosting Rewards Before Liquidating
An attacker could temporarily inflate a user's collateral and rewards share, then rapidly borrow USDS to make them eligible for liquidation. This could allow stealing their pending rewards and share.
Other Transaction Order Front-Running
General frontrunning of transactions around liquidations could allow attackers to profit from side effects.
However, CollateralAndLiquidity
contains some key mitigating checks:
canUserBeLiquidated()
prevents unwarranted liquidationnonReentrant
modifier prevents reentrancy issuesProper monitoring for transaction reordering and validating price feed sanity is prudent. But the core logic appears sound.
The main external code dependencies are:
OpenZeppelin libraries - Used extensively for common DeFi constructs like SafeMath, ReentrancyGuard etc. As an established audited library this poses minimal risk.
Chainlink Price Feeds - Used as one of the potential price oracle sources. As decentralized infrastructure, reasonable reliance. But availability issues would cause problems.
Uniswap V3 TWAP - Also used as a potential price feed source. As on-chain DEX fairly manipulate resistant but potential for liquidity issues.
Operationally, main external risks include:
Public Ethereum infrastructure - Outages to core blockchain networks/tooling could break system utility
Frontend hosting - Attacks disrupting the Salty.IO site/interface would limit usability
Maker governance actions - As DAI is a key aspect, risks to its peg stability from Maker proposals is a factor
Reasonably limited external code dependencies help security. But production infrastructure issues still pose risks. Likely best mitigated at the operations level through redundancy.
Diagram showing the core flow of assets between the main Salty.IO protocol contracts:
SALT Tokens โ Emissions โ โโโโโโโโโโดโโโโโโโโโ โ โ Staking Liquidity โ โ โ โ xSALT Holders Liquidity Providers โ โ StakingRewards CollateralAndLiquidity โ โ โโโโโโโดโโโโโโโ โ โ WBTC/WETH USDS โ โ โ โ โ Borrow & โ Repay USDS โ โ Pools โคโฌโฌโฌโฌโฌโฌโฌยคโฌโฌโฌโฌโฌ โโโโโโโโ โโโโโ Price Feeds Swaps โ Arbitrage โ โโโโโโโโโโดโโโโโ DAO โ โ Upkeep โ โ Protocol Rewards Owned Liquidity โ โ Callers
50 hours
#0 - c4-judge
2024-02-03T14:52:39Z
Picodes marked the issue as grade-c
#1 - c4-judge
2024-02-03T14:52:43Z
Picodes marked the issue as grade-b
#2 - c4-judge
2024-02-03T14:52:51Z
Picodes marked the issue as grade-a
#3 - Picodes
2024-02-03T14:53:07Z
Giving grade-a for the invalidated findings that could have been a good fit for the analysis