主页 > imtoken钱包app下载 > 从 approve 函数看 DeFi

从 approve 函数看 DeFi

imtoken钱包app下载 2023-04-28 07:20:46

DeFi最近很火,尤其是以Compound为代表,非常火。 简单来说,DeFi可以理解为去中心化的P2P借贷。 借贷规则通过智能合约公开透明,资金池也是去中心化的,可以随时存取。 从而避免了传统P2P借贷的诸多弊端。

DeFi 的核心挑战是智能合约的安全性。 一旦某个合约出现重大安全漏洞,很可能所有资产都会被黑客拿走。 虽然合约代码是开源的,一般都经过几家公司的审计(我个人觉得这是在忽悠观众,总觉得代码审计公司是一个很莫名其妙的存在),但并不代表安全。

我仔细查看了 Compound,发现了一些问题。 以USDT借贷为例,借款人的行为是:存入USDT,获得cUSDT。 充值USDT具体步骤为:

调用USDT合约批准cUSDT合约;

调用cUSDT合约的mint方法充值USDT。

有些人可能不理解ERC20的approve方法。 简单说明一下usdt账号里有钱,你(私钥账户或者合约账户)对外转账token不需要审批,但是你需要提前通过transferFrom在别人的合约中转账token。 得到正式认可的。

approve 方法本身也有一些检查,要求每次批准的帐户都是干净的。 下面以USDT合约的approve源码为例:

    /**    * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.    * @param _spender The address which will spend the funds.    * @param _value The amount of tokens to be spent.    */    function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) {
// To change the approve amount you first have to reduce the addresses` // allowance to zero by calling `approve(_spender, 0)` if it is not // already 0 to mitigate the race condition described here: // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 require(!((_value != 0) && (allowed[msg.sender][_spender] != 0)));
allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); }

从require里面可以看出,要么传入_value为0清空someone,要么someone已经0了才能进行新的approve。

比如你同意小明可以转100 USDT,但是小明只转了50 USDT。 此时如果再次批准小明可以转账200 USDT,则操作失败。 这时候你只需要先把小明清零,然后再批准,或者让小明把剩下的50 USDT转过去。

也就是说,ERC20合约有上面关于approve和transferFrom的规则和限制,来保证你的token的安全。

我使用Compound官方Dapp充值USDT。 为了避免上面的麻烦,我发现他们是这样调用的:

Function: approve(address _spender, uint256 _value)
MethodID: 0x095ea7b3[0]: 000000000000000000000000f650c3d88d12db855b8bf7d11be6c55a4e07dcc9[1]: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

天空! 这是什么意思? 这意味着cUSDT合约可以在我的账户中转出任意数量的USDTusdt账号里有钱,但我实际上只实验了10个USDT。

这就是所谓的潜在漏洞,也许今天不会发生的事情。 但是有一天某个合约功能升级了,或者又一个bug被黑客抓到了。 此漏洞可能会导致灾难。 黑客可能会从所有使用过 Compound 合约的账户转移任何资产,因为你允许它转移(见上面的 ffff 表示非常大的数字)。

认为您的帐户安全吗? 被这样的代码执行之后,你以后就有钱了。 你赚了100万个USDT,然后突然发现被人转走了,被cUSDT合约账户转走了,因为cUSDT账户被黑客操纵了。

我已经把这个issue提交给Compound官方了。 虽然这个问题现在不会造成什么问题,但是我们不应该留下这样的隐患。

DeFi 将合约的安全要求提升到了一个全新的高度。 以太坊的智能合约功能就像潘多拉魔盒,非常强大,但也充满了各种危险和陷阱!