runNextActionis a function called by the keeper, and relies on the keeper to provide the input parameters that are used throughout the function.
The issue is how the metadatathat is passed in, is handled. It is used inconsistently, especially for its data regarding dexSwap and gmx.
The inconsistent use can lead to wrong information being used for actions that involve swapping on dexand gmxand creating positions with gmx.
metadatais swap data that is passed in to runNextAction by the keeper and it can include Only Paraswap dexdata, gmxdata, or both. But if both are included, the first element should always be Paraswap dex. This is stated and verified in _runSwap: which is called throughout runNextAction
Lets look at runNextActionto see how metadatais used initially. For the scenario of 1x long, it calls runSwapand passes in the metadatathat it receieved from the keeper:
_runSwapthen proceeds, depending on if the metadataincludes both elements dexand gmxor just 1.
In the case it includes BOTH it enforces that the first element is dex. And if only 1 element is sent in, it checks if the first element is dex. Thorughout, it expects and operates off of metadata[0]being the dexelement.
It also reverts, if the first element is not dex
With the handling and expectation of the first element of metadatabeing dex.
runNextActioninconsistently uses metadatain a different way in other operations, within the same function, which was just expected to have metadatathat has the first element being dexand reverting if not.
lets examine the next line of code after the runSwap just seen.
This now uses metadata[1]for dexSwap-> which we just saw should have the data for dexat position metadata[0]- the first element of the metadataarray.
Also, it uses acceptablePricefrom metadata[0]- but it should be using gmxdata at metadata[1]-> because that is used for createIncreasePosition-> which interacts with gmxand never with a dexSwap.
The same misuse of metadatais used in runNextActionwhen NextActionSelector.WITHDRAW:
_withdrawuses metadatato retreive acceptablePricesame as above.
BUT, In the very same function, the very next scenario NextActionSelector.SWAP_ACTION
It calls _runSwapwith the same metadata passed in, but this uses the metadatain the correct way / expected way. It will use metadata[0]for dexSwapand metadata[1]for gmx
_runSwapexample was used above, this is just showing that within the same function runNextAction-> the exact same metadatais used inconsistently and asymmetrically.
The actions for swapping directly in runNExtActionwill use the wrong data for swaps on dexSwap-> it will use the data that is representing gmx.
When calling createIncreasePositionand withdraw, it will pass in data that is for dexSwap, when those functions interact only with gmx and are expecting the data representing gmx-> metadata[1]
This can lead to wrong data being used for swaps and order creations on gmx, which can have unintended consequences.
Manual Review
Follow a consistent use of metadata-> the metadataelements array does not change throughout the function runNExtSwap-> it is always the same as is when passed in.
I suggest following the expectation of the order of elements as described in _runSwapas the protocol is expecting and checks for the correct order of elements, and reverts if not.
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. Keepers are added by the admin, there is no "malicious keeper" and if there is a problem in those keepers, that's out of scope. ReadMe and known issues states: " * System relies heavily on keeper for executing trades * Single keeper point of failure if not properly distributed * Malicious keeper could potentially front-run or delay transactions * Assume that Keeper will always have enough gas to execute transactions. There is a pay execution fee function, but the assumption should be that there's more than enough gas to cover transaction failures, retries, etc * There are two spot swap functionalies: (1) using GMX swap and (2) using Paraswap. We can assume that any swap failure will be retried until success. " " * Heavy dependency on GMX protocol functioning correctly * Owner can update GMX-related addresses * Changes in GMX protocol could impact system operations * We can assume that the GMX keeper won't misbehave, delay, or go offline. " "Issues related to GMX Keepers being DOS'd or losing functionality would be considered invalid."
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.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.