function withdraw() public {
        uint256 amountToSend = address(this).balance / 100;
        // perform a call without checking return
        // The recipient can revert, the owner will still get their share
        partner.call{value: amountToSend}("");
        // keep track of last withdrawal time
        timeLastWithdrawn = block.timestamp;
        withdrawPartnerBalances[partner] += amountToSend;

I have this vulnerable function from Ethernaut's Level 20 Denial CTF. How should I go about writing a Foundry test case to test that this function will cause a DoS when it calls a malicious contract that wastes the gas by going in an endless loop such as:

receive() external payable {

1 Answer 1


First thing to know is that this won't always revert since a call will use at most 63/64 of the gas forwarded. So if 1/64 of the gas forwarded is sufficient for the rest of the operations (besides the call), invoking the function withdraw won't revert (solidity documentation).

You could write something like below (this uses the implementation from the Ethernaut 20)

contract DenialTest is Test {
    Denial public denial;
    function setUp() public {
        denial = new Denial();
        Receiver receiver = new Receiver();
    function testRevertWithdrawal() public {
        denial.withdraw{gas: 1000000}();

contract Receiver {
    receive() external payable {
        while(true) {}

Or you could do a fuzz test by setting the gas forwarded as argument to the test, but beware to use vm.assume to limit the gas forwarded, because there won't be a revert if you forward too much gas, and the test will fail.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.