Steadefi

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

Missing Callback Verification and Default Handling

Summary

The function afterDepositExecution is designed to be called by the GMX contract as part of a callback process. It checks various conditions to determine the appropriate action, such as processing a deposit, rebalancing, or dealing with withdrawals. However, there is no explicit handling for the case where none of the specified conditions are met. An attacker can detect a bug and deploy own contract then use GMXCallback.sol as the call back function when sending a transaction to GMX, This mean GMX kepper calls the GMXCallback.sol and when non of the various condition is met, it will not revert which could lead to unexpected and potentially risky behavior when a transaction is initiated from the GMX contract, assuming that everything is fine. Therefore, a vulnerability exists in the handling of transactions that do not meet any of the defined conditions.

Vulnerability Details

Bob deploy a contract and call it bundle.sol then use GMXCallback.sol and the callback contract then instantiate a transaction into GMX for deposit, GMX controller call GMXCallback.sol {afterDepositExecution()} passed in Bob deposit key, and send market token into the callback contract, this will ensure that all calls to GMXCallback.sol are from GMXVault.sol

Conditional Execution: The function afterDepositExecution contains a series of conditional statements that check the status of the GMX contract and the provided deposit key to determine the appropriate action. If a matching condition is found, the corresponding function is called.

Missing Default Handling: There is no default handling or explicit condition for situations where none of the specified conditions is met. In such cases, the function proceeds without any specific action, potentially leading to unintended consequences.

Transaction Initiation: The function is intended to be called by the GMX contract as part of a callback process. A transaction is sent from GMX to this contract, and the function should handle it appropriately based on the conditions. However, in the absence of a matching condition, the transaction proceeds without any explicit guidance.

Impact

The potential impact of this vulnerability includes:

Unintended and unpredictable behavior when a transaction is initiated from GMX without a matching condition.
Risk of unexpected execution, which may lead to undesired state changes or financial implications.

Tools Used

Recommendations

To address this vulnerability, the following recommendations are proposed:

Add Explicit Default Handling: Implement an else statement or a default condition to handle transactions that do not meet any of the specified conditions. This default behavior should include an explicit action or a transaction revert to prevent unintended execution.

function afterDepositExecution(
bytes32 depositKey,
IDeposit.Props memory /* depositProps */,
IEvent.Props memory /* eventData */
) external onlyController {
GMXTypes.Store memory _store = vault.store();
if (
_store.status == GMXTypes.Status.Deposit &&
_store.depositCache.depositKey == depositKey
) {
vault.processDeposit();
} else if (
_store.status == GMXTypes.Status.Rebalance_Add &&
_store.rebalanceCache.depositKey == depositKey
) {
vault.processRebalanceAdd();
} else if (
_store.status == GMXTypes.Status.Compound &&
_store.compoundCache.depositKey == depositKey
) {
vault.processCompound();
} else if (
_store.status == GMXTypes.Status.Withdraw_Failed &&
_store.withdrawCache.depositKey == depositKey
) {
vault.processWithdrawFailureLiquidityAdded();
} else if (_store.status == GMXTypes.Status.Resume) {
// This if block is to catch the Deposit callback after an
// emergencyResume() to set the vault status to Open
vault.processEmergencyResume();
} else { // @audit additional code
revert Errors.InvalidStatus
}
}

Implement Call Verification with Boolean Enablement: To enhance security and ensure that calls are only accepted from known and trusted contracts, consider implementing a verification mechanism using a boolean enablement flag. Before processing any action, the contract should verify that the call is coming from a known and trusted contract. If the verification fails, the transaction should be reverted. This additional layer of protection can help prevent unauthorized or unexpected calls to the function, adding an extra level of security and predictability to the contract's behavior.

struct Store {
/// ........
bool verified;
}
function deposit(
GMXTypes.Store storage self,
GMXTypes.DepositParams memory dp,
bool isNative
) external {
// ......
self.verified = true;
}
function afterDepositExecution(
bytes32 depositKey,
IDeposit.Props memory /* depositProps */,
IEvent.Props memory /* eventData */
) external onlyController {
GMXTypes.Store memory _store = vault.store();
if(!self.verified) revert UnverifiedSource;
}

This can be done during withdrawal also.

Enhance Predictability: Ensure that all transactions initiated from GMX, even those not covered by specific conditions, are handled predictably and safely. Clearly document the expected behavior for such cases.

Updates

Lead Judging Commences

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

Incomplete logic branch in callback

Support

FAQs

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