code-423n4 / 2022-11-redactedcartel-findings

3 stars 2 forks source link

Variable used before assignation on function `beforeDeposit` #334

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/PirexERC4626.sol#L60-L78 ttps://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/PirexERC4626.sol#L80-L97 https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/vaults/PirexERC4626.sol#L278-L282

Vulnerability details

Author: rotcivegaf

Impact

When the shares/assets parameters are passed in the function beforeDeposit they are not assigned yet:

In the both cases the value of the variable(shares/assets) it's 0 As the PirexERC4626 it's an abstract contract some new vault contract can inherit from him, like AutoPxGmx and AutoPxGlp If this new vault implement the function beforeDeposit using the shares or assets parameters for a calculation, the function deposit and mint could be broke

Note: The current contracts don't use the shares/assets parameters, but because it's a abstract contract this issue should be taken into consideration

Another consideration: remove the if (totalAssets() != 0), the function beforeDeposit should call in all cases and the case of totalAssets it's 0 should be resolve inside the function beforeDeposit

Proof of Concept

File: src/vaults/PirexERC4626.sol

/// @audit: `shares` defined in L68
65:        if (totalAssets() != 0) beforeDeposit(receiver, assets, shares);

/// @audit: `assets` defined in L87
85:        if (totalAssets() != 0) beforeDeposit(receiver, assets, shares);

Recommended Mitigation Steps

Move the beforeDeposit after the shares/assets definition

@@ -62,11 +62,11 @@ abstract contract PirexERC4626 is ERC20 {
         virtual
         returns (uint256 shares)
     {
-        if (totalAssets() != 0) beforeDeposit(receiver, assets, shares);
-
         // Check for rounding error since we round down in previewDeposit.
         require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");

+        if (totalAssets() != 0) beforeDeposit(receiver, assets, shares);
+
         // Need to transfer before minting or ERC777s could reenter.
         asset.safeTransferFrom(msg.sender, address(this), assets);

@@ -82,10 +82,10 @@ abstract contract PirexERC4626 is ERC20 {
         virtual
         returns (uint256 assets)
     {
-        if (totalAssets() != 0) beforeDeposit(receiver, assets, shares);
-
         assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up.

+        if (totalAssets() != 0) beforeDeposit(receiver, assets, shares);
+
         // Need to transfer before minting or ERC777s could reenter.
         asset.safeTransferFrom(msg.sender, address(this), assets);
Picodes commented 1 year ago

Interesting remarks but this does not lead to a finding in the context of this contest when PirexERC4626 is used

c4-judge commented 1 year ago

Duplicate of https://github.com/code-423n4/2022-11-redactedcartel-findings/issues/360