火星链 火星链
Ctrl+D收藏火星链

COM:Compound代码更新事故

作者:

时间:1900/1/1 0:00:00

"有些事,发生在别人身上是故事,发生在自己身上就成了事故"

代码的升级是一件痛苦且脆弱的事。尤其是在本就十分复杂的代码大厦上,任何微小的改动,都可能因为某些边界条件的疏忽而造成崩塌,Compound最近就遇到了这事

Compound是一个老牌的去中心化借贷平台

Q1: 为什么要有借贷这回事儿?

在区块链上,所有的资产都是代币化的。我们看好一个项目,但是却没有这个项目发行的代币。这时最简单的方法就是去交易所用手里有的币来换。但是,如果我们又不舍得自己手里的币,该怎么办呢。这时可以去借,抵押品便是我们拥有的币。如果这个项目涨了,获得收益的同时,还可以赎回曾经抵押的币。

交易会发生所有权的转移,而借贷不发生所有权的转移,只是被暂时锁在合约中

同时,由于借贷的引入,我们可以操控更大的资金敞口,实现杠杆交易...

Q2:Compound的运作流程?

和AMM类似,在区块链上实现自动化的借贷,首先要做的便是吸引资金(流动性),而用户所以能将钱存在一个平台,必然是受到利益的驱使。AMM通过交易费来激励用户添加流动性,而借贷平台的手段便是借款利息

由于存在借贷这一需求,总会有人愿意付出利息来借币。而有了利息的激励,也有人愿意将闲钱拿来提供流动性。此外,借贷平台通过利率模型参数的动态调整,可以维持整个系统的供给平衡与风险

Q3: 如何与Compound交互?

用户与Compound的交互接口主要是CToken/CEther合约(这些合约本身就是一种代币), CToken 相当于 Compound这一平台的"入场券"。通过向不同CToken合约质押其底层代币(underlying token)便可以获得相应的CToken

这一操作,表现在代码层面就是?ctoken.mint(amount),比方说:我手里有1000个ETH,便可以调用cEth.mint(1000)?来向cEth池中 "注入流动性"

Crypto.com 聘请 Bittrex 前高管 Kwon Park 担任董事总经理:5月27日消息,总部位于新加坡的加密公司 Crypto.com 宣布聘请交易所 Bittrex 前高管 Kwon Park 担任董事总经理,以帮助指导该公司的 Web3 战略,Kwon Park 曾担任 Bittrex的首席战略官和业务发展总监,他还是几家 Bittrex 附属公司的董事会成员,在加入 Bittrex 和 Crypto.com 之前,Park 在美国政府事务公司 Delta Strategy Group 担任了四年多的法律顾问。Kwon 涉足多个行业,包括监管合规、执法、业务战略和政策问题等多个领域。在新职位上,Kwon Park 将领导 Crypto.com 的合作伙伴关系发展,并尝试规划新的商机。[2022/5/27 3:44:40]

要注意的是,cToken和底层代币并不是1:1的兑换关系,当蛋糕越做越大时,cToken所能换出的底层代币也就越多。这和LP token的类似,利息便是以这种形式来发放的

那有了cToken以后,我们可以做什么呢?

最简单的便是借钱,因为cToken代表用户质押在Compound的资产,因此可以通过"过抵押"的方式来借出Compound拥有的代币。Compound会先计算用户拥有所有cToken的价值(可能来自于不同的池),根据抵押率来计算用户的流动性(Liquidity)

表现在代码层面就是?ctoken.borrow(amount),比方说:我通过?ceth.mint(1000)?质押了 1000 个 ETH,如果我想借 Dai 的话,需要调用?cDai.borrow(x)?这里的 x 最多价值750 ETH (抵押率75%)

这些都是以美元计算的,再根据Oracle来换算成不同的Token数量

而Comptroller这一合约是一个中间层,它所做的事情,便是交互前的一些计算与验证工作,类似银行的审计员。比方说:张三借了多少钱,欠了多少钱,这小子又来借1000个ETH还能不能借给他

Composable Finance赢得波卡第7次平行链插槽拍卖:1月13日消息,Polkadot网络第7次平行链插槽Auction的蜡烛期结束。由于在整个蜡烛期内,Composable Finance都处于领先状态。所以“摇骰子”结束之后,在23:35,Composable以 锁定6,027,000 DOT赢得Polkadot第7次平行链插槽Auction。

由于Polkadot的第二轮插槽Auction是每两周进行一次,所以第8次Auction将在2022年1月21日凌晨2点 开启。目前在所有活跃的Crowdloan活动中,Centrifuge收集的DOT最多,排在后面的还有 Interlay、HydraDX、Nodle和Litentry。

此外,第二批Auction的所有6个获胜者都将在2022年3月11日接入Polkadot中继链并上线主网[2022/1/14 8:48:07]

表现在代码层面就是:getHypotheticalAccountLiquidityInternal()、borrowAllowed()、mintAllowed()?...

Q4: COMP代币与Compound的关系?

COMP代币是Compound发行的平台代币,可以用于管理。因为Compound采用DAO的治理模式。对Compound所有的操作,都需要通过投票来决定,提案(proposals)通过后由一个特权合约来执行写在提案中的操作。通过COMP可以获得投票的权重

详情见:https://compound.finance/governance

当然只能用来投票显然还是缺少些吸引力的,COMP本质上就是Compound发行的股票,拥有更多的COMP,可以享受更优的利率,随着Compound的发展,COMP带来的价值也会越来越大,因此COMP值钱(目前 $300 左右)

同时,为了激励用户使用Compound,无论是向Compound提供流动性,还是从Compound借出资产,都会获得一定的COMP奖励,这些奖励以区块为单位计算(划重点:这里与本次事件相关)

事故1代码地址:0x75442Ac771a7243433e033F3F8EaB2631e22938f

Nifty's推出社交NFT平台Niftys.com,同步推出勒布朗·詹姆斯主演的NFT电影:Nifty's推出旨在将数字藏品带给主流受众的NFT社交平台Niftys.com,并与华纳兄弟合作推出了一系列限量版NFT,包括了由NBA巨星勒布朗·詹姆斯主演,并加入了华纳早期推出的卡通系列LooneyTunes卡通人物的电影《SpaceJam:ANewLegacy》。该电影将于美国各大影院与HBOMax上映。华纳兄弟将为在Niftys.com上注册的用户赠送限量版NFT,用户可在平台上的《SpaceJam:ANewLegacy》展览馆里领取,用户在社交媒体进行分享将再获得一份NFT。[2021/7/12 0:46:11]

事情的起因是这样的:

2021年9月31日,Compound DAO出现这样一条提案(Proposals 62: https://compound.finance/governance/proposals/62):

该提案提出更新 Comptroller 合约以修复一些 Bug

这里我们可以看出 Bug 和 CompSpeed 有关,CompSpeed 这个变量代表是每个区块可以挖出的 COMP 数量

这里以 mint 为例简单介绍Bug的原理:

ctoken 的 mint 函数的调用链为:mint → mintInternal → mintFresh

可以看到,在?mintFresh?中,会先调用 Comptroller 的?mintAllowed?函数,再更新用户 ctoken 的余额

而 mintAllowed 中,会先调用 updateCompSupplyIndex,再调用 distributeSupplierComp

Asproex(阿波罗)于9月3日正式上线DeFi热门币种DOT、LINK、LEND、COMP:据官方消息,2020年9月3日,Asproex(阿波罗)正式上线DeFi热门币种DOT、LINK、LEND、COMP ,并于当日开通DOT/USDT、LINK/USDT、LEND/USDT、COMP/USDT交易对。开放充提时间:9月3日17:00;开放交易时间:9月3日18:00。2020年,DeFi流动性挖矿盛行,Asproex(阿波罗)已率先切入“DeFi”生态赛道,后续将为用户甄选更优质的DeFi项目,让用户安全快捷参与DeFi浪潮。

Asproex(阿波罗)作为首家离岸银行控股持牌交易平台,也是一家涵盖CTO企业通证上市的交易平台,持有5国牌照,为全球中小微企业提供融资难的解决方案,助力数字化上市。[2020/9/3]

前者会更新借贷池的奖励状态,主要是 compSupplyState

这一结构体中,block字段记录了更新时的区块号,index字段记录的是更新时的奖励指数

**什么是奖励指数(index)呢?**这是一个随时间不断累加的值,其公式为

表示的是一个借贷池,随着时间的推移,向每个cToken分发的COMP数量。因此,其差值可以简单理解为,这段时间内一个cToken可以获得的COMP数量

接下来我们看另一个函数:distributeSupplierComp。这个函数的作用,就是将用户可以获得的COMP数记录到compAccrued[supplier]?中:

研究人员:COMP价值被高估至少5倍:金色财经报道,根据Delta Exchange的研究,Compound代币COMP的价值至少被高估了5倍,其10亿美元资产中有超过88%借给了流动性挖矿者。根据Compound的统计,在被借的10亿美元资产中,超过8亿美元是DAI,而目前全部DAI总计为2亿美元。7月1日,仅3000万DAI被借。USDC也发生了类似的情况,其价值在一夜之间从3000万美元跃升至约1.8亿美元。DAI和USDC价值的突然跃升可以用来估计Compound的订单上有多少是合法使用的,有多少是由于流动性挖矿。USDC和DAI总价值前后相差8.81亿美元,这是由积极的流动性矿工增加的。Compound的真实账面价值不应超过1.19亿美元,其中一部分可能仍由积极程度较低的yield farmers(即通过为DeFi提供流动性赚取收益的人)组成。[2020/7/14]

每次有用户来和 Compound 交互,都会触发全局的奖励指数 compSupplyState 更新

与此同时,在上面的函数中,我们可以看到,用户会先从 compSupplierIndex 中取得上次的 compSupplyState 保存在临时变量 supplierIndex 中,接下来更新 compSupplyState

这里要区分好 supplyIndex 和 supplierIndex,前者表示当前的奖励指数,后者表示用户上次交互时的奖励指数

而两个时间点全局奖励指数的差 * 用户拥有的 cToken 数量,就是这段时间奖励给该用户的 COMP 数量

现在看起来都是一起正常,岁月静好,直到...

有一天Compound调用了?setCompSpeed:

因为一个Market的CompSpeed是可以设置为0(表示暂停发放COMP奖励),所以存在这样一种情况:

我们先把一个市场的CompSpeed设置为0

过了一段时间后又想要重新开启COMP奖励,这时就会调用setCompSpeed设置compSpeed为一个非零值

这会发生什么呢?

很显然,合约会走到?else if (compSpeed != 0)?这个分支。我们来看这个分支中有两个if判断(以第一个为例):if (compSupplyState[address(cToken)].index == 0 && compSupplyState[address(cToken)].block == 0)。其作用是:为一个未初始化的市场,初始化奖励指数(index)和区块号(block)

问题1:这里可以想想:未初始化的市场(index = 0 && block = 0)和被暂停的市场(index = 0)一样吗?

先别急,我们重新来看?updateCompSupplyIndex:

这里我们可以回答一下问题1:未初始化的市场和暂停的市场是不一样的,暂停的市场虽然index = 0,但是block会一直更新!

因此,当我们为一个暂停的市场重新设置compSpeed时:index不会被初始化!

[注]Compound假设奖励指数初始值为CompInitialIndex = 1e36

这会有什么影响呢?

我们再来看下奖励分发函数?distributeSupplierComp:

看出来了吗?用户自己的奖励指数(supplierIndex)会被初始化为compInitialIndex (1e36),而市场的奖励指数(supplyIndex)由于上面的问题为0,这就导致:Double memory deltaIndex = sub_(supplyIndex=0, supplierIndex=1e36)?出现下溢!

事故2代码地址:0x374abb8ce19a73f2c4efad642bda76c797f19233

Compound方面对事故1的修复如下:

Compound很显然意识到了问题出在setCompSpeed函数只考虑了"未初始化市场",而没有考虑"暂停的市场"

因此,新代码中,增加了函数:_initializeMarket?这个函数会在添加新市场时调用。也就是说,只要添加新市场,就会初始化其奖励指数为compInitialIndex

但是既然市场奖励指数初始化为了compInitialIndex,那用户的奖励指数呢?这是我们来看新的distributeSupplierComp?函数:

因为很多市场的 CompSpeed 为0,所以其奖励指数会停留在 compInitialIndex(1e36) 这个值,此时如果调用这个函数会发生什么?

很显然上图中的if被绕过了,这意味着没有初始化用户的奖励指数(supplierIndex),而市场的奖励指数(supplyIndex)是compInitialIndex

所以deltaIndex本应是(compInitialIndex - compInitialIndex = 0)就变成了 (compInitialIndex - 0 = 1e36)

哦豁,出大问题。可是,奖励不仅仅依赖于这个deltaIndex,还需要用户有cToken(supplierTokens)

是否存在这一情况呢?显然是存在的,如果用户在合约更新之前就做了mint操作,其supplierIndex=0,但是手里是存在cToken的。当合约更新后,用户再次调用该函数,就可以获得 1e36 * ctoken.balanceOf(user) 数量的COMP奖励

通过compStateIndex = compInitialIndex,可以很容易的得到受到影响的市场有:

我们以一位涉事者为例:0xa7b95d2a2d10028cc4450e453151181cbcac74fc

我们看到在这笔交易中:0x6416ed016c39ffa23694a70d8a386c613f005be18aa0048ded8094f6165e7308

其Claim大量的COMP代币,通过调试我们发现,在调用distribute时:

由于事故2,获得的deltaIndex = 1e36,而恰恰该用户之前有cToken

从而可以薅到大量的COMP:

最终,事情的解决方式也很简单

在接下来一条提案中(Proposal 63),暂停COMP奖励,但是最终被取消掉了

最新的一条提案,更新了Comptroller合约,该提案目前仍在排队中:

最新的合约里,distributeSupplierComp函数中初始化用户奖励指数的判断条件修改如下:

Compound作为借贷平台的老大哥,本次的事件有些唏嘘

虽然Compound软硬兼施,一方面承诺拿出10%的白帽奖励给获得"意外之财"的用户,一方面又寻求法律的手段。但是,事故终究已经发生

当我们不断探索区块链,不断追求更高的APY,追求项目快速落地。是否还有人记得,区块链最基本的一条原则就是:覆水难收!

启示如下:

代码部署上链前一定要做好充足的审计与测试工作

使用代理模式时,更新逻辑合约要保证一致性,注意是否会对原来的Storage产生影响

DAO模式虽然减少了中心化的风险,但是应对紧急情况时的反应迟缓问题

即使是大公司依然会有犯错误的可能,借鉴其他项目代码时要注意检查

参考

Comptroller: compSpeed bug:?https://www.comp.xyz/t/comptroller-compspeed-bug/2111

github issue:?https://github.com/compound-finance/compound-protocol/pull/144/commits/f6d717bb78bef0c9851ad672f7b9aa1d90b0f00a

标签:COMCOMPOMPINDEXINCOME价格comp币价格FOMP价格BasketDAO DeFi Index

芝麻开门交易所热门资讯
MMI:重磅 | 新加坡正式开放加密交易牌照申请 限时仅一个月

摘要2019/12/20新加坡金管局宣布将于2020年1月28日起正式实施《支付服务法案》(Payment Service Act).

1900/1/1 0:00:00
COI:金色趋势丨BTC市值占比突破 对市场有何意义?

看下BTC市值占整个加密货币比率走势,去年10月开始BTC从1万美金启动主升浪,其余主流币包括山寨币弱于BTC上涨,BTC一马当先市值占比一路拉升,在今年1月初涨至顶峰.

1900/1/1 0:00:00
CTO:2021年两会区块链相关提案汇总:数字人民币试点成热门

3月11日,随着十三届全国人大四次会议闭幕,2021年全国“两会”正式落下帷幕。“两会”中,区块链相关话题引来不少代表、委员的热议,小编根据公开资料中整理了一些今年两会中产生热议的区块链相关提案.

1900/1/1 0:00:00
DEFI:晚间必读5篇 | DOT 本月多笔大额解锁 价格会跌吗?

1.DeFi数据周报:一图总览DeFi龙头和黑马项目金色财经报道,据欧科云链OKLink数据显示,本周涨幅前三的币种为:RAMP日涨幅104.7%.

1900/1/1 0:00:00
CRV:Ve(3,3) = Curve ^ Olympus

1月26日,由Yearn Finance创始人AC发起的新项目Ve(3,3)宣布即将上线,并更名为Solidly。从命名上看Ve(3,3)可以被拆解为两部分:Ve&(3,3).

1900/1/1 0:00:00
CEB:Libra将面临欧盟的反垄断审查 联盟模式玩得转吗?

据彭博社报道,欧盟反垄断监管机构已经在探讨对Facebook于今年6月公布的Libra数字货币项目进行审查.

1900/1/1 0:00:00