Salty.IO Mitigation Review
Salty.IO is an Ethereum-based DEX with zero swap fees, yield-generating Automatic Arbitrage, a native WBTC/WETH backed stablecoin, and is fully DAO owned and decentralized at launch.
- Start date1 Mar 2024
- End date11 Mar 2024
- Total awards$30,000 in USDC
- Duration10 days
- Details
Salty.IO - Mitigation Review details
- Total Prize Pool: $30,000 in USDC
- Warden guidelines for C4 mitigation reviews
- Submit findings using the C4 form
- Starts March 1, 20:00 UTC
- Ends March 11, 20:00 UTC
Important note
Each warden must submit a mitigation review for every High and Medium finding from the parent audit that is listed as in-scope for the mitigation review along with the Additional Scope to be Reviewed section. Incomplete mitigation reviews will not be eligible for awards.
Findings being mitigated
Mitigations of all High and Medium issues will be considered in-scope and listed here.
-
H-02: First Liquidity provider can claim all initial pool rewards
-
M-02: Persistent Contract Call revert prevents finalizing a ballot
-
M-04: If there is only one USDS borrower, he can never be liquidated
-
M-07: Impossible to change managed wallets with proposeWallets after first rejection
-
M-09: Remove Liquidity has missing reserve1 DUST check, which can make reserve1 to be less than DUST
-
M-11: SALT staker can get extra voting power by simply unstaking their xSALT
-
M-12: DOS of proposals by abusing ballot names without important parameters
-
M-19: No proposal time limit traps sponsors of unpopular proposals
-
M-20: Some rewards from POL will not be send to team wallet nor burned
-
M-21: When forming POL the DAO will end up stucked with DAI and USDS tokens that cannot handle.
-
M-24: Salt Rewards - Rewards related to Arbitrage profits for pools can be lost
-
M-25: Incorrect assumption in PoolMath.sol can cause underflow when zapping is used
-
M-27: Attacker Can Inflate LP Position Value To Create a Bad Debt Loan
-
M-28: MinShares Slippage Parameters Are Ineffective For Initial Deposit
-
M-29: Incorrect calculation to check remaining ratio after reward in StableConfig.sol
Overview of changes
To decrease the risk profile of the exchange and focus on the core features provided by automatic arbitrage, the USDS stablecoin and all associated functionality (price feeds, collateral, liquidizer, etc) have been completely removed. The stablecoin was largely isolated from the rest of the project, but this did refactor the way Upkeep works.
Resulting from the stablecoin being removed all tokens are now paired with WETH and USDC rather than WETH and WBTC (which was previously done to provide increased yield for now removed collateral).
Also, the ManagedWallet contract has been removed - with the teamVestingWallet now targeting a simple teamWallet address.
To prevent any swaps from occurring during performUpkeep, Protocol Owned Liquidity has been removed. Additionally, on user swap any WETH profits that are generated are swapped immediately to SALT - rather than being done in performUpkeep.
In response to a suggestion by one of the wardens in the original competition, the ArbitrageSearch mechanism has been refactored and optimized extensively:
https://github.com/code-423n4/2024-01-salty-findings/issues/419
Users are now limited to one swap per block due to an issue found in which arbitrage could be bypassed by dividing up individual swaps into tens or hundreds of swaps. Without the limitation and due to the protocol's reletively low gas costs for swap and arbitrage, attackers would otherwise be able to perform multiple swaps in one transaction - effectively bypassing arbitrage and the rebalancing done that discourages manipulation. While multiple wallets could still be used on such an attack, the gas costs incurred on the multiple separate swap transactions are considered a sufficient deterrent.
Mitigations to be reviewed
URL | Mitigation of | Purpose |
---|---|---|
https://github.com/othernet-global/salty-io/commit/5766592880737a5e682bb694a3a79e12926d48a5 | H-01 | ManagedWallet has been removed. VestingWallet now just vests directly to teamWallet. |
https://github.com/othernet-global/salty-io/commit/4f0c9c6a6e3e4234135ab7119a0e380af3e9776c | H-02 | performUpkeep is now called at the start of BootstrapBallot.finalizeBallot to reset the emissions timers just before liquidity rewards claiming is started. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | H-03 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/5f79dc4f0db978202ab7da464b09bf08374ec618 | H-04 | virtualRewards and userShare are now uint256 rather than uint128. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | H-05 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | H-06 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/b3b8cb955db2b9f0e47a4964e1e4f833a447a72d | M-01 | virtualRewards now rounded up on _decreaseUserShare |
https://github.com/othernet-global/salty-io/commit/5f1a5206a04b0f3fe45ad88a311370ce12fb0135 | M-02 | callFromDAO now wrapped in a try/catch |
https://github.com/othernet-global/salty-io/commit/ccf4368fcf1777894417fccd2771456f3eeaa81c | M-03 | There is now no limit to the number of tokens that can be proposed for whitelisting. Also, any whitelisting proposal that has reached quorum with sufficient approval votes can be executed. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-04 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-05 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/758349850a994c305a0ab9a151d00e738a5a45a0 | M-06 | ballotMaximumDuration added. There is now a default 30 day period after which ballots can be removed by any user. |
https://github.com/othernet-global/salty-io/commit/5766592880737a5e682bb694a3a79e12926d48a5 | M-07 | ManagedWallet has been removed. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-08 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/b01f6e5cb360e89f9e4cdae41d609ea747bcaa86 | M-09 | Fixes reserves DUST check |
https://github.com/othernet-global/salty-io/commit/c46069644739885fa36e84e27e1dd6362b854663 | M-11 | Ballots now keep track of their own requiredQuorum at the time they were created. |
https://github.com/othernet-global/salty-io/commit/39921b4a25041c7ac4e9b5279e12bb2ec518140b | M-12 | ballotNames now include all provided proposal arguments. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-13 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/ccf4368 | M-14 | Removed maxPendingTokensForWhitelisting. There is now no limit to the number of tokens that can be proposed for whitelisting. Also, any whitelisting proposal that has reached quorum with sufficient approval votes can be executed. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-15 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/a54656dd18135ca57eef7c4bf615b7cdff2613a7 https://github.com/othernet-global/salty-io/commit/53feaeb0d335bd33803f98db022871b48b3f2454 | M-16 | ArbitrageSearch updated as suggested with MSB as well |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-18 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/758349850a994c305a0ab9a151d00e738a5a45a0 | M-19 | There is now a default 30 day period after which ballots can be removed by any user. |
https://github.com/othernet-global/salty-io/commit/eaf40ef0fa27314c6e674db6830990df68e5d70e | M-20 | POL has been removed from the protocol |
https://github.com/othernet-global/salty-io/commit/eaf40ef0fa27314c6e674db6830990df68e5d70e | M-21 | POL has been removed from the protocol |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-22 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/44320a8cc9b94de433e437e025f072aa850b995a | M-25 | Zapping no longer uses scaling. |
https://github.com/othernet-global/salty-io/commit/eaf40ef0fa27314c6e674db6830990df68e5d70e | M-26 | POL has been removed from the protocol |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-27 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/0bb763cc67e6a30a97d8b157f7e5954692b3dd68 | M-28 | minAddedAmountA and minAddedAmountB are now used. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-29 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/8e3231d3f444e9851881d642d6dd03021fade5ed | M-30 | The stablecoin framework has been removed: /stablecoin, /price_feed, WBTC/WETH collateral, PriceAggregator, price feeds and USDS. |
https://github.com/othernet-global/salty-io/commit/5766592880737a5e682bb694a3a79e12926d48a5 | M-31 | ManagedWallet has been removed. |
Additional scope to be reviewed
Individual PRs
These are additional changes that will be in scope and were addressed outside of direct mitigation. (EXTRA Scoope)
URL | Mitigation of | Purpose |
---|---|---|
https://github.com/othernet-global/salty-io/commit/f16623e6bf1cdb0845b83ebf3592e30885a8fc61 | E1 | Arbitrage no longer occurs when zapping liquidity |
https://github.com/othernet-global/salty-io/commit/75901cae57382a87b5f049d7afb9c5d9b9ba4c19 https://github.com/othernet-global/salty-io/commit/7de25bca740332ae7a4b2f25c3a6f6419eaa7569 | E2 | Arbitrage gas optimization |
https://github.com/othernet-global/salty-io/commit/60de2c02bcfbcc64b41c03ea0582ec9e7a3f332a | E3 | Gas stabilization by preventing overwriting zeros after performUpkeep |
https://github.com/othernet-global/salty-io/commit/6998661013e86a50c7db552d189fadb0521dbeb0 | E4 | Fixes arbitrage revert when there is zero SALT/WETH liquidity |
https://github.com/othernet-global/salty-io/commit/2d1b7df004394720c0d8bb4aefe903021631eff3 | E5 | Limited user swaps to one per block to prevent bypassing arbitrage within a single block |
Out of Scope
Please list any High and Medium issues that were judged as valid but you have chosen not to fix.
M-10
M-17
M-23
M-24