Platform: Code4rena
Start Date: 21/12/2021
Pot Size: $30,000 USDC
Total HM: 20
Participants: 20
Period: 5 days
Judge: Jack the Pug
Total Solo HM: 13
Id: 70
League: ETH
Rank: 3/20
Findings: 4
Award: $2,561.70
🌟 Selected for report: 5
🚀 Solo Findings: 1
141.5133 USDC - $141.51
danb
https://github.com/code-423n4/2021-12-vader/blob/main/contracts/dex-v2/pool/VaderPoolV2.sol#L165
nativeAsset.safeTransferFrom(from, address(this), nativeDeposit);
mintSynth has a from
parameter, this is where they take the money for the transaction.
If an address has allowance for the contract, anyone can use it and take it using mintSynth
.
If a user sets more allowance than they have to, for example if they want to call mintSynth many times and don't want to call approve again, then their funds can be stolen by anyone.
also, if a user wants to call mintSynth, and call approve in another transaction (so they don't have to create a contract), then mintSynth
can be frontrun to steal their funds.
consider the following scenario:
A user wants to call mintSynth. They know that they must approve nativeAsset
to the contract, so they execute an approve
transaction, so that later they will execute mintSynth.
when they submit the approve transaction, a malicious actor spots this, and sends a mintSynth transaction where from
is equal to the user address.
the hacker was able to steal the user's funds!
manual review
change to:
nativeAsset.safeTransferFrom(msg.sender, address(this), nativeDeposit);
#0 - jack-the-pug
2022-03-12T04:13:25Z
Dup of #147
🌟 Selected for report: TomFrenchBlockchain
388.2396 USDC - $388.24
danb
https://github.com/code-423n4/2021-12-vader/blob/main/contracts/lbt/LiquidityBasedTWAP.sol#L131
for tokens that are not updating in syncVaderPrice
because their updatePeriod is greated than timeElapsed, their liquidty weight will be zero, it will make the vader price wrong when calling getVaderPrice
and it can be exploited.
move this line: https://github.com/code-423n4/2021-12-vader/blob/main/contracts/lbt/LiquidityBasedTWAP.sol#L140 before this line: https://github.com/code-423n4/2021-12-vader/blob/main/contracts/lbt/LiquidityBasedTWAP.sol#L131
#0 - jack-the-pug
2022-03-13T12:08:59Z
Dup #42
🌟 Selected for report: danb
1437.9245 USDC - $1,437.92
danb
https://github.com/code-423n4/2021-12-vader/blob/main/contracts/dex-v2/pool/VaderPoolV2.sol#L334
on the first deposit, the total liquidity is set to nativeDeposit
.
this might be a very low number compared to foreignDeposit
.
It can cause a denial of service of the pair.
A pair can enter a denial of service state.
consider the following scenario:
the owner of the pool calls setFungibleTokenSupport
for a new token, for example weth.
a malicious actor calls mintFungible
, with nativeDeposit == 1
and foreignDeposit == 10 ether
.
totalLiquidityUnits
will be 1.
the pool can be arbitraged, even by the attacker, but totalLiquidityUnits
will still be 1.
this means that 1 liquidity token is equal to all of the pool reserves, which is a lot of money.
It will cause a very high rounding error for anyone trying to mint liquidity.
then, anyone who will try to mint liquidity will either:
after this is realised, no one will want to provide liquidity, and since the pair cannot be removed or replaced, it will cause denial of service for that token forever.
🌟 Selected for report: defsec
Also found by: Jujic, TomFrenchBlockchain, danb, hyh
18.8684 USDC - $18.87
danb
https://github.com/code-423n4/2021-12-vader/blob/main/contracts/lbt/LiquidityBasedTWAP.sol#L93 chainlink price might be negative, it's not a malfunction: https://stackoverflow.com/questions/67094903/anybody-knows-why-chainlinks-pricefeed-return-price-value-with-int-type-while if one of the tokens has anegative price, the system will be in denial of service.
#0 - SamSteinGG
2021-12-27T10:41:54Z
Chainlink price can not be negative
#1 - jack-the-pug
2022-03-13T11:20:46Z
Dup #111
🌟 Selected for report: danb
143.7924 USDC - $143.79
danb
https://github.com/code-423n4/2021-12-vader/blob/main/contracts/dex-v2/pool/VaderPoolV2.sol#L178
If a user calls mintSynth
when reserveForeign
is equal to zero, then they will pay and get nothing in return. They might interpert this as a scam.
amountSynth = VaderMath.calculateSwap( nativeDeposit, reserveNative, reserveForeign );
amountSynth
will be zero if reserveForeign
is zero (that happens before anyone provided liquidity).
#0 - jack-the-pug
2022-03-13T11:52:39Z
A valid low
: should require(amountSynth > 0)
.
🌟 Selected for report: danb
143.7924 USDC - $143.79
danb
https://github.com/code-423n4/2021-12-vader/blob/main/contracts/dex/utils/GasThrottle.sol#L12 uncomment.
#0 - jack-the-pug
2022-03-13T11:54:16Z
Downgrading to low
as the comment indicated it's going to uncomment before deployment.
🌟 Selected for report: danb
143.7924 USDC - $143.79
danb
https://github.com/code-423n4/2021-12-vader/blob/main/contracts/lbt/LiquidityBasedTWAP.sol#L191
in the calculation, both the nominator and the denominator are divided by totalVaderLiquidityWeight
:
return (totalUSD * 1 ether) / totalVader;
nominator:
totalUSD += (foreignPrice * liquidityWeights[i]) / totalVaderLiquidityWeight;
denominator:
totalVader += (pairData .nativeTokenPriceAverage .mul(pairData.foreignUnit) .decode144() * liquidityWeights[i]) / totalVaderLiquidityWeight;
it lowers the precision, it will be better if you remove the division by totalVaderLiquidityWeight
both in the nominator and the denominator.
🌟 Selected for report: danb
143.7924 USDC - $143.79
danb
https://github.com/code-423n4/2021-12-vader/blob/main/contracts/lbt/LiquidityBasedTWAP.sol#L221
vader can be initialized twice if in the first call to setupVader
, vaderPrice == 0
.
add:
require(vaderPrice > 0);
in setupVader
.