Sturdy contest - fatherOfBlocks's results

The first protocol for interest-free borrowing and high yield lending.

General Information

Platform: Code4rena

Start Date: 13/05/2022

Pot Size: $30,000 USDC

Total HM: 8

Participants: 65

Period: 3 days

Judge: hickuphh3

Total Solo HM: 1

Id: 125

League: ETH

Sturdy

Findings Distribution

Researcher Performance

Rank: 30/65

Findings: 3

Award: $83.11

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

14.8433 USDC - $14.84

Labels

bug
duplicate
3 (High Risk)

External Links

Lines of code

https://github.com/code-423n4/2022-05-sturdy/blob/78f51a7a74ebe8adfd055bdbaedfddc05632566f/smart-contracts/LidoVault.sol#L140

Vulnerability details

Impact

In lines 140 and 141 a low-level transfer is performed and first it is reversed and then it is validated with the require if it was done correctly. This can generate many problems, since the transaction may not be carried out and a message may be returned as if it had been carried out correctly.

You must first perform the validation (line 140) and then perform the return (line 141)

#0 - sforman2000

2022-05-18T03:09:29Z

GeneralVault.sol

  • In general, they only put the contracts and no interfaces or other components inside the repository, therefore we cannot validate how correct a call to an interface is, for example. How can we know if they are respecting the interface or not.

  • Another example of this is the function withdrawCollateral() which is called on line 119 and has the comment: In Lido vault, it will return ETH or stETH to user, but we don't know how it is implemented.

  • In the L51 it appears that the vault fee is 20%, it is not clear what that comment refers to. This generates confusion since in the setTreasuryInfo() function it allows setting up to 30% of the fee.

LidoVault.sol

  • By not having access to the dependencies we cannot know how some calls are specifically implemented, for example, on line 57 when TransferHelper.transferFrom() is called, it is not known if some type of reentrance could be generated, for example.

  • In most methods you start by setting the LIDO address variable = _addressesProvider.getAddress('LIDO'); Since both are used and the LIDO value is set in the constructor, the LIDO variable could be created in storage and in the constructor set it with this line: "LIDO = _addressesProvider.getAddress('LIDO');"

  • Inside the function _withdrawFromYieldPool() when swapExactTokensForTokens(L130) is called, the value of 200 is found as the last parameter reading the code that represents that 200 is very difficult to understand.

YieldManager.sol

  • L219 - Validate that _asset meets the interface directly in the signature, this would avoid spending unnecessary gas.

ConvexCurveLPVault.sol

  • L40/27/62 - convexBooster address is hardcoded, that means it can only be run on one network, therefore

  • it only serves for testing on a certain testnet or only for mainnet.

  • It should be a constant and should be directly hardcoded into storage.

  • It would be better to simplify the use of interfaces, if in storage convexBooster instead of address directly it is of type IConvexBooster.

  • L137 - It is not necessary to request a parameter that can only be unique, therefore it is better not to request the _asset variable in the signature of _depositToYieldPool and remove the require.

  • L178 - It is not necessary to request a parameter that can only be unique, therefore it is better not to request the _asset variable in the signature of withdrawOnLiquidationy() removes the require.

  • L192 - It is not necessary to request a parameter that can only be unique, therefore it is better not to request the _asset variable in the signature of _withdrawFromYieldPool() removes the require.

#0 - HickupHH3

2022-06-06T07:26:46Z

working through the bullet pts:

  • Disagree, link to full repo was provided. behaviour can be verified.
  • Implementation in LidoVault. ETH/stETH were given as an example
  • Agree, issue with comment. (L1)
  • Invalid, as per first pt.
  • Possibly, I would argue it's done the way it is in case LIDO contract changes (NC1)
  • Readability issue, but lacks further explanation on what the issue really is. (NC2)
  • Only 1 other point is valid of hardcoding an address, but it honestly isn't that big of an issue. Constant declaration probably more valid as a gas opt.

Hence, 1 low and 2 NC have been raised

Awards

23.4132 USDC - $23.41

Labels

bug
G (Gas Optimization)

External Links

GeneralVault.sol

  • L29/L34: You can save 20,000 gas if instead of using modifiers you use a private view function.

  • L218: In the for loop you could save 25,000 gas if instead of using uint256 i= 0, you didn't set it to its default value. Also, instead of terminating with i++ to raise the value of i, use unchecked with ++i on the last line of the loop.

YieldManager.sol

  • L51: the onlyOwner() could generate a saving of 20,000 gas, if it is created as a private view.

  • L120/130/156: In the for loop you could save 25,000 gas if instead of using uint256 i= 0, you didn't set it to its default value. Also, instead of terminating with i++ to raise the value of i, use unchecked with ++i on the last line of the loop.

CollateralAdapter.sol

  • L17: the onlyOwner() could generate a saving of 20,000 gas, if it is created as a private view.

ConvexCurveLPVault.sol

  • L106: In the for loop you could save 25,000 gas if instead of using uint256 i= 0, you didn't set it to its default value. Also, instead of terminating with i++ to raise the value of i, use unchecked with ++i on the last line of the loop.

#0 - sforman2000

2022-05-18T01:20:33Z

Particularly high quality.

Edit: After further review, it looks like the numbers cited are incorrect

#1 - iris112

2022-05-18T16:26:29Z

L29/L34: You can save 20,000 gas if instead of using modifiers you use a private view function. I'm not sure how it could save 20000 gas. I have a test on remix with simple contract, when i change from modifier to private view function, deploying cost and function call cost is increased.

#2 - iris112

2022-05-18T17:03:01Z

Also, how did you estimated the reducing gas amount? You specified the reducing gas amount (ex: 20000, 25000 etc...)

#3 - HickupHH3

2022-06-07T06:37:24Z

I'm invalidating this report, numbers are over-inflated to possibly game the system.

#4 - HickupHH3

2022-06-07T06:38:52Z

Nvm the removal of zero initialisations and prefix increment suggestions are valid. However, I'll award a lower score for the inflated numbers.

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