tx.origin的穿透性和攻击性 / 学习智能合约#19
如果只是简单地逻辑实现,那么就应该只用msg.sender
就好啰。但是真实情况往往是你需要把逻辑划分成不同的合约来实现,再通过它们之间的相互调用来实现复杂的逻辑。这就好比不同的类之间要相互交流一样。
如上图所示,用户D通过合约B调用合约接口来调用合约A中的函数,这时tx.origin
的穿透性就体现出来了。msg.sender
只能得到直接调用它的地址(即合约B),得不到用户D的身份,只有tx.origin
才能得到!所以,从这里可能看到,tx.origin
具有的穿透的访问性。
利用tx.origin
的穿透性会产生一定的钓鱼攻击,如下面所示:
pragma solidity >=0.4.22 <0.7.0;
contract UserWallet {
address owner;
constructor() public payable {
owner = msg.sender;
}
function transferTo(address payable _to, uint amount) public {
require(tx.origin == owner); //tx.origin作验证会有漏洞
_to.transfer(amount);
}
}
require(tx.origin == owner);
用它用验证时有一定的漏洞,因为任何人都可以创建一个合约B来试图调用这个合约中的transferTo
方法来攻陷你的钱包!
如果你已经熟悉了tx.origin
的这点特性,倒也不用谈虎色变,它的特性还是给了我们相互调用合约的便利性,使得我们设计的合约复杂度得以提高,能做的事更多。