Steadefi

Steadefi
DeFiHardhatFoundryOracle
35,000 USDC
View results
Submission Details
Severity: low
Invalid

Any residual `GMXVault` vault tokens might be lost if the trove is not re-set after deployment

Summary

Any residual GMXVault vault tokens might be lost if the trove is not re-set after deployment.

Vulnerability Details

  • In GMXVault contract: whenever a deposit or withdrawal is made by the user, a check is made to transfer any reidual tokens locked in the vault to the GMXTrove to prevent it from being considered as part of depositor's assets.

  • Each vault has a trove contract deployed for it, where the trove contract approves the vault on its tokenA & tokenB balnace so that the vault can manage and transfer them.

  • First when the GMXVault is deployed; it's trove (_store.trove) will be assigned any arbitrary value because the GMXTrove contract can be deployed after the vault is deployed as it only has a constructor with the address of its attached vault as a parameter (so it can't be deployed before the vault is deployed).

  • Once the GMXTrove contract is deployed for the vault; the owner of the contract will update the trove address via GMXVault.updateTrove function.

  • But as mentioned in the documentation, the owner of the GMXTrove is a multisig contract, and any change made by the owner must bypass the timelock before execution.

Impact

So, if users started to use the vault (before the trove contract address is updated) by making deposits (adding liquidity to GMX); any residual vault tokens (of tokenA and tokenB) will be lost instead of being transferred to the trove contract.

Proof of Concept

GMXTrove.constructor

constructor (address _vault) {
vault = IGMXVault(_vault);
GMXTypes.Store memory _store = vault.store();
// Set token approvals for this trove's vault contract
_store.tokenA.approve(address(vault), type(uint256).max);
_store.tokenB.approve(address(vault), type(uint256).max);
}

GMXVault.constructor

_store.trove = store_.trove;

Tools Used

Manual Review.

Recommendations

Deploy the trove contract in the constructor of the GMXVault:

_store.trove = new GMXTrove(address(this));
Updates

Lead Judging Commences

hans Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.