流行的区块链游戏确实是一个庞氏骗局。区块链奥运会潜在的危机是什么?_币百科_转赚网

流行的区块链游戏确实是一个庞氏骗局。区块链奥运会潜在的危机是什么?

转赚网 0 0

流行的区块链游戏确实是一个庞氏骗局。区块链奥运会潜在的危机是什么?如果你在2017年开始关注以太坊区块链,你应该知道早期的智能合约有庞氏骗局。就像传统的庞氏骗局。这些游戏旨在吸引玩家加入,以便让游戏继续下去。虽然这些合同会戛然而止,但有些人会发现是因为其他原因而结束的。本文列举了对此类契约可能的攻击。

攻击#1:异常障碍

当攻击者利用合同中的漏洞返回异常错误时,就会发生异常障碍攻击。。当合同能够';t成功调用address.send()或address.call.value()之类的函数。错误本身不会被标记,胖契约引导它这样做;异常错误不会自动生成。

攻击示例

2016年2月6日,KotET游戏智能合约部署完成。在KotET游戏中,玩家需要向契约中发送一些飘渺的硬币来获得"王座"。只要拿到皇位,玩家就会被加进朝廷。,并被永远记录在区块链上。更重要的是,后来的国王有权得到新国王';以太坊。随着国外数量的增加,成为王者的代价会越来越贵。如果14天过去了,没有新的继任者,那么王位将被重置,游戏将重新开始。。这个游戏的理想是新的外国要支付一定的费用才能获得王位,同时不断有新人继续玩这个游戏,这就导致了庞氏陷阱。

代码示例

以下是初始KotET契约代码的简化版本。。注意,当玩家向契约发送msg.value时,会触发返回功能。返回函数将首先检查国王是否发出了足够的以太坊来获得王位。否则,需求将被丢弃,代码将返回。如果有足够的以太币。那么现任国王将获得足够的补偿(认购价减去服务费),发行资金的人将成为新国王。然后,计算新的地王价格。

合同KotET{

地址公王;

uint公开索赔价格=100;

地址所有者;

//constructor,assigningownership

constructor(){

owner=msg.sender;

king=msg.sender;

[XY001]}[XY002][XY001]//Forthecontractortowithdrawthecommission[XY002]

函数佣金(单位金额){

所有者。发送(金额);

}

//回退函数

function(){

if(msg。valueclaimPrice)还原;

uint补偿=计算补偿();king.send(补偿);

king=msg。发件人;

claimPrice=calculatenewprice();

}

}

kotetcontract的漏洞在于它使用了address.send(),当调用不成功时,它可以';t检查异常错误。如前所述。,地址。发送()和地址。转移()都受限于2300的油费。虽然这对于防止再入攻击很有用,但气体燃料的限制会导致向国王发送资金的失败';的地址。如果国王';的合同有退款功能,它将花费2300多气体燃料。这就是KotET的情况。付给国王的钱将被送到&";合同钱包"以太坊而不是"合同账户",这需要更多的气体燃料来完成转移。。最后的结果是转移不成功,以太坊还给国王';的账户,所以新国王可以';不加冕,所以契约永远卡。

解决方案

KotET可以通过以下两种方式解决问题:

1。丢弃异常,调用将继续——我们可以通过在函数中添加revert来实现这一点。这将防止合同停止,但也需要额外的步骤来启动支付转移。有两种方案。一种是让用户自己发出多次支付转账(过于集中)。二是实行批量支付,保证支付到"一等奖"。

2。用提现代替直接发送调用,可以结构化合约,然后玩家可以让自己提现失败,代替合约中的剩余资金。。现金提取算法的唯一缺点是它不是自动的,需要大量的用户交互。让';让我们看看如何更新合同来实现这些变化。

合同KotET{

addressmaleking;

uintpublicclaimprice=100;

CorporatePublicResolutionFund

地址所有者;

映射(地址=

uint)贷记资金;

//constructor,assigningownership

constructor(){

owner=msg.sender;

king=msg.sender;

[XY001]}[XY002][XY001]//Forthecontractortowithdrawthecommission[XY002]

函数佣金(单位金额){

所有者。发送(金额);

}

//Usedtoallocatethenewkingandcreditbalance

函数becomeKing()公共应付款返回(bool){

if(msg。值

claimPrice){

贷记资金[最富有]=消息。价值;

king=msg。发件人;

返回true

}else{

返回false

}

}

函数撤回()公共{

uintamount=creditedfunds[msg.sender];

//Clearthebalancebeforesendingthecreditedfunds.

//防止重入攻击

等待撤销。发件人]=0;

msg.sender.transfer(金额);

}

}

现在契约不再依赖返回函数来执行新外国的加冕,可以直接给下一任国王发资金。。该契约现在是安全的,可以抵御任何可能攻击该契约的后退/再入攻击。

攻击#2:调用栈攻击

在使用EIP150之前,以太坊虚拟机的调用栈深度是1024。也就是说,有人可以调用1023次合同,然后自动使用第1024次调用。攻击者最终会到达第1023个契约,导致下一次调用失败,让他们自己窃取契约的资金,控制契约。

攻击示例

类似于KotET等庞氏游戏,用户会向合约发送飘渺币来加入游戏。每轮游戏的获胜者可以获得奖池的金额。游戏规则如下:

你必须至少发送1个ETH到契约,然后你会得到10%的利息。

如果"政府"(合约)12小时内没有收到新的资金,最后一个人将赢得所有奖池,所有人都将失去自己的资金。

送合约的以太坊分配如下:奖池5%,合约主5%。按照支付顺序,90%支付给发送资金的人

当奖池满(10000等)时,95%的资金发送给支付人。[XY002][XY001]奖励:付款人可以使用推荐链接邀请其他人。。如果朋友为这个合同付费,邀请人可以获得5%,5%给合同所有人,5%进入奖池,剩下的85%用于支付利息。

合约的书写需要保证用户及其资金记录在两个数组中。,address[]publiccredaddr和int[]publiccredAmt。这两个数组会在游戏结束时重置。政府已经非常成功,因为阵列已经变得非常大。,需要清除他们的燃料费用已经超过了每次转移的限制。最后的结局是奖池永久冻结,共1100以太币左右。最后,过了两个月,资金终于解冻,发给了打电话的人。

政府虽然没有受到恶意用户的攻击,但也是一个很好的例子。这种灾难将由调用栈攻击引起。这也表明,在处理大型数据库时,您需要格外小心。

代码

以下是政府智能合同的完整代码,其中也包含短变量。我已经完整地包含了真实的合同,因为通过逐行检查合同,我可以学到很多东西,包括合同是如何构造的。。有些人可以看到函数lendGovernmentMoney(),它代表资金发送方的地址,以及需要重置或添加到现有数据中的以太坊数量。应该注意的是,在相同的功能中12小时结束时,合同所有者和最后一个发行者之间的资金是如何分配的?,credAddr[credAddr.length1].发送(profitfromrash);以及腐败的生活。发(这个。平衡)。

契约政府{

//全局变量

uint32publiclastpayed;

uintpubliclastimeofnewcredit;

unit公众从崩溃中获利;

address[]公共信用地址;

单位[]公共信用;

处理公共腐败;

map(address=

uint)friends;

uintconstanttwelvehours=43200;

uint8公共回合;

//constructor

constructor(){

profitfromrash=msg。价值;

损坏lite=msg。发件人;

lastimeofnewcredit=block。时间戳;

}

函数lendGovernmentMoney(地址好友)返回(bool){

uintamount=msg。价值;

//Checkwhetherthesystemhascrashed.

//Ifthereisnonewcreditorwithin12hours,

//Thesystemwillstoprunning.Average

//12h=60*60*12/12.5=3456

.

if(lastimeofnewcredit十二小时块。时间戳)

//向发送方退款

msg.sender.send(amount);

//Sendallcontractmoneytothelastcreditor

信用地址。长度-1].发送(profitfromrash);

瓦楞原纸。发(这个。平衡);

//重置合同状态

lastpayed=0;

lastimeofnewcredit=block。时间戳;

profitfromrash=0;

//Thisiswherethearrayiscleared

credAddr=新地址[](0);

信用金额=新单位[](0);

round=1;

返回错误的

}

else{

//Thesystemneedstobecollectedat

.

//If(amount

=10**18){

,getatleast1%profitfromthecollapsetosurvive

.

//Thesystemhasreceivednewmoney,

//Itcansurviveforatleast12hours

.

lastimeofnewcredit=block。时间戳;

//注册新的债权人及其

//利率10%的金额

credaddr。推(msg。发件人);

credAmt.push(amount*110/100);

//Nowthemoneyhasbeensent

//First,thecorruptelitetakes5%-thieves!

corruptelite.send(amount*5/100);

//5%willentertheeconomy(theywillincrease

//Valueofpeoplewhoseethecollapsecoming]

If(profitfromcrash10000*10**18)

profitfromrash=金额*5/100;

}

//Ifyouhaveabuddyinthegovernment(heis

//inthecreditorlistcanget5%ofyour

//creditor'srights.Makeadealwithhim.

if(buddies[buddy]

=amount){

buddy。发送(金额*5/100);

}

Friend[msg.sender]=amount*110/100;

//90%ofthefundsareusedtorepaytheoldcreditors.

if(信用金额[上次付款人]

信用地址[上次付款人]).发送(信用金额[上次付款]);

好友[信用地址[上次付款]]-=信用金额[上次付款];

lastpayed=1;

}

返回真实的

}

else{

msg。发件人。发送(金额);

返回false

}

}

}

//fallbackfunction

function(){

lendgovermentmoney(0);

}

函数债务总额()返回(uint债务){

for(uintI=最后支付;我

债务=信用额[I];

}

}

函数totalPayedOut()返回(uint支出){

for(uintI=0;我

payment=creditamount[i];

}

}

//direction'Government'

Donation

functioninvestInTheSystem(){

profitfromscrash=msg。价值;

}

//Thecorruptelite

//Fromtimetotime,thepowerispassedontothenextgeneration

函数inheritToNextGeneration(地址下一代){

if(消息。sender==corruptElite){

corruptElite=下一代;

}

}

函数getCreditorAddresses()returns(address[]){

returncredAddr;

}

函数getCreditorAmounts()returns(uint[]){

返回信用金额;

}

}

让';假设攻击者编写了下面的契约来恶意攻击契约政府{}。合同攻击政府{

functionattackGov(addresstarget,uintcount){

if(0

.

这个。攻击政府燃气(燃气左()-2000)(目标,计数1);

}

else{

attackGov(target)LendOvernmentmoney

}

}

Theattackercalledthecontractattackgovernment{}function.,直到堆栈的大小为1023。当堆栈达到1022时,将在第1023个堆栈上执行1022.lendGovernmentMoney()函数。因为第1024次呼叫失败了。而send()函数不会检查返回的代码,而credaddr[credaddr。长度-1]。发送(profitfromcrash)合同的代码也将无效。合同到期后会重置。下一轮已经开始了。因为支付失败,合同现在会得到上一轮的奖池,下一轮结束后,合同主会得到所有资金,corruptlite.send(this.balance)。

解决方案

那么如何才能避免全栈攻击呢?好在EIP150标准已经更新,堆栈调用深度几乎不可能达到1024。按照规则,分呼不能花掉主呼63/64的油费。。为了达到堆栈调用的极限,攻击者需要花费难以想象的开销,所以很少有人会这么做。

另一方面,对于大量数据的处理方法包括:

写合同时,数据清理工作要分散在多次传输中。,而不是专注于一个,或者

通过使用户能够独立地处理数据集来编写合同。

攻击#3——不可撤销的经理缺陷

是什么让智能合约如此特殊?它们是不可改变的。。是什么创造了智能合约的噩梦?它们是不可改变的。现在,很遗憾的是,在编写智能合同时,经常会出现错误。在激活合同之前,有必要审查整体功能、参数和合同结构。

如果在以太坊的历史上,有一个因为整体架构问题最终失败的智能合约,毫无疑问就是Rubixi。Rubixi是另一种庞氏游戏,玩家需要将以太币送入合约中,获得更多以太币。但是Rubixi开发过程中,车主随意更改合同名称,但查车没有不一致。毫无疑问,卢比西远远称不上"成功>;

攻击示例

由于Solidityv0.4.24算法,契约的管理器函数是construct()。但是,在创建Rubixi契约时,管理器功能是由以太坊虚拟机和同名契约共享的。。Rubixi的问题是,当契约中部署的管理器被命名为functionDynamicPyramid()而不是functionRubixi()时,这意味着卢比西';的原名是"动态金字塔"。由于这种不一致,在创建合同时没有指定所有者,所以城堡的钥匙被拿走了。任何人都可以将自己定义为合同的所有者。,然后获得参与者加入的签约费。

代码示例

如果我们取出合约代码的前几行,你会发现合约名称和指定的经理职能之间的区别。

合同约定

//Declarethatthestoragevariableuintprivatebalance=0;iscrucialtothecontract

;

uint私人收取的费用=0;

uint私人费用百分比=10;

uint私有金字塔乘数=300;

单位私人付款人=0;

privatecreatorofaddress;

//Setthecreator

functionDynamicPyramid(){

creator=msg.sender;

}

现在你应该明白了,攻击者需要做的是创建一个名为functionDynamicPyramid()的契约,然后获得所有权。。然后,攻击者可以集体调用函数Feeds()并提取现金。虽然这种攻击很直接,但是Rubixi就是一个很好的例子,告诉我们一定要彻底检查合同。

合同提取卢比Xi{

地址所有者;

Rubixir=Rubixi(0xe82.);

构造函数()public{

owner=msg。发件人;

}

函数setAndGrab()public{

r.动态金字塔();

r.collectallfees();

}

}

解决方案

很幸运地是Solidity语言已经更新,因此管理器函数被定义为constructor()而不是contractName()。我们从中可以学到的是多次检查我们的合同代码,并确保你在整个开发过程中,以保持一致性。没有什么比部署一个不可变更的契约,发现它有问题更糟糕的了。

以上是流行的区块链游戏确实是一个庞氏骗局。区块链奥运会的潜在危机是什么?对…的详细介绍庞氏区块链游戏可能已经成为过去,但乔治桑塔亚纳曾经说过那些能';不吸取历史教训就会重蹈覆辙。。"通过从KotET,GovernMental和Rubixi等错误中吸取教训,我们可以防止自己在错误的道路上越走越远。

相关内容

标签: 契约中 发送资金 合约中

流行的区块链游戏确实是一个庞氏骗局。区块链奥运会潜在的危机是什么?文档下载: PDF DOC TXT