Skip to content

Instantly share code, notes, and snippets.

Last active April 18, 2023 14:59
Show Gist options
  • Save estarriolvetch/47b7b2e592ab4c11bd75fa1b65d24557 to your computer and use it in GitHub Desktop.
Save estarriolvetch/47b7b2e592ab4c11bd75fa1b65d24557 to your computer and use it in GitHub Desktop.

Gelato Vulnerability Disclosure

Related important addresses

Who are affected:

  • Contracts that inherited from GelatoRelayContext and use _transferRelayFee() method to pay the relayer are vulnerable.
  • Similar issues may also occur with contracts inherited from GelatoRelayContextERC2771 as it implements the fee payment in a similar way.

Notable vulnerable contract:


The GelatoRelay is a trusted contract that could collect relay fee from clients' smart contract. It is designed to be trusted and thus the funds that are in the target contract is at GelatoRelay's disposal. As per design, callWithSyncFeeV2 in GelatoRelay.sol is guarded by the onlyGelato modifier.

As the target contract inherits from GelatoRelayContext, the _transferRelayFee() is called by the GelatoRelay.sol. _getFeeCollector() and _getFee()

We found it is possilbe to encode arbitrary feeCollector, feeToken,fee in the calldata and have it relayed by the gelato relay through sponsoredCall. Since sponsoredCall transactions are also relayed from the same contract as the one for the callWithSyncFeeV2, the smart contract can not distinguished whether the encoded fee parameters is from a legit callWithSyncFeeV2 call or a sponsoredCall call with malacious fee parameters. Both types of transactions can pass the onlyGelato modifier. This allows exploiter to drain all the funds from contracts that implements _transferRelayFee().

Even though the target contract can cap the relay fee with _transferRelayFeeCapped(uint256 _maxFee), the exploiter may still be able to drain the contract with multiple transactions.

Proof of Concept


It's possible to trigger _transferRelayFee() encoded with aribitray fee receipant and parameters with sponsoredCall() with the Counter.sol example provided on the Gelato's documentation. This is an actual relayed transaction on the mumbai testnet.


Simulation agaist 0xfea5b6d5f990ebdff4e8b103eddeb4279f4efd51 on Polygon

We also simulated the transaction on one of the notable vulnerable contracts and showed it's possible drained the funds from the contract. In this example, 1000 USDC (It can be encoded to any number.) is drained by the exploiter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment