Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

63/64 Rule and its role in preventing call depth attacks #36

Closed
indeqs opened this issue May 18, 2024 · 7 comments
Closed

63/64 Rule and its role in preventing call depth attacks #36

indeqs opened this issue May 18, 2024 · 7 comments

Comments

@indeqs
Copy link
Contributor

indeqs commented May 18, 2024

Understanding the 63/64 Rule and its Role in Preventing Call Depth Attacks

Introduction

The 63/64 rule was introduced with Ethereum Improvement Proposal (EIP) 150. This rule states that when one contract calls another, a part of the available gas (1/64) will remain in the calling contract, while the rest (63/64) will be forwarded. For instance, if contract A has 64K gas and calls contract B, then contract B will receive 63K gas.

The Problem Addressed by the 63/64 Rule

To understand the reason behind this rule, it is crucial to know about the problem it aims to solve: the "Call Depth Attack."

Call Stack Limit

Ethereum has a call stack limit of 1024. This means no more than 1023 nested calls can be made by a contract before the Ethereum Virtual Machine (EVM) reverts. For example, if we have five contracts calling each other, we would have a call depth of 5:

A -> B -> C -> D -> E

Call Depth Attack Example

Before EIP-150, this stack limit could be exploited in what was known as the "Call Depth Attack." Consider the following Solidity contract:

contract Auction {
    address highestBidder;
    uint256 highestBid;

    function bid() external payable {
        if(msg.value < highestBid) revert();

        // Refund previous bidder
        if(highestBidder != address(0)) {
            payable(highestBidder).send(highestBid);
        }

        highestBidder = msg.sender;
        highestBid = msg.value;
    }
}

The bid() function could be exploited by a malicious contract that would initiate a recursive call to itself, causing the stack depth to increase to 1023 before calling bid(). For instance, a contract B which calls the function bid() in contract Auction can recursively call a function within itself 1023 times before calling the function bid(). As a result, the .send(highestBid) call would fail silently, and no refund would happen.

How EIP-150 Prevents Call Depth Attacks

This attack is no longer possible after EIP-150, because the forwarded gas (63/64) in each call is reduced exponentially the deeper the stack gets. The available gas at different stack depths is calculated as follows:

  • Gas available at stack depth 0: gasleft() * (63/64)^0
  • Gas available at stack depth 1: gasleft() * (63/64)^1
  • ...
  • Gas available at stack depth N: gasleft() * (63/64)^N

This exponential reduction in gas makes it impossible to reach the stack limit, effectively preventing the "Call Depth Attack."

Implications for Protocol Logic and Gas Calculation

It is essential to be aware of this rule if your protocol logic depends on gas calculations, especially if you are using the built-in Solidity gasleft() function.

References

Most of the above findings are relatively recent (less than a year ago), while EIP-150 has been around for the past 8+ years.

@kadenzipfel
Copy link
Owner

Since the actual vulnerability referenced here, call depth attacks, has effectively been prevented since EIP-150, I would consider this as more of a heuristic, so not sure how it would fit in to this repo. Might be useful to include a note about 63/64 if relevant for any existing issues though?

@indeqs
Copy link
Contributor Author

indeqs commented May 18, 2024

True, call depth attacks have been effectively prevented since EIP-150, but the 63/64 rule has clearly been leveraged in the bug reports linked above to cause some interesting vulnerabilities due to assumptions made about gas calculations. It obviously doesn't classify as a vulnerability on its own(you could argue the same about open redirects vulnerabilities in web2) but can lead to bugs if not taken into consideration when your protocol depends on gas calculation.

I do find it relevant to this repository as it is a way to improve the value of this repo.

@kadenzipfel
Copy link
Owner

@indeqs, I don't disagree. Perhaps we can expand the repo to include heuristics that are relevant to security researchers? I'm not set on this idea, but curious what others think. Perhaps would be worth opening an issue to discuss this

@indeqs
Copy link
Contributor Author

indeqs commented May 18, 2024

@kadenzipfel perhaps the below might be a better classification of the vulnerabilities listed in this repo. I also included more vulnerabilities as seen here by @ShieldifyAnon on X/Twitter

Gas Management Issues

  • Insufficient Gas Griefing
  • Loops Gas Limit

Reentrancy

  • Reentrancy via Modifier
  • Read-Only Reentrancy
  • Cross-Function Reentrancy
  • Cross-Contract Reentrancy

Front-running

  • Front-Running - Unprotected Withdraw
  • Front-Running - Sandwich Attack
  • Front-Running - ERC20 Approval
  • Front-Running - Signatures
  • Back-Running

Flash Loans

  • Flash-Loan Governance Attack
  • Flash-Loan Price Attack

Denial of Service (DoS)

  • Denial Of Service (DOS) by Complex Fallback Function
  • DoS with Block Gas Limit
  • DoS with (Unexpected) revert
  • Denial Of Service (DOS) by Non-Existent Address or Malicious Contract

Arithmetic Issues

  • Floating Point Arithmetic
  • Integer Overflow
  • Integer Underflow
  • Divide before Multiply
  • Lack of Precision
  • Off-By-One

Cryptographic Issues

  • ECDSA Signature Malleability
  • ECDSA Signature Replay
  • Replay Attack
  • Signature Malleability

Price Oracle Manipulation

  • Price Oracle Manipulation

Cross-Chain Issues

  • Cross-Chain Bridge Manipulation

Token Supply Issues

  • Initial Supply Mint Issue

DeFi Specific Vulnerabilities

  • DeFi Slippage Attack
  • Amplification Attack Double Spending

Malicious Contracts

  • Malicious Honeypot

Unsafe Calls

  • Unsafe Delegatecalls
  • Unsafe Low-Level Call
  • Delegatecall to Untrusted Callee

Social Engineering and Phishing

  • Phishing With Improper Authorization

Ether Handling Issues

  • Unexpected Ether With Forcibly Sending Ether

Block Attributes and Timing Issues

  • Block Timestamp Manipulation
  • Timestamp Dependence
  • Transaction-Ordering Dependence

Function Validation and Standards

  • Unchecked Return Values
  • Requirement Validation
  • Absent Modifiers
  • Use of Deprecated Functions
  • Strict Equalities
  • Insecure Randomness
  • Inadherence to Standards

Storage and Visibility Issues

  • Proxy Storage Collision
  • Uninitialized Storage Pointer
  • Write to Arbitrary Storage Location
  • Incorrect Inheritance Order
  • Shadowing State Variables
  • Presence of Unused Variables
  • Unencrypted Private Data On-Chain

Data Handling Issues

  • Unencrypted Private Data On-Chain

Heuristic

  • 63/64 gas rule

Other Issues

  • Rounding Down To Zero
  • Force Feeding
  • Unexpected ecrecover null address
  • Asserting Contract from Code Size
  • Floating Pragma
  • Outdated Compiler Version
  • Assert Violation
  • Authorization Through tx.origin
  • Insufficient Access Control
  • Default Visibility

This categorization is by no means exhaustive but something we can work with for starters

@kadenzipfel
Copy link
Owner

@indeqs, this is really useful and I think would be good to open up an issue to discuss taxonomy of vulnerabilities with this being an excellent starting point. Definitely also a ton of findings here that are not already included in this repo, so lots to add!

This being said, I don't feel like heuristics really fits in as a category here so not sure how the 63/64 rule will fit into the repo in general. Will leave this open for discussion though

@indeqs
Copy link
Contributor Author

indeqs commented May 19, 2024

Also leaving this open for discussion.

@indeqs
Copy link
Contributor Author

indeqs commented Jun 9, 2024

closing this as it is now issue#41

@indeqs indeqs closed this as completed Jun 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants