为什么 0x 不像看起来那么无需信任

DEX(去中心化交易所,decentralized exchange)的主要优势之一就是它们既无需信任又不用托管。可以使用户无需将资金移交给中心化实体(校注:托管账户)里放一段时间,就能进行交易。0x 也是因无需信任而出名的 DEX 之一,实际上大多数基于 0x 的中继者宣传的正是这个。但是只要我们稍微深入调查,就可以看出 0x 并不像表面看上去那么无需信任,而且很多人可能实际并没有意识到这一点。

0x 协议中使得无需信任的承诺不成立的问题在于该协议里的一个基本合约,叫做代币转移代理服务(TokenTransferProxy),该合约主要负责将代币从一个地址转移到另一个地址。该解决方案就是为了确保在每次交易所更新时,用户不用再重新设置他们的代币转账额度,这从根本上提高了整体用户体验。

- 0x 架构图详细说明了代理服务是如何进行代币转移的。-

目前的代理服务机制使得其所有者可以注册一个新的授权地址,该新地址便有权通过代理服务来转移代币。而这就是问题所在,代理合约所有者能够授权任意他们喜欢的地址,这可能导致所有者授权的是一个恶意地址,而该地址随后就将所有资金额度转移到他们自己的钱包里。

0x 是如何缓解这个问题的

0x 并没解决问题,但确实缓解了问题。这是通过使多重签名合约成为代理服务的所有者来实现的。交易执行前需要通过一个时间锁。这使得用户在看到团队(校注:即授权地址)正试图进行一项有可能是恶意的交易时,他们能将额度设置为 0。但是这个解决方案也有自己的缺点,因为该方案是建立在几个不一定准确的假设之上的:

  1. 假设所有人都会积极地检查多重签名合约,扫描恶意交易。
  2. 假定在发生恶意行为时,用户将很快能得到通知。

所以虽然这能使攻击发生的概率降低,但并不能完全消除攻击。它仍会允许恶意行动者在锁定时间之后,获得经由代理合约授权的(额度降低后的)代币的全部保管权。

有一点要注意的是,如果发现了一个严重错误,那这个解决方案也会使得升级交易所合同变得更难,因为时间锁仍然适用。

0x 团队目前实现的多重签名是一个过渡选项,以后将使用社区治理模型。但是如果不重建代理服务,这里就仍有个缺点,用户可能会自动转向使用一个他们根本不知道的新交易所。

正如尼克·约翰逊(Nick Johnson)提到的,值得指出的是社区治理模型可能比目前的多重签名更 ;很容易就能想象一个这样的情境:有人提出了一个建议,将所有非阴谋者的代币分发给的所有阴谋者。

此外,如果一个恶意地址获批,那用户为保护其资金的开销就会呈线性增长,因为他们需要变更所有他们已批准给代理的代币的额度。这对很多用户来说可能是困难的,尤其是一旦中继者开始出现在你可以用与以德(etherdelta)运作方式相似的方法进行代币交易的地方。

一个更简单的解决方案

由于这是一个我必须解决的问题,我花了很多时间试图想出一个既有用又不会产生太多开销的方案。当然所执行的任何解决方案都将产生少量开销,但是我认为如果这能保证资金更安全的话,大部分用户都将接受这笔开销。

那么这样的解决方案是怎样的呢?很简单,我们需要一个双重审批机制,首先代理服务合同的所有者授权一个新地址,然后用户再次授权那个地址来转移其代币。这不仅考虑到了与 0x 协议旨在达到的灵活性,而且也让用户可以选择他们的代币要通过哪个版本的交易所进行交易。除此之外,这个解决方案也消除了对允许快速更新的时间锁的需求了。

pragma solidity 0.4.11;

contract TokenTransferProxy is Ownable {

    modifier onlyAuthorized {
        require(authorized[msg.sender]);
        _;
    }

    modifier onlyApprovedByUser(address user) {
        require(approvedByUser[user][msg.sender]);
        _;
    }

    mapping (address => bool) public authorized;

    mapping (address => mapping (address => bool) public approvedByUser;

    function transferFrom(address token, address from, address to, uint value)
        public
        onlyAuthorized
        onlyApprovedByUser(from)
        returns (bool)
    {
        return Token(token).transferFrom(from, to, value);
    }

    function approve(address spender) public {
        require(authorized[spender]);
        authorizedByUser[msg.sender][spender] = true;
    }

    function unapprove(address spender) public {
        authorizedByUser[msg.sender][spender] = false;
    }
}

-双重审批机制范例-

虽然这个问题不 严重,但绝对是个值得关注的有趣的问题。它不是一个在审计中会被发现的安全问题,因为更确切地说,它是一个信任问题。我也质疑这个问题是如何在无需保管的背景上产生影响的,因为理论上说,保管权是可以获取的。这个问题可能不大,甚至可能很多人都不认为这是个问题,但是可以这么说,用户需要更加信任 0x 团队,而其他 DEX 可能没有这个问题。

披露:我目前正与一个创建 DEXY(一个去中心化交易所)的团队共事。但是我很乐意帮助 0x 团队来执行这个问题的临时解决方案。我相信,信任问题会以一种开放中立的方式得以解决。


链接: https://medium.com/@decanus/why-0x-is-not-trustless-as-it-may-seem-b807929b6e3e

猜你喜欢

转载自blog.csdn.net/shangsongwww/article/details/90136900