Slingshot Finance contest - gpersoon's results

Web3 trading platform.

General Information

Platform: Code4rena

Start Date: 30/10/2021

Pot Size: $35,000 ETH

Total HM: 2

Participants: 16

Period: 3 days

Judge: alcueca

Total Solo HM: 1

Id: 48

League: ETH

Slingshot Finance

Findings Distribution

Researcher Performance

Rank: 9/16

Findings: 2

Award: $588.84

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Findings Information

🌟 Selected for report: WatchPug

Also found by: daejunpark, gpersoon, hickuphh3, kenzo, pmerkleplant

Labels

bug
duplicate
2 (Med Risk)
disagree with severity
sponsor confirmed

Awards

588.8441 USDC - $588.84

External Links

Handle

gpersoon

Vulnerability details

Impact

The function executeTrades() of Slingshot.sol calulates the initialBalance and finalBalance in a different way. If toToken == nativeToken then:

  • initialBalance == executioner.balance;
  • finalBalance == wrappedNativeToken.balanceOf(address(executioner))

This could lead to different problems:

  1. If someone (accidentally) sends ETH to the executioner then: 1a) "finalBalance - initialBalance" could be negative, resulting in a revert 1b) finalBalance - initialBalance could be smaller than finalAmountMin, resulting in a revert (even if the expected amount of wrappedNativeToken has been received) So you could create a grieving attack by sending ETH to the executioner Then any future trades with toToken == nativeToken will most likely fail (until the nativeToken is removed with rescueTokens)
  2. You can sweep any available wrappedNativeToken in the executioner because executioner.balance and thus initialBalance will usually be 0, so finalBalance is the entire amount of wrappedNativeToken in the executioner.

Proof of Concept

https://github.com/code-423n4/2021-10-slingshot/blob/f6e7a0a39e3267bbe3c7fe60d6074cbf54f5750f/contracts/Slingshot.sol#L81-L91

Tools Used

Possible solutions:

  1. Calculate initialBalance in the same way as finalBalance: if (toToken == nativeToken) { initialBalance = _getTokenBalance(address(wrappedNativeToken)); } else { initialBalance = _getTokenBalance(toToken); }

  2. Sum the amount of nativeToken and wrappedNativeToken: function _getTokenBalance(address token) internal view returns (uint256 balance) { if (token == nativeToken) { balance = address(executioner).balance;
    token = address(wrappedNativeToken); } balance += IERC20(token).balanceOf(address(executioner)); }

  3. Ignore the initialBalance because the executioner isn't supposed to have any tokens anyway

#0 - tommyz7

2021-11-03T14:29:49Z

good finding, however, I disagree on risk. No user funds are at risk. This is medium riks.

#1 - alcueca

2021-11-06T06:05:13Z

Griefing attacks are severity 2

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