DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Unvalidated Token Transfers in GmxProxy

Summary

The afterOrderExecution function in GmxProxy.sol transfers tokens based on unvalidated addresses from eventData, allowing potential transfers of unauthorized tokens.

https://github.com/CodeHawks-Contests/2025-02-gamma/blob/e5b98627a4c965e203dbb616a5f43ec194e7631a/contracts/GmxProxy.sol#L250

https://github.com/CodeHawks-Contests/2025-02-gamma/blob/e5b98627a4c965e203dbb616a5f43ec194e7631a/contracts/GmxProxy.sol#L253

Vulnerability Details

Faulty Code Snippet:

// GmxProxy.sol
function afterOrderExecution(...) external validCallback(...) {
// ...
if (eventData.uintItems.items[0].value > 0) {
IERC20(eventData.addressItems.items[0].value).safeTransfer(perpVault, eventData.uintItems.items[0].value); // ⚠️ Unvalidated token address
}
if (eventData.uintItems.items[1].value > 0) {
IERC20(eventData.addressItems.items[1].value).safeTransfer(perpVault, eventData.uintItems.items[1].value); // ⚠️ Unvalidated token address
}
// ...
}

Unchecked Addresses: The token addresses (eventData.addressItems.items[0].value and eventData.addressItems.items[1].value) are not validated against a list of allowed tokens (e.g., collateralToken or indexToken).

Risk of Malicious Data: If eventData is manipulated (e.g., via compromised GMX callback), attackers can drain funds by specifying arbitrary token addresses.

Example Attack Scenario

  • Malicious Order Execution: An attacker triggers an order that populates eventData with a fake token address (e.g., attackerToken).

  • Unauthorized Transfer: The contract transfers attackerToken to perpVault, but since attackerToken is controlled by the attacker, they can mint unlimited tokens or re-enter the contract.

Impact

  1. Fund Theft: Attackers can steal any ERC20 token held by GmxProxy.

  2. Reentrancy: Malicious tokens may re-enter the contract during transfer, bypassing the state checks

Tools Used

Manual review

Recommendations

Validate that transferred tokens are collateralToken or indexToken.

function afterOrderExecution(...) external validCallback(...) {
// ...
// Validate token addresses before transferring
if (eventData.uintItems.items[0].value > 0) {
address token0 = eventData.addressItems.items[0].value;
require(
token0 == address(collateralToken) || token0 == indexToken,
"Invalid token 0"
);
IERC20(token0).safeTransfer(perpVault, eventData.uintItems.items[0].value);
}
if (eventData.uintItems.items[1].value > 0) {
address token1 = eventData.addressItems.items[1].value;
require(
token1 == address(collateralToken) || token1 == indexToken,
"Invalid token 1"
);
IERC20(token1).safeTransfer(perpVault, eventData.uintItems.items[1].value);
}
// ...
}

After fix:

Address Validation: Added require statements to ensure only collateralToken or indexToken are transferred.

Verification

Test Case 1 (Valid Token):

eventData specifies collateralToken and indexToken.

Transfers succeed ✅.

Test Case 2 (Invalid Token):

eventData includes attackerToken.

Transaction reverts with "Invalid token" ❌.

Updates

Lead Judging Commences

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Suppositions

There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Suppositions

There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.

Support

FAQs

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