国庆长假快进尾声,今天把GUSD的合约代码仔细看了,得出一个非常惊人的结论:
GUSD已经抛弃了Custodian
第三方托管合约,变成由Gemini自由控制的中心化的增发工具。
通过仔细阅读GUSD复杂的合约,笔者发现,GUSD的主合约:ERC20Impl
合约的custodian
(托管账户)从原先的Custodian
合约变成了PrintingLimiter
合约,导致增发等重要的操作可以不受Custodian
合约控制,无需第三方托管账户操作。
事实上,GUSD的Custodian
合约有史以来只操作了4次,见:https://etherscan.io/address/0x9a7b5f6e453d0cda978163cb4a9a88367250a52d
每次只是授权了confirmImplChange
方法(该方法的Method Id为0x8181b029
)
下面,我们来进一步查看究竟GUSD是如何实现增发的。
首先,我们来看该代币地址:https://etherscan.io/token/0x056fd409e1d7a124bd7017459dfea2f387b6d5cd
显示余额为:957525.96
GUSD(2018年10月6日16点左右)
在列表中随意找一个From
为0x0000...
的Tx交易记录,点击后,查看交易详情:
https://etherscan.io/tx/0xd204a0e54d63a27de84074d48491016892a933ddce9cf7debf36747f1af96460。
可以看出,该币交易增发了157,882.70
个GUSD。
通过查询交易的Event Logs
,可以看出,这笔交易完成后收到了三个事件:
-
ERC20Impl
合约的requestPrint
方法,发送PrintingLocked
事件; -
ERC20Impl
合约的confirmPrint
方法,发送PrintingConfirmed
事件; -
ERC20Proxy
合约的发送代币,并释放Transfer
事件。
而以上事件全部是由PrintLimiter
合约中的limitedPrint
方法统一控制的。
在PrintLimiter
合约中找到limitedPrint
函数,源码如下:
function limitedPrint(address _receiver, uint256 _value) public onlyLimitedPrinter {
uint256 totalSupply = erc20Impl.totalSupply();
uint256 newTotalSupply = totalSupply + _value;
require(newTotalSupply >= totalSupply);
require(newTotalSupply <= totalSupplyCeiling);
erc20Impl.confirmPrint(erc20Impl.requestPrint(_receiver, _value));
}
看最后一句erc20Impl.confirmPrint(erc20Impl.requestPrint(_receiver, _value));
,是指拥有增发权限的用户,直接从requestPrint()
方法中获取lockId
,并交给confirmPrint()
方法作为参数,确认其增发行为。
按道理,应该在提出增发申请,即requestPrint()
后,由资金托管方Custodian
进行多签授权,然后执行确认增发命令,即confirmPrint()
。但实际上,这里全部省略了。
我们再来看看到底谁拥有增发权限的账户呢?也即是上面代码中的modifier
方法onlyLimitedPrinter
中的条件到底是什么?
看代码:
modifier onlyLimitedPrinter {
require(msg.sender == limitedPrinter);
_;
}
即只要发送改指令的以太坊账号msg.sender
等于limitedPrinter
就行了,而limitedPrinter
是在部署PrintLimiter
合约时的构造函数中设定的。因此,只要部署该合约时指定某个以太坊账户拥有增发权限即可。
那么,究竟谁是拥有这个增发权限的超级账号呢?
我们通过查询前面的交易记录:https://etherscan.io/tx/0xd204a0e54d63a27de84074d48491016892a933ddce9cf7debf36747f1af96460
找到From
账户,就是给合约发送指令的msg.sender
的地址:0xd24400ae8bfebb18ca49be86258a3c749cf46853
。
那这个地址又是什么呢?
让我们打开ERC20Impl
合约的详情:https://etherscan.io/address/0x6704ba24b8640BCcEe6BF2fd276a6a1b8EdF4Ade#readContract
可以发现,以上地址就是sweeper
。
查看ERC20Impl
合约的构造函数可以发现,这个sweeper
地址是在部署ERC20Impl
合约时设定的参数。通过etherscan.io
查询,发现这个地址就是Gemini
交易所地址。
由此,一个看似复杂,公平,受第三方监管的稳定币GUSD
,其实增发完全被一个交易所账户控制着。增发过程很容易,只要执行PrintLimiter
合约中的limitedPrint
方法即可。所谓的托管方Custodian
只是一个幌子罢了。
那么,GUSD的所有代码是不是都是摆设呢?也不是,在Custodian
合约中,已经把所有逻辑写的很清楚了。其基本逻辑是:
如果某人需要执行某个更改(如增发),首先需要提出一个申请,获取lockId
,然后第三方监管机构执行Custodian
合约中的requestUnlock
函数,提出解锁申请。第三方监管机构中有权限的几个账户中的两个对该申请审核,然后通过多签,确定是否批准解锁。如果批准,则执行人拥有执行该方法的权限(如增发)。
以上逻辑,其实建立了一套:发行-监管
的模式,该模式适用于几乎所有金融应用场景。
根据笔者对GUSD合约的理解,只要将上面的limitPrint
方法的modifier
方法改为onlyCustodian
即可实现增发行为的第三方监管,如下:
function limitedPrint(address _receiver, uint256 _value) public onlyCustodian {
uint256 totalSupply = erc20Impl.totalSupply();
uint256 newTotalSupply = totalSupply + _value;
require(newTotalSupply >= totalSupply);
require(newTotalSupply <= totalSupplyCeiling);
erc20Impl.confirmPrint(erc20Impl.requestPrint(_receiver, _value));
}
网友评论