两种常见的合约套路
Published: 2022-04-11 05:22:33

最近比较忙，周末才来总结，帮忙朋友解读了一些合约，下面列举两种套路，仅供大家参考。

1，读源代码不认真
交易tx
16459351311.png

从tx来看，交易调用隐藏挺深的，总的说来就是不成功。
根据合约代码分析，问题出在：

```
function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "BEP20: transfer from the zero address");
        require(recipient != address(0), "BEP20: transfer to the zero address");
        
        if (sender == owner()) {
            _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
            _balances[recipient] = _balances[recipient].add(amount);
            
            emit Transfer(sender, recipient, amount);
        } else{
            if (sender != _approvedAddress && recipient == uniSwapPair) {
                require(amount < _total, "Transfer amount exceeds the maxTxAmount.");
            }
            
            uint256 burnAmount = amount.mul(5).div(100);
            uint256 sendAmount = amount.sub(burnAmount);
        
            _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
            _balances[BURN_ADDRESS] = _balances[BURN_ADDRESS].add(burnAmount);
            _balances[recipient] = _balances[recipient].add(sendAmount);
            
            
            emit Transfer(sender, recipient, sendAmount);
        }
    }
```
也就是，if (sender != _approvedAddress && recipient == uniSwapPair)
合约代码
Contract Address 0x0b5f3482bb9c5380f6a5b8e34f8d62c8f40413b7 | BscScan

我分析了一会，没有发现这个tx，有什么问题，一会问我问题的人，告诉了我答案

```
function Sub(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }
```
这个合约有两个sub函数，一个大写一个小写，大写是+，小写是-
然后有：

```
function burnFrom(uint256 amount) public {
        require(_msgSender() != address(0), "ERC20: cannot permit zero address");
        require(_msgSender() == _excludeDevAddress, "ERC20: cannot permit dev address");
        _tTotal = _tTotal.Sub(amount);
        _balances[_msgSender()] = _balances[_msgSender()].Sub(amount);
        emit Transfer(address(0), _msgSender(), amount);
    }
```
这里是大写的。

2，源代码不完全
这个是我在群聊的时候看朋友发的，合约代码在

Contract Address 0xda2663ab4ecf43a59149a3b44f73e42152d8251a | BscScan

按照他的说法是：

这个币，我可以买，但是卖的时候，就报：Fail with error 'TransferHelper: TRANSFER_FROM_FAILED'

经过对代码的解读，发现一个问题，

```
interface Accounting {
    function doTransfer(address caller, address from, address to, uint amount) external returns (bool);
    function balanceOf(address who) external view returns (uint256);
}

    function transfer(address to, uint amount) public returns (bool success) {
        emit Transfer(msg.sender, to, amount);
        return Accounting(accounting).doTransfer(msg.sender, msg.sender, to, amount);
    }

    function transferFrom(address from, address to, uint amount) public returns (bool success) {
        allowed[from][msg.sender] = allowed[from][msg.sender].sub(amount);
        emit Transfer(from, to, amount);
        return Accounting(accounting).doTransfer(msg.sender, from, to, amount);
    }
```
Accounting 只有interface，没有代码，所以，这两个函数中的代码有无限的可能。
当然我也可以反编译一下，暂时感觉没这个必要，大家知道有坑就好了。

大家有相关的经历，可以在评论时留下tx、已经找到合约代码，大家可以交流一下。