Back to glossary

63 / 64 Gas Rule (Solidity Code Example)

Table of Contents

According to the 63 / 64 gas rule, external calls receive, at most, 63 / 64 of the remaining gas in the calling contract.

Vulnerability

Contracts that refund gas used must account for this 1/64 gas that is not spent.

Here is a simplified example of a contract that refunds gas.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

contract A {
    function f(address b) external {
        uint256 gasStart = gasleft();
        B(payable(b)).g(msg.sender, gasStart);
    }
}

contract B {
    event Log(uint256 gas);

    mapping(address => bool) public authorized;

    constructor() {
        authorized[msg.sender] = true;
    }

    receive() external payable {}

    function setAuth(address addr, bool auth) external {
        require(authorized[msg.sender], "not authorized");
        authorized[addr] = auth;
    }

    // Send 9000000000000000000 gas to drain ETH
    function g(address receiver, uint256 gasStart) external {
        require(authorized[msg.sender], "not authorized");

        uint256 gasNow = gasleft();
        uint256 gasUsed = gasStart - gasNow;
        // Fix
        //uint256 gasUsed = gasStart - (gasNow / 63) - gasNow;
        (bool ok,) = receiver.call{value: gasUsed}("");
        require(ok, "send failed");

        emit Log(gasUsed);
    }
}

/*
# 63 / 64 gas rule
External calls receive max 63 / 64 of gas left in current contract
1 / 64 gas is kept in the current contract

g0 = call to gasleft() somewhere in A
g1 = call to gasleft() somewhere in B
g* = Actual gas left immediately before call to B

  g*    63/64 g*
A |---->| B
|         |
g0        g1

# Gas used
dg = gas used between g0 and g1
   = g0 - g* + 63/64 g* - g1
   = g0 - g1 - 1/64 g* >= 0

# Problem
- Refund of g0 - g1 over pays by 1/64 g*
- g* can be large by sending large amount of gas

# Fix
g1 <= 63/64 g* <= g0
g1/63 <= 1/64 g* <= g0/63
g0 - g1 - g1/63 >= g0 - g1 - 1/64 g* >= g0 - g1 - 1/63 g0 = 62/63 g0 - g1
                                     >= 0

Refund g0 - g1 - g1/63
*/

Related Terms

No items found.