Salty.IO - Tripathi'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: 61/178

Findings: 4

Award: $163.11

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: 0xBinChook

Also found by: 0x3b, 0xRobocop, 0xpiken, SpicyMeatball, Tripathi, cats, erosjohn, ether_sky, fnanni, juancito, pina

Labels

bug
2 (Med Risk)
satisfactory
sponsor disputed
duplicate-362

Awards

53.4926 USDC - $53.49

External Links

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/main/src/dao/Proposals.sol#L317 https://github.com/code-423n4/2024-01-salty/blob/main/src/dao/Proposals.sol#L385 https://github.com/code-423n4/2024-01-salty/blob/main/src/dao/DAO.sol#L278

Vulnerability details

Impact

Altering the quorum for a proposal could result in unexpected outcomes since, for all active proposals, the current quorum is considered instead of the quorum that was present at the start of the proposal.

Proof of Concept

https://github.com/code-423n4/2024-01-salty/blob/main/src/dao/DAO.sol#L278

The finalizeBallot() function is called to execute the proposal, checking if the minimum time and quorum for the proposal are met using proposals.canFinalizeBallot(ballotID).

https://github.com/code-423n4/2024-01-salty/blob/main/src/dao/Proposals.sol#L385

canFinalizeBallot() examines the ballotMinimumNedTime from the ballot storage variable. For quorum, it assumes that the quorum remains the same as it was at the time of proposing the proposal. However, the current quorum depends on various parameters.


	function requiredQuorumForBallotType( BallotType ballotType ) public view returns (uint256 requiredQuorum)
		{
		// The quorum will be specified as a percentage of the total amount of SALT staked
		uint256 totalStaked = staking.totalShares( PoolUtils.STAKED_SALT );
		require( totalStaked != 0, "SALT staked cannot be zero to determine quorum" );

		if ( ballotType == BallotType.PARAMETER )
			requiredQuorum = ( 1 * totalStaked * daoConfig.baseBallotQuorumPercentTimes1000()) / ( 100 * 1000 );
		else if ( ( ballotType == BallotType.WHITELIST_TOKEN ) || ( ballotType == BallotType.UNWHITELIST_TOKEN ) )
			requiredQuorum = ( 2 * totalStaked * daoConfig.baseBallotQuorumPercentTimes1000()) / ( 100 * 1000 );
		else
			// All other ballot types require 3x multiple of the baseQuorum
			requiredQuorum = ( 3 * totalStaked * daoConfig.baseBallotQuorumPercentTimes1000()) / ( 100 * 1000 );

		// Make sure that the requiredQuorum is at least 0.50% of the total SALT supply.
		// Circulating supply after the first 45 days of emissions will be about 3 million - so this would require about 16% of the circulating
		// SALT to be staked and voting to pass a proposal (including whitelisting) 45 days after deployment..
		uint256 totalSupply = ERC20(address(exchangeConfig.salt())).totalSupply();//@audit increase total supply will increase the quorum
		uint256 minimumQuorum = totalSupply * 5 / 1000;

		if ( requiredQuorum < minimumQuorum )
			requiredQuorum = minimumQuorum;
		}

https://github.com/code-423n4/2024-01-salty/blob/main/src/dao/Proposals.sol#L317

The issue arises as the quorum is global for all proposals, leading to the execution of proposals with incorrect quorum values

  1. Decreasing quorum may lead to executing proposals, which was intentionally ignored due to less participation
  2. opposite to above

Proposer could wait to decrease/increase to call finalize ballot depending upon his/her pro and cons

Tools Used

Manual

implement tracking of quorum for proposals from the time of creation. During execution, compare the stored quorum with the current quorum to ensure accurate execution of proposals.

Assessed type

Context

#0 - c4-judge

2024-02-02T22:20:41Z

Picodes marked the issue as primary issue

#1 - c4-sponsor

2024-02-12T21:10:34Z

othernet-global (sponsor) disputed

#2 - othernet-global

2024-02-12T21:11:03Z

Yes, this is acceptable as part of the reason to lower quorum would be to push through previous proposals.

#3 - c4-judge

2024-02-20T11:31:07Z

Picodes changed the severity to QA (Quality Assurance)

#4 - Picodes

2024-02-20T11:31:39Z

Downgrading to QA as although it is risky and requires careful checks when lowering the quorum this is a suitable design.

#5 - Tri-pathi

2024-02-23T20:51:39Z

Hey @Picodes

Thanks for smooth judging. Sponsor comment- Yes, this is acceptable as part of the reason to lower quorum would be to push through previous proposals

what about the proposals which were malicious/bad for protocol and didn't able to get required votes during proposed time. Lowering quorum won't push only indented proposals it will push above malicious proposals too and it is way risky than it seems. I believe a core property is breaking here and hence qualifies for Medium severity{ even if won't fix tag from the sponsor }.

PS: More than welcome to whatever decision you take, but please have a second look at the impact

#6 - Picodes

2024-02-26T14:07:58Z

Thanks for your comment. This is a duplicate of https://github.com/code-423n4/2024-01-salty-findings/issues/764. See my arguments there.

#7 - Picodes

2024-02-28T10:57:37Z

@Tri-pathi following the discussion on #764 I'll upgrade this issue as well.

#8 - c4-judge

2024-02-28T10:58:20Z

This previously downgraded issue has been upgraded by Picodes

#9 - c4-judge

2024-02-28T10:58:36Z

Picodes marked the issue as duplicate of #362

#10 - c4-judge

2024-02-28T10:58:39Z

Picodes marked the issue as satisfactory

Findings Information

🌟 Selected for report: Banditx0x

Also found by: 00xSEV, 0xGreyWolf, 0xmuxyz, Hajime, Jorgect, Kaysoft, Krace, PENGUN, Tripathi, b0g0, djxploit, oakcobalt

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
duplicate-224

Awards

44.44 USDC - $44.44

External Links

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/main/src/staking/Liquidity.sol#L14 https://github.com/code-423n4/2024-01-salty/blob/main/src/staking/Liquidity.sol#L102

Vulnerability details

Impact

The protocol may experience a reduction in liquidity/shares and suboptimal trades due to the absence of slippage protection and deadline checks

Proof of Concept

https://github.com/code-423n4/2024-01-salty/blob/main/src/dao/DAO.sol#L316

The DAO invokes formPOL to create SALT/USD or USDS/DAI protocol-owned liquidity but does not specify parameters for slippages/minimum liquidity and deadline.

This function then calls

https://github.com/code-423n4/2024-01-salty/blob/main/src/staking/Liquidity.sol#L146

collateralAndLiquidity.depositLiquidityAndIncreaseShare() with minLiquidityReceived=0 and deadline=block.timestamp i.e neither slippage nor deadline has been implemented properly

Moreover, within the same function, the deadline parameter is discarded before any checks for calling internal _depositLiquidityAndIncreaseShare(). In other words, even if a front-end user attempts to provide a deadline, it won't be taken into account.

https://github.com/code-423n4/2024-01-salty/blob/main/src/staking/Liquidity.sol#L102

Upon further analysis, it becomes evident that it adds/withdraw liquidity to/from the pool without any slippage and deadline checks, leading to very unfavorable trades

Tools Used

Manual

Implement slippage and deadline checks appropriately throughout the codebase.

Assessed type

Token-Transfer

#0 - c4-judge

2024-02-02T10:47:22Z

Picodes marked the issue as duplicate of #224

#1 - c4-judge

2024-02-19T14:12:19Z

Picodes changed the severity to 2 (Med Risk)

#2 - c4-judge

2024-02-21T15:30:37Z

Picodes marked the issue as satisfactory

Findings Information

🌟 Selected for report: thekmj

Also found by: 00xSEV, J4X, Lalanda, OMEN, Toshii, Tripathi, Ward, eeshenggoh, grearlake, juancito, peanuts

Labels

bug
2 (Med Risk)
satisfactory
duplicate-60

Awards

53.4926 USDC - $53.49

External Links

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/main/src/price_feed/CoreChainlinkFeed.sol#L21

Vulnerability details

Impact

Reserve ratios and pool constraints may break if the WBTC bridge becomes compromised, and WBTC undergoes depegging

Proof of Concept

The chainlink BTC/USD oracle is utilized to price WBTC [https://github.com/code-423n4/2024-01-salty/blob/main/src/price_feed/CoreChainlinkFeed.sol#L21] . WBTC, being a bridged asset, could depeg if the bridge is compromised or fails, causing it to no longer be equivalent to BTC. This scenario would result in all swap functions (essentially the entire protocol) being active against an asset that is now effectively worthless.The protocol continues to value WBTC via BTC/USD, leading to several potential malicious actions, especially since many invariants depend on the WBTC/ETH pool

As the protocol operates smoothly with at least two functioning price feeds,the CoreUniswapFeed UniV3 TWAP safeguards against such asset depegging but other two CoreSaltyFeed and CoreChainlinkFeed will have no effect and hence protocol will keep functioning even in such case

Tools Used

Manual

Conduct a thorough analysis and implement a robust solution for determining the price of WBTC.

Assessed type

Oracle

#0 - c4-judge

2024-02-01T16:35:39Z

Picodes marked the issue as duplicate of #632

#1 - c4-judge

2024-02-20T15:51:24Z

Picodes marked the issue as satisfactory

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/main/src/launch/BootstrapBallot.sol#L69

Vulnerability details

Impact

f the protocol fails to receive enough votes during the initial proposal, all funds sent to the InitialDistribution will become stuck (1000000 ether)

Proof of Concept

https://github.com/code-423n4/2024-01-salty/blob/main/src/launch/BootstrapBallot.sol#L69

The finalizeBallot() function is called for the initial distribution, airdrop, and starting the exchange at the launch time. However, if startExchangeYes <= startExchangeNo, this condition leads to ballotFinalized = true, preventing further calls. There is currently no way to retrieve the funds, as the protocol assumes it will receive startExchangeYes > startExchangeNo. A malicious competitor or attacker could exploit this by funding the attack or employing other methods to ensure the condition holds

The main issue is that the protocol cannot propose for a vote a second time. If it fails to get enough startExchange votes the first time, it will lose all the funds

Tools Used

Manual

Implement a better approach that allows the protocol to repropose in case it doesn't receive enough votes initially:

  1. Provide a period for protocol teams to reevaluate and advertise the protocol after the first failed proposal

  2. Implement measures to make reproposing difficult for attackers by increasing the cost of such attacks

Assessed type

DoS

#0 - c4-judge

2024-02-02T12:04:28Z

Picodes marked the issue as duplicate of #606

#1 - c4-judge

2024-02-19T11:08:18Z

Picodes changed the severity to QA (Quality Assurance)

#2 - c4-judge

2024-02-21T17:00:56Z

Picodes marked the issue as grade-b

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