热门区块链游戏背后的庞氏骗局与潜在危机
在当今数字经济蓬勃发展的背景下,区块链技术以其独特的去中心化特性吸引了大量投资者和玩家的关注。尤其是区块链游戏,凭借其独特的经济模型和虚拟资产交易,迅速成为市场上的热门话题。然而,随着热度的提升,越来越多的声音开始质疑这些游戏的真实价值,甚至将其视为潜在的庞氏骗局。本文将深入探讨热门区块链游戏的本质,分析其潜在危机,并揭示背后可能隐藏的风险。
区块链游戏的崛起与其背后的经济模型密不可分。许多游戏通过引入数字资产、NFT(非同质化代币)等元素,试图为玩家提供一种全新的游戏体验和收益模式。这种模式吸引了大量玩家参与,他们希望通过游戏获得丰厚的回报。例如,《Axie Infinity》凭借其可爱的小精灵和丰富的游戏玩法,迅速积累了大量用户,成为了区块链游戏的代表。然而,随着玩家数量的激增,其经济模型的可持续性却开始受到质疑。
许多分析师认为,区块链游戏的经济模型往往依赖于新玩家的不断涌入。换句话说,只有不断有新玩家加入,才能维持游戏内的生态平衡。这种模式与传统的庞氏骗局有着惊人的相似之处。在庞氏骗局中,早期投资者的收益是通过后续投资者的资金来支付的,而区块链游戏中的收益也是依赖于新玩家的投入。这就使得游戏的可持续性面临严峻挑战,一旦新玩家的数量下降,整个生态系统就可能崩溃。
此外,区块链游戏的透明性并不意味着安全性。尽管区块链技术本身具有去中心化和不可篡改的特性,但游戏的设计和运营仍然存在诸多不确定性。一些项目可能会在没有足够技术支持的情况下推出,导致玩家的资金安全无法得到保障。例如,某些游戏项目在推出初期声称高回报,吸引了大量投资者。然而,随着时间的推移,游戏的运营方却选择了“跑路”,导致玩家的资金血本无归。这种情况在区块链游戏中屡见不鲜,给玩家带来了巨大的经济损失。
除了资金安全问题,区块链游戏的法律监管也成为了一个重要议题。由于区块链技术的去中心化特性,许多游戏项目往往游走在法律的边缘。一些国家和地区对加密货币和区块链游戏的监管政策尚不明确,导致玩家在参与游戏时面临法律风险。一旦发生纠纷,玩家可能难以通过合法途径维护自己的权益。这种法律风险无疑增加了玩家参与区块链游戏的隐患。
值得注意的是,区块链游戏的盈利模式也引发了广泛的讨论。许多游戏通过出售虚拟物品、NFT等方式获取收益,而这些虚拟资产的价值却往往缺乏实质性的支撑。市场上充斥着大量价格虚高的NFT,许多人在追逐这些虚拟资产时,往往忽视了其背后的价值基础。这种现象不仅可能导致玩家的经济损失,也让整个市场面临泡沫破裂的风险。
在这种背景下,玩家在参与区块链游戏时,需要保持高度警惕。首先,了解游戏的经济模型和盈利模式至关重要。玩家应当仔细研究游戏的白皮书和相关文档,了解其背后的运作机制,以避免因盲目跟风而导致的损失。其次,合理评估投资风险也是必要的。尽管区块链游戏的收益诱人,但高风险往往伴随着高回报,玩家需根据自身的风险承受能力做出明智的投资决策。
在体验区块链游戏的过程中,玩家也应当保持理性。许多人因一时冲动而投入大量资金,最终却发现自己身陷困境。理性的投资心态和对市场的深入理解,才能帮助玩家在这个快速变化的领域中立于不败之地。
此外,区块链游戏的未来发展仍然充满不确定性。虽然目前市场上涌现出大量游戏项目,但其中真正能够持续运营并带给玩家价值的项目并不多。随着监管政策的逐步完善,许多不合规的项目将被淘汰,市场将逐渐回归理性。在这个过程中,玩家需要时刻关注市场动态,把握机会。
在众多区块链游戏中,有些项目通过创新的玩法和良好的社区氛围获得了成功。例如,《The Sandbox》通过构建一个开放的虚拟世界,让玩家能够自由创造和交易资产,吸引了大量用户参与。该项目不仅在技术上取得了突破,在经济模型上也展现出良好的可持续性。这种成功的案例为其他区块链游戏提供了借鉴,展示了创新与合规的重要性。
在总结区块链游戏的现状时,我们不禁要思考:在这个充满机遇与挑战的领域,玩家如何才能更好地保护自己的权益?首先,选择正规的游戏平台和项目是至关重要的。通过对项目团队的背景调查和社区反馈的了解,玩家可以有效降低投资风险。其次,参与游戏时应当保持适度,不盲目追求高回报,合理规划资金投入,避免因一时冲动而造成的损失。
区块链游戏的未来仍需探索,虽然潜在的危机不容小觑,但其中蕴含的机遇也值得关注。随着技术的发展和市场的成熟,区块链游戏有望实现更为健康的生态发展。玩家在参与的同时,也应积极关注行业动态,提升自身的判断力和风险意识。
在这个变幻莫测的数字时代,区块链游戏无疑是一个引人注目的领域。它不仅代表了技术的创新,更是经济模式的一次大胆探索。尽管其中存在诸多风险,但对于勇于尝试的人来说,这也是一个充满可能性的舞台。只有在理性与激情的平衡中,才能在这个新兴领域中立足并获得成功。希望每一位玩家都能在享受游戏的乐趣时,保持对潜在危机的警惕,做出明智的决策。
火爆的区块链游戏确是庞氏骗局,区块链游戏存在哪些潜在危机?如果你在2017年就开始关注以太坊区块链,你应该知道早期的智能合约有庞氏骗局。就好像传统的庞氏骗局,这些游戏的设计是为了能够连续吸引玩家加入,来让这个游戏一直进行下去。虽然这些合约会戛然而止,有些人会发现是因为别的原因导致其结束。本文列举了这类合约可能遭到的攻击。
攻击1:异常障碍
当攻击者利用合约的漏洞返回一个异常错误的时候,异常障碍攻击就会发生。异常障碍会在合约不能成功调用类似address.send()
或者address.call.value()之类的函数时,自动触发。这个错误本身不会被标出,痴肥合约指导去这样做;异常错误不会自动产生。
攻击示例
2016年2月6日,KotET游戏的智能合约部署完成。KotET游戏中,玩家需要发送给合约一些以太币,从而获得“王位”。只要拿到了王位,玩家就会被加到皇庭,并且永远地被记录在区块链上。更重要地是,后来的国王有权去获得新国王的以太币。随着国外数量增多,成为国王的代价也会越来越贵。如果14天过去了,还没有新的继承者,那么王位就会重置,并且游戏也全部重新开始。这个游戏的理想是新的国外会支付一定的费用,来获得王位,同时有新人来不停地进行游戏,这就导致了“庞氏陷阱”。
代码示例
下面是初始KotET合约的简化版代码。需要注意地是返回函数,这会在玩家将msg.value发送到合约的时候触发。返回函数会首先检查国王是否发出了足够的以太币来获得王位。如果没有,这个需求就会被丢弃,然后代码也会返回。如果有足够的以太币,那么现在的国王就获得足够的弥补(认购价格减去服务费),并且发出资金的人就会成为新的国王。然后,新的国王价格会计算出来。
contract KotET {
address public king;
uint public claimPrice = 100;
address owner;
//constructor, assigning ownership
constructor() {
owner = msg.sender;
king = msg.sender;
}
//for contract creator to withdraw commission fees
function sweepCommission(uint amount) {
owner.send(amount);
}
//fallback function
function() {
if (msg.value < claimPrice) revert;
uint compensation = calculateCompensation();
king.send(compensation);
king = msg.sender;
claimPrice = calculateNewPrice();
}
}
KotET合约的漏洞在于使用了address.send(),并且在不成功调用的时候,就不能检查异常错误。就像之前讨论的,address.send() and
address.transfer()都是受限于2300的燃料费。虽然这对于防止重入攻击很有用,但是gas燃料限制会导致发送资金给国王地址失败,如果国王的合约有退回函数需要花费超过2300的gas燃料费。这就是KotET的情况,支付给国王的钱会发送到以太坊mist“合约钱包”,而不是“合约账户”,这就需要更多的gas燃料来完成转账。最终的结果就是不成功的转账,以太币呗退回到国王的账户中,新的国王无法进行加冕,所以这个合约就会一直卡住。
解决方案
KotET能够用以下2个办法解决问题:
1\. 将异常丢弃,那么调用就会恢复-
我们可以通过在函数中添加revert来完成。这会防止合约停止,但是也会需要多余的步骤来启动支付转账。有两种方案,一是让用户自己发出多个支付转账(太中心化),二是实施批量支付确保付款,直到在“头奖”中没有剩余资金。
2\.
使用提现,而不是直接的send调用,合约就可以有结构的,然后玩家就可以让自己的提现失败,而不是合约中剩下的资金。提现算法的唯一不好处,就是这并不是自动化的,需要很多的用户交互。让我们来看看,我们可以如何更新合约,来实施这些变化。
contract KotET {
address public king;
uint public claimPrice = 100;
uint public resolutionFunds
address owner;
mapping (address => uint) creditedFunds;
//constructor, assigning ownership
constructor() {
owner = msg.sender;
king = msg.sender;
}
//for contract creator to withdraw commission fees
function sweepCommission(uint amount) {
owner.send(amount);
}
//for assigning new king and crediting balance
function becomeKing() public payable returns (bool) {
if (msg.value > claimPrice) {
creditedFunds[richest] += msg.value;
king = msg.sender;
return true;
} else {
return false;
}
}
function withdraw() public {
uint amount = creditedFunds[msg.sender];
//zeroing the balance BEFORE sending creditedFunds
//to prevent re-entrancy attacks
pendingWithdrawals[msg.sender] = 0;
msg.sender.transfer(amount);
}
}
现在合约再也不用依赖于退回函数来执行对新的国外进行加冕了,并且可以直接发送资金给下个国王。这个合约现在对于任何的能够攻击合约的回退/重入攻击来说,都是安全的。
攻击2:调用栈攻击
在EIP150使用之前,以太坊虚拟机的调用栈深度为1024.这也就是说,有人可以在自动使用第1024个调用之前,调用某个合约1023次。攻击者最终会达到第1023次合约,导致接下来的调用失败,并且让他们自身来盗窃合约的资金,并且掌控合约。
攻击示例
和KotET这类旁氏游戏类似,用户会发出以太币给合约,来加入游戏。每轮游戏的赢家可以获得奖池的金额。游戏的规则如下:
• 你必须要发送至少1ETH到合约,然后你会被支付10%的利息。
• 如果“政府”(合约)在12小时内没有收到新的资金,最后的人获得所有的奖池,所有人都会失去资金。
• 发送到合约的以太币分配如下:5%给奖池,5%给合约拥有者,90%根据支付顺序,用来支付给发送资金的人
• 当奖池满了(1万以太币),95%的资金会发送给支付者。
•
红利:支付者可以使用推荐链接来邀请别人。如果有朋友对这个合约进行支付,那么邀请人可以获得5%,5%会给到合约拥有者,5%会进入奖池,剩下的85%会用来支付利息。
合约的写入,需要保证用户和他们的资金被记录在2个数组,ddress[] public credAddr 和int[] public
credAmt。这两个数组会在游戏最后重置。GovernMental已经非常成功了,因为数组变得非常大,需要清除他们的燃料费已经超过每个转账能够做到的极限。最终的结局是奖池的永久性冻结,总共有大约1100个以太坊。最后,在2个月后,资金最后还是解冻了,并且发给了调用者。
GovernMental虽然不是被恶意的用户攻击,但是它也是很好的例子,这类灾难会由调用栈攻击产生。这也表面,在进行大型数据库工作的时候,需要格外的小心。
代码
下面是GovernMental智能合约的完整代码,其中还包含简短的变量。我已经在它的整体中包含了真正的合约,因为通过一行行地检查合约可以学到很多,包含这个合约是如何构建的。有人可以看到function
lendGovernmentMoney(),代表了发出资金者的地址,并且需要以太币的数量被重置或者添加到现有数据。需要注意,在同个函数中,资金是如何在合约拥有者以及12个小时结束时的最后发出资金者之间分配的,
credAddr[credAddr.length 1].send(profitFromCrash);
以及corruptElite.send(this.balance)。
contract Government {
// Global Variables
uint32 public lastPaid;
uint public lastTimeOfNewCredit;
uint public profitFromCrash;
address[] public credAddr;
uint[] public credit;
address public corruptElite;
mapping (address => uint) buddies;
uint constant TWELVE_HOURS = 43200;
uint8 public round;
// constructor
constructor() {
profitFromCrash = msg.value;
corruptElite = msg.sender;
lastTimeOfNewCredit = block.timestamp;
}
function lendGovernmentMoney(address buddy) returns (bool) {
uint amount = msg.value;
// check if the system already broke down.
// If 12h no new creditor gives new credit to
// the system it will brake down.
// 12h are on average = 606012/12.5 = 3456
if (lastTimeOfNewCredit + TWELVE_HOURS < block.timestamp)
// Return money to sender
msg.sender.send(amount);
// Sends all contract money to the last creditor
credAddr[credAddr.length – 1].send(profitFromCrash);
corruptElite.send(this.balance);
// Reset contract state
lastPaid = 0;
lastTimeOfNewCredit = block.timestamp;
profitFromCrash = 0;
// this is where the arrays are cleared
credAddr = new address[](0);
credAmt = new uint[](0);
round += 1;
return false;
}
else {
// the system needs to collect at
// least 1% of the profit from a crash to stay alive
if (amount >= 10 18) {
// the System has received fresh money,
// it will survive at leat 12h more
lastTimeOfNewCredit = block.timestamp;
// register the new creditor and his
// amount with 10% interest rate
credAddr.push(msg.sender);
credAmt.push(amount 110 / 100);
// now the money is distributed
// first the corrupt elite grabs 5% — thieves!
corruptElite.send(amount 5/100);
// 5% are going into the economy (they will increase
// the value for the person seeing the crash coming)
if (profitFromCrash < 10000 1018)
profitFromCrash += amount 5/100;
}
// if you have a buddy in the government (and he is
// in the creditor list) he can get 5% of your
// credits. Make a deal with him.
if(buddies[buddy] >= amount) {
buddy.send(amount 5/100);
}
buddies[msg.sender] += amount 110 / 100;
// 90% of money used to pay out old creditors
if (credAmt[lastPaid] <= address(this).balance — profitFromCrash){
credAddr[lastPaid].send(credAmt[lastPaid]);
buddies[credAddr[lastPaid]] -= credAmt[lastPaid];
lastPaid += 1;
}
return true;
}
else {
msg.sender.send(amount);
return false;
}
}
}
// fallback function
function() {
lendGovernmentMoney(0);
}
function totalDebt() returns (uint debt) {
for(uint i=lastPaid; i
debt += credAmt[i];
}
}
function totalPayedOut() returns (uint payout) {
for(uint i=0; i
payout += credAmt[i];
}
}
// donate funds to “the government”
function investInTheSystem() {
profitFromCrash += msg.value;
}
// From time to time the corrupt elite
// inherits it’s power to the next generation
function inheritToNextGeneration(address nextGeneration) {
if (msg.sender == corruptElite) {
corruptElite = nextGeneration;
}
}
function getCreditorAddresses() returns (address[]) {
return credAddr;
}
function getCreditorAmounts() returns (uint[]) {
return credAmt;
}
}
我们假设攻击者写了如下的合约,进行恶意攻击contract Government {}。
contract attackGov {
function attackGov (address target, uint count) {
if (0<= count && count<1023) {
this.attackGov.gas(gasleft() – 2000)(target, count+1);
}
else {
attackGov(target).lendGovernmentMoney;
}
}
攻击者调用了contract attackGov{}
函数,来进行调用直到栈的大小为1023.当栈达到1022.lendGovernmentMoney()函数就会在第1023个栈上执行。因为第1024个调用已经失败了,并且
send() 函数不会检查返回的代码,合约的credAddr[credAddr.length —
1].send(profitFromCrash)代码也会失效。合约之后就会重置,而且下一轮已经可以开始。因为支付失败了,合约现在就会从最后一轮中获得奖池,在下轮结束后,合约拥有者就会获得全部的资金,corruptElite.send(this.balance)。
解决方案
那么我们怎么才能避免全栈攻击呢?很幸运地是,EIP150标准进行了更新,使得栈调用的深度达到1024是几乎不可能的事情。规则中写到,子调用不能花费主调用的63/64燃料费用。为了达到接近栈调用的极限,攻击者需要花费难以想象地费用,所以很少有人会这么做。
另个方面,对于大量数据的处理方法包含:
• 写合约的时候,要在多个转账中分散数据清理工作,而不是集中在某个,或者
• 通过让用户能够独立处理数据集的方式来写入合约。
攻击3- 不可更改的管理器缺陷
什么使得智能合约这么特别?他们是不可更改的。什么造就了智能合约的噩梦?他们是不可更改的。现在,很遗憾的结论是,当在写智能合约时,很多时候会出现错误。在激活合约之前,对整体的函数,参数和合约结构进行审核,是非常必要的。
如果在以太坊历史上,有智能合约是因为整体架构出问题,而最终失败的,毫无疑问就是Rubixi。Rubixi是另一个旁氏游戏,其中玩家需要发送以太币到合约中,并且可以获得更多的以太币。但是,在Rubixi开发的过程中,拥有者随意更改了合约名称,但是并没有检车任何的不一致性。毋庸置疑,Rubixi远不能称为“成功”。
攻击示例
由于Solidity
v0.4.24算法,合约的管理器功能是construct()。但是,在Rubixi合约创建的时候,管理器功能被以太坊虚拟机和合约共享了同个名字。Rubixi的问题在于当合约中部署了管理器的名称为function
DynamicPyramid() ,而不是function
Rubixi(),,这就意味着Rubixi最初的名字叫“DynamicPyramid”。由于这个不一致性,合约在创建的时候,并没有指定拥有者,所以城堡的钥匙被抢走了。任何人都能够定义他们自己为合约的拥有者,然后获得参与者加入的合约费用。
代码示例
如果我们把合约代码的前几行拿出来,你就会发现合约名称和指定管理器函数的区别。
contract Rubixi {
//Declare variables for storage critical to contract
uint private balance = 0;
uint private collectedFees = 0;
uint private feePercent = 10;
uint private pyramidMultiplier = 300;
uint private payoutOrder = 0;
address private creator;
//Sets creator
function DynamicPyramid() {
creator = msg.sender;
}
现在你应该明白了,攻击者需要做的,就是创建合约的名字为function DynamicPyramid(),
然后获得拥有权。然后,攻击者可以调用function
collectAllFees(),然后提现。虽然这个攻击已经非常直接了,Rubixi是个很好的例子,告诉我们一定要彻底地检查合约。
contract extractRubixi {
address owner;
Rubixi r = Rubixi(0xe82…);
constructor() public {
owner=msg.sender;
}
function setAndGrab() public {
r.DynamicPyramid();
r.collectAllFees();
}
}
解决方案
很幸运地是,Solidity语言已经更新了,以至于管理器功能被定义为constructor()
,而不是contractName()。我们可以从中学到的是,多次检查我们的合约代码,并且保证你在整个开发过程中,保持一致性。没有什么比部署一个无法改变的合约,但是发现其中有问题,更糟糕了。
以上就是火爆的区块链游戏确是庞氏骗局,区块链游戏存在哪些潜在危机?的详细介绍,庞氏区块链游戏或许已经是过去的事情,但是George
Santayana曾经说过,“那些不能从历史中学到教训的人,还会重复错误。”通过从KotET,
GovernMental和Rubixi这类错误中学习,我们可以防止自己在错误的道路上越走越远。
免责声明:网站所有文字、图片、视频、音频等资料均来自互联网,不代表本站赞同其观点,内容仅提供用户参考,若因此产生任何纠纷,本站概不负责,如有侵权联系本站删除!