-
Notifications
You must be signed in to change notification settings - Fork 2
通过全员投票来攻击DAO合约的可能性 #11
Copy link
Copy link
Open
Description
- 修改委员会的操作接口
addCommitteeMember
removeCommitteeMember
setCommittees
最后生成依赖的params列表基本都是一个或者多个number address,加上一个字符串,表示此次的proposal的目的
比如:
setCommittees([addr1, addr2, addr3])
那么生成的params列表如下:
params: [addr1, addr2, addr3, "setCommittees"]
但这个参数列表是可以直接通过其它的投票purposal来直接生成的,比如全员投票
- 全员投票
发起全员投票的接口如下
function fullPropose(
uint duration,
bytes32[] memory params,
uint threshold
) external override returns (uint proposalId)
由于params是外部可以完全指定,那么可以指定成上面的setCommittees的参数列表,然后生成一个proposal
只要这个proposal被投票通过了,那么直接拿这个proposalId,来调用setCommittees,一样可以通过其中_takeResult的检查,因为参数一致,并且结果也是Accept
-
基于上述的情况,几乎所有的操作,包括修改委员会,合约升级,都可以通过全员投票来生成提案并通过,然后基于这个accept的提案,进行对应的操作
-
问题在于,现在全员投票的门槛极低,看fullPropose的接口:
- duration 没有任何限制,所以可以设计一个极短的时间间隔
- params 可以是任意参数列表,包括最后一个操作类型的字符串(很多操作都有附加)
- threshold 最低可以设置10,这个是最大的问题所在
所以基于这个假设,只要有一个人掌握了大约10%的已释放token,就几乎获得了对合约所有的操作权:
可以创建一个duration极小,threshold=10的全员投票,指定好攻击参数,那么就可以自己立刻投票并结算,然后进行目标的攻击操作
通过上述操作,可以升级合约,把所有token都释放到自己名下,从而进一步控制整个DAO组织
- 所以上述的核心,就是需要改进全员投票的设计:
-
duration必须增加最短时间间隔
对于全员投票这种重大事情,时间最少应该是一到两周 -
params 内部需要强制在后面追加一个字符串参数,用作操作类型
也可以强制发起者最后一个字符串参数,并且不可以是特定的敏感操作比如升级合约之类 -
threshold 这个不可以小于50
任何全员投票,都应该满足半数原则,避免类似区块链的50%攻击
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels