Platform: Code4rena
Start Date: 15/06/2022
Pot Size: $30,000 USDC
Total HM: 5
Participants: 55
Period: 3 days
Judge: Jack the Pug
Id: 138
League: ETH
Rank: 26/55
Findings: 3
Award: $130.88
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Picodes
Also found by: 0x1f8b, 0x52, Chom, GimelSec, IllIllI, berndartmueller, cccz, defsec, georgypetrov, hyh, kenzo, minhquanym, oyc_109, scaraven, unforgiven
50.7077 USDC - $50.71
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L249 https://dev.balancer.fi/resources/swaps/single-swap#swap-function
Due to a bug with the slippage configuration it is possible to make a call to the harvest
method do a swap with 0 BALETH_BPT
tokens.
According to the balancer documentation the limit
argument represents:
limit: The meaning of limit depends on the value of singleSwap.kind GIVEN_IN: The minimum amount of tokens we would accept to receive from the swap.
So if an attacker detects the harvest
transaction in the memory pool, and configures two transactions to perform a sadwitch attack, the contract will perform a swap with an expected minimum of 0 tokens.
Reference:
Affected source code:
#0 - GalloDaSballo
2022-06-17T14:57:35Z
Dup of #6
#1 - 0x1f8b
2022-06-21T12:46:01Z
Dup of https://github.com/code-423n4/2022-06-badger-findings/issues/6
Is not related to #6 @GalloDaSballo
#2 - KenzoAgada
2022-06-23T02:14:39Z
Duplicate of #155
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0xDjango, 0xFar5eer, 0xNazgul, 0xNineDec, 242, Chom, Czar102, Funen, GimelSec, Meera, Picodes, Sm4rty, Tadashi, TerrierLover, Waze, _Adam, a12jmx, asutorufos, codexploder, cryptphi, defsec, gzeon, hyh, joestakey, minhquanym, oyc_109, reassor, robee, saian, sorrynotsorry, unforgiven, zzzitron
50.8486 USDC - $50.85
The pragma version used is:
pragma solidity 0.6.12;
But recently solidity released a new version with important Bugfixes:
The first one is related to ABI-encoding nested arrays directly from calldata. You can find more information here.
The second bug is triggered in certain inheritance structures and can cause a memory pointer to be interpreted as a calldata pointer or vice-versa. We also have a dedicated blog post about this bug.
Apart from these, there are several minor bug fixes and improvements.
The minimum required version should be 0.8.14
It's important to emit events when the governance change important values in the contract, in order to be more open and transparent.
Affected source code:
The method claimBribesFromHiddenHand
does not define the public
visibility, take in care that when is not defined, the visibility is public
.
Affected source code:
whenNotPaused
The method claimBribesFromHiddenHand
allows to do do changes when the contract is paused. It's better to limit this.
Affected source code:
TODO usually mean something still have to be checked of done. This could lead to vulnerabilities if not verified.
Affected source code:
Although it is a contract that is not inherited, it is possible that it will be extended in the future, it is worth adding _gap
variables at the end of the contract to avoid update problems.
Affected source code:
#0 - GalloDaSballo
2022-06-19T01:24:37Z
Ack but disagree
Disagree
It's external, check the bot
Why?
Ack
It's in BaseStrategy, check the bot
29.3239 USDC - $29.32
external
visibilityThe following methods could be improved if external
visibility is used:
In MyStrategy.sol#L56-L59 is not needed the argument, it's possible to change the logic from:
function initialize(address _vault) public initializer { assert(IVault(_vault).token() == address(AURA)); __BaseStrategy_init(_vault);
to:
function initialize() public initializer { __BaseStrategy_init(AURA);
Gas optimizations and additional safety checks are provided for free when using newer compiler versions and the optimizer.
pragma solidity 0.6.12;
Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met)
Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.
Custom errors are defined using the error statement, which can be used inside and outside of contracts (including interfaces and libraries).
If it's not possible to use error codes due to the pragma used, it is recommended to reduce the strings to less than 32 bytes.
Affected contracts:
++i
costs less gas compared to i++
or i += 1
++i
costs less gas compared to i++
or i += 1
for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled.
i++
increments i
and returns the initial value of i
. Which means:
uint i = 1; i++; // == 1 but i == 2
But ++i
returns the actual incremented value:
uint i = 1; ++i; // == 2 and i == 2 too, so no need for a temporary variable
In the first case, the compiler has to create a temporary variable (when used) for returning 1
instead of 2
I suggest using ++i
instead of i++
to increment the value of an uint variable. Same thing for --i
and i--
It is also recommended to not initialize the counter variable and surround the increment with an unchecked
region.
Affected source code:
#0 - GalloDaSballo
2022-06-19T01:26:27Z
Disagree with the exception of the increment of loop that would save 3 + 5 gas