区块链安全防护论文翻译:Bartoletti, Massimo, et al. "Dissecting Ponzi schemes on Ethereum: identification, analysis, and impact." Future Generation Computer Systems 102 (2020): 259-277.
摘要:庞氏骗局是一种以高额利润为诱饵的金融欺诈。实际上,只有新用户加入了庞氏骗局,用户才能得到回报:因此,庞氏骗局在用户停止加入后不久就会崩溃。庞氏骗局起源于150年前的线下世界,从那时起就开始向数字世界迁移,最早出现在网络上,最近又出现在比特币等加密货币上。像以太坊这样的智能合约平台为骗子提供了一个新的机会,他们现在有可能制造“值得信赖的”欺诈,仍然让用户赔钱,但至少可以保证“正确”执行。我们对以太坊的庞氏骗局进行了全面的调查,从不同的角度分析了它们的行为及其影响。
比特币 [1, 2] 的出现催生了一种新的货币兑换方式,允许安全和(几乎)匿名的资金转移,而无需可信机构的中介。通过适当地结合几种技术,这已经成为可能,其中包括数字签名方案、中等难度的“工作量证明”难题,以及区块链的想法,一种记录所有货币交易的不可变公共分类账,并由对等方维护通过分布式共识协议建立对等网络。比特币普及后不久,它就开始引起犯罪分子的兴趣,他们渴望找到新的方式来转移货币而不会被调查人员和监督机构追踪 [3]。最近,庞氏骗局 [4]——一种至少在 150 年前起源于线下世界的经典欺诈——已经来到了数字世界,首先是在网络上 [5],最近也在比特币 [6] 上。庞氏骗局通常伪装成“高收益”投资计划。用户通过投资一些钱进入该计划。允许赚钱的实际条件取决于该计划的具体规则,但所有庞氏骗局都有一个共同点,即要赎回其投资,必须让新用户进入该计划。庞氏骗局的更权威定义来自美国证券交易委员会 (SEC):
“庞氏骗局是一种投资欺诈,涉及从新投资者提供的资金中向现有投资者支付所谓的回报。庞氏骗局的组织者经常通过承诺将资金投资于声称能产生高回报、风险很小或没有风险的机会来吸引新的投资者。由于合法收益很少或根本没有,庞氏骗局需要新投资者源源不断的资金才能继续。庞氏骗局不可避免地会崩溃,最常见的情况是难以招募新的投资者,或者大量投资者要求返还资金。”
通常,庞氏骗局的投资机制会产生一个金字塔形的用户拓扑结构,在顶层有方案的发起人,在`+1层有补偿`层用户投资的用户。这个计划最终会崩溃,因为在某个时刻,随着新投资者的数量在这个金字塔的数量上呈指数级增长,他们将不可能再找到新的投资者。因此,金字塔顶层的用户将获得金钱,而底层的用户只会失去投资。尽管许多投资者完全意识到这些骗局的欺诈性质,以及这些骗局在许多国家是非法的,庞氏骗局仍然吸引了大量资金。一项研究[6]估计,仅仅从2013年9月到2014年9月这段时间,通过比特币运作的庞氏骗局就聚集了700多万美元42。
“智能的”庞氏骗局。智能合约的传播,即计算机程序的正确执行在不依赖可信机构的情况下自动执行[7],为欺诈者创造了新的机会。实际上,将庞氏骗局作为智能合约来实施有几个吸引人的特点:1.庞氏骗局的发起人可以保持匿名,因为创建合约和从合约中取款不需要透露发起人的身份;2.由于智能合约是“不可更改”和“不可阻挡的”,因此任何中央当局(特别是任何法院)都无法终止该计划的执行,或恢复其效力以退还受害者。这对于运行在无权限区块链上的智能合约尤其如此,这些区块链由对等节点网络控制。3.由于智能合约的守则是公开的、不可更改的,而且其执行是自动执行的,投资者可能会产生虚假的诚信感。这可能导致投资者相信,所有者不能利用他们的资金,该计划将永远运行,他们有公平的概率获得所宣布的利益。
所有这些功能都是由多种因素共同作用而实现的,其中智能合同平台的发展[8],将匿名性和合同持久性作为主要卖点,以及这些技术是非常新的,仍然生活在法律制度的灰色地带[9,10]。了解“智能”庞氏骗局的行为对于制定适当的干预政策至关重要。为此,必须分析欺诈的各个方面,回答几个问题:涉及多少受害者?投资多少钱?欺诈的时间演变和寿命是什么?什么样的用户会卷入这些欺诈?我们能在庞氏骗局的执行过程中,甚至在开始之前,识别出它们吗?调查这些问题将有助于预防这种欺诈行为。
贡献。这篇论文是对以太坊庞氏骗局的首次全面调查 [11],这是迄今为止最著名的智能合约平台。我们构建了一个庞氏骗局的数据集,并从各个角度对其进行了分析。更具体地说,我们的贡献可以总结如下:
• 一套确定智能合约何时实施庞氏骗局的标准。我们的标准只考虑了合约实现的收集和分配资金的逻辑,而忽略了外部因素,例如计划的广告或游戏化方式。
• 部署在以太坊上的庞氏骗局公共数据集(goo.gl/CvdxBp),与我们的分类标准一致,该数据集是通过检查合约源代码构建的。我们从源代码可在区块链浏览器上获得的合约开始,在其中找到 138 个庞氏骗局。我们通过在区块链中搜索字节码与已归类为庞氏骗局的合约高度相似的合约,将这个集合扩展到 184 个,并且有通过手动检查反编译代码来排除假阴性。
•一个开源工具(github.com/blockchain-unica/ethereum-ponzi),该工具从以太坊区块链中提取在我们数据集中的庞氏骗局的所有交易,记录所有进出的货币流动,并计算分析结果在本文中提出。
• 对我们集合中合约源代码的分析(第 4 节)。我们发现大多数合约都有一些共同的模式,其中许多是通过对现有合约的微小变化而获得的。我们设计了庞氏骗局的粗略分类,根据用于重新分配支出的模式对它们进行分类。我们表明,每个类别中的计划都未能实现资金的公平分配。此外,我们在分析的合约中发现了几个安全漏洞,攻击者可能会利用这些漏洞窃取资金。
• 衡量庞氏骗局的经济影响,量化通过它们交换的整体价值(第 5 节)。
• 衡量庞氏骗局用户的收益和损失(第 6 节)。我们专注于前 10 个方案(交易数量最多的方案),以及我们从具有最有趣特征(用户数量、交易数量或交换的以太币数量)的方案中选择的另外 13 个方案。在大多数情况下,我们观察到庞氏骗局的典型模式:少数用户获得了很多收益,而大多数用户则只是赔了钱。
• 在不同观点下分析庞氏骗局的时间行为(第 7 节)。首先,我们调查庞氏骗局的生命周期,这是一个预测计划何时崩溃的重要指标。然后,我们分析了合同流入和流出之间随时间变化的相关性。最后,我们衡量每月的交易量。
• 衡量与计划之间的支付不平等程度(第 8 节)。该指标可能会揭示诈骗者如何选择受害者:公平的付款分配意味着该计划由支付少量资金的大量受害者提供;相反,分配不均通常意味着该计划从少数投入大量资金的“大鱼”中获利。
• 用户可以遵循的一套指导方针,以保护自己免受庞氏骗局的侵害(第 9 节)。
以太坊简述
以太坊 [11] 是一个去中心化的虚拟机,它可以执行用图灵完备字节码语言编写的程序(称为合约),称为 EVM [12]。每个合约都有一个永久存储来保存数据,以及一组可以由用户或其他合约调用的函数。用户和合约可以拥有一种加密货币(称为以太币,简称 ETH),并向用户或其他合约发送/接收以太币。用户可以将交易发送到以太坊网络,以便:(i) 创建新合约; (ii) 调用合同的功能; (iii) 将以太币转移给合约或其他用户。用户发送的所有交易,称为外部交易,都记录在一个公共的、只能追加的数据结构——区块链上。合约收到外部交易后,可以触发一些内部交易,这些交易没有明确记录在区块链上,但仍然会影响用户和其他合约的余额。由于交易可以转移资金,因此确保正确执行交易至关重要。为此,以太坊不依赖受信任的中央机构:相反,每笔交易都由分散的节点网络处理。存在一种用于解决失配(例如由于故障或攻击而导致)的共识协议,该协议当前基于“工作量证明”难题。共识协议的安全性取决于以下事实:遵循协议比尝试对其进行攻击更为方便。实际上,节点会因正确执行协议所需的所有计算而获得经济激励。只要不是有人控制了整个以太坊网络的很大一部分计算能力,都能保证合约的执行是正确的 [13]。
抽象地说,智能合约可以被看作是面向对象语言中的对象,由字段和函数组成。用户可以通过向以太坊节点发送合适的交易来调用函数。交易必须包括执行费(对于矿工),并且可能包括从调用者到合约的以太币转移。我们通过一个小例子(图 1 中的 AWallet)来说明合约,它实现了一个与所有者关联的个人钱包。我们没有直接将其编程为 EVM 字节码,而是使用 Solidity表示,这是一种类似于 Javascript 的编程语言,可编译为 EVM 字节码 [14]。合约可以从其他用户那里接收以太币,其所有者可以通过功能支付将(部分)以太币发送给其他用户。哈希表outflow记录了它汇款到的所有地址,并将总转账金额与每个地址相关联。哈希表inflow记录了它收到钱的所有地址。收到的所有以太币都由合约持有。它的数量会自动记录在余额中:这是一个特殊的变量,程序员无法更改。当合约收到以太币时,它还会执行一个没有名称的特殊函数,称为fallback函数。
第 6 行的函数 AWallet 是一个构造函数,在创建合约时只运行一次。函数 pay 从合约发送金额 wei (1 wei = 10−18ETH) 给接收者。在第 9 行,如果调用者 (msg.sender) 不是所有者,或者调用时将一些以太 (msg.value) 附加到调用并转移到合约,则合约将引发异常。由于异常会引发回滚,因此该以太币将返回给调用者(但调用者会失去gas)。在第 10 行,如果所需数量的以太币不可用,则call终止;在这种情况下,不需要通过异常恢复状态。在第 11 行,合约更新outflow,然后将以太币转移给接收者。在第 12 行用于此目的的函数 send 提出了一些条件,例如如果收件人是智能合约地址,则可能会失败。当没有其他函数被调用时,第16行的fallback函数在接收到ether时触发。在这种情况下,fallback函数只是更新流入注册表inflow。在这两种情况下,当接收以太币时和发送时,合约的以太币总量(存储在变量this.balance中)都会自动更新。
3.收集庞氏骗局
在本节中,我们建立了一套标准,将合同归类为庞氏骗局。然后我们描述了构造庞氏骗局集合和提取相关交易的方法。
3.1.什么是“智能”庞氏骗局?
本文首先阐明了什么是庞氏骗局。我们所做的第一个关键选择是限制作为智能合约或“智能”Ponzis实现的方案[15]。这种选择排除了仅将以太坊用作支付手段(或仅用于广告)的庞氏骗局。这些骗局包括一些众所周知的“高收益”投资项目,其中许多项目被列入BadBitcoin4维护的黑名单。我们选择从我们的分析中排除这类骗局,因为几乎不可能检索到有关他们使用的以太坊地址的任何信息(如果有的话)。在图2中,我们提出了四个要求来确定合约是否是庞氏骗局,完全基于合约代码中实现的逻辑。当一个合约满足所有四个条件时,我们将其归类为庞氏骗局。
• R1 要求合约将资金分配给投资者,即通过向合约发送一些资金来加入合约的用户。这个要求没有对用于分配资金的逻辑施加任何限制,因此仅 R1 不足以将合约归类为庞氏骗局:例如,赌博游戏、彩票、保险和债券,它们同样满足 R1。然而,R1 排除了为用户提供某种资产的合约,但没有实现分发这些资金的逻辑,相反,这些资产通过外部市场进行交换,如加密货币交易所。例如,ERC-20 代币 [16] 的大多数实现就是这种情况,其中包括初始代币发行 [17]。
•R2要求合约收集的资金仅来自投资者。这排除了分配给投资者的资金来自外部来源的情况,例如支付“智能”债券利息的银行,或使用自有资金支付赌注的博彩公司。
• R3 要求每个投资者都获利,并且前提是新投资者继续向合约汇款。连同前两个要求,这意味着用户只能通过其他用户的投资来获利。请注意,赌博游戏,博彩和彩票违反了R3:在那里,即使有恒定的投资流量,也不能保证不会出现一个不幸的用户一直没有获得任何利润(例如,他总是没有中彩)。
• R4 要求失去投资的风险随着加入计划的时间而增加。这也是现实世界中庞氏骗局的一个标志性特征:在某个时刻,很难找到新的投资者,因此没有人再获利,并且该计划崩溃了。
与第1节引用的美国证券交易委员会对庞氏骗局的定义相比,R1和R2的要求共同反映了这样一个事实,即庞氏骗局“涉及从新投资者出资的基金中向现有投资者支付声称的回报”;R3对应于这样一个事实:它们“需要新投资者源源不断的资金流才能继续”;R4意味着它们“不可避免地崩溃,最常见的情况是当招募新投资者变得困难时”。请注意,我们的要求没有抓住这样一个事实:“庞氏骗局组织者经常通过承诺将资金投资于声称能产生高回报、几乎没有风险或没有风险的机会来吸引新的投资者”。这是因为,根据设计,我们的需求完全基于合约中实现的逻辑,而广告则是在合约代码之外完成的。在区分庞氏骗局与伪庞氏骗局时,R4排除了一些有时被认为是庞氏骗局的合约,即使分配投资的庞氏机制在合约中没有硬编码。例如,实施加密收藏市场的合同就是这种情况——最著名的例子是CryptoKitties,一种玩家可以繁殖和交易虚拟猫的游戏,作为ERC-721代币实施。事实上,加密猫合约违反了R4,因为一个幸运的用户,无论何时加入合约,都可能繁殖出一只稀有的猫,并通过出售来获利。
出于类似的原因,R4 排除了 Fomo3D,这是一种有时被指出为庞氏骗局的游戏。 Fomo3D 作为一种彩票游戏,在每一轮中,玩家都可以购买一些“钥匙”,并且该轮中的最后一个买家赢得大奖。每当购买钥匙时,到回合结束的截止日期都会延长,出售钥匙的收益分为两部分:一部分添加到头奖中,另一部分则在回合参与者之间共享。彩票机制将用户加入该计划的时间与其失去投资的风险分离,因此违反了 R4。
要求 R4 也排除了另一个所谓的庞氏骗局 PoWH3D。 PoWH3D 实现了代币及其交换:合约机制确保代币的价值在人们购买时增加,而在人们出售时减少;此外,每笔代币交易都有 10% 的费用。投资者可以通过三种方式赚钱:以高于支付的价格出售代币;通过邀请新投资者购买代币(在这种情况下,他们获得受邀者的费用);并通过接收(未受邀)投资者支付的费用(这些费用在所有代币持有者之间分配)。这违反了要求 R4,因为即使投资晚了,例如在停滞时期,也不一定意味着更大的投资损失风险,因为该机制确保了此时代币的价值较低。
我们注意到,即使合约没有明确实现庞氏骗局(因此,违反了我们的一些要求),它也可能会诱发与庞氏骗局非常相似的行为。 例如,CryptoKitties 及其追随者催生了一个加密收藏品市场,这通常被比作“郁金香狂热”,这是 1600 年代的一个巨大的投机泡沫。 CryptoKitties 的火爆几乎造成了 2017 年以太坊网络的拥堵; 部分虚拟猫售价超过170KUSD,市场处理的虚拟猫销售额超过1200万美元[18]。
3.2.建立庞氏骗局数据集
为了构建庞氏骗局的数据集,我们首先检索在以太坊区块链上发布的合约的 Solidity 代码。由于区块链只存储 EVM 字节码,为此我们依赖区块链浏览器 Etherscan,它允许开发人员上传其合约的 Solidity 代码,并验证他们的编译是否与区块链上的 EVM 代码匹配。通过手动检查这些合约的 Solidity 代码,我们检测到 138 个满足图 2 中所有要求的合约,因此可以归类为庞氏骗局。由于此样本中的所有合同都相对较小(< 120 LOC,包括评论),因此人工检查足够准确以检查要求。作为进一步检查,对于所有这些合约,我们研究了它们用于重新分配货币的模式,这是我们在第 4 节中进行分类的基础。为了安全起见(即避免误报),我们没有包括收集那些过于复杂而无法确定是否满足要求的合同。我们执行第二个搜索阶段来扩大我们的数据集。更具体地说,我们在以太坊区块链中搜索字节码与我们最初收集的某些庞氏骗局相似的合约。这是通过以下步骤完成的:
1.我们使用蒙特卡罗算法来估计以太坊区块链上两个任意EVM合约之间的归一化Levenshtein距离[20](NLD)。NLD是两个字符串之间相似性的标准度量。两个字符串之间的非标准化Levenshtein距离度量一个字符串在转换第二个字符串时必须更改的字符数(例如,“Ponzi”和“Banzai”之间的距离是3)。规范化版本是一个度量,它的值是一个介于0(完全相等)和1(完全不相等)之间的实数。经过这些计算,我们计算出从区块链下载的两个随机EVM合同之间的NLD为0.79。
2.我们计算初始样本中的合约与以太坊区块链上所有合约之间的NLD。我们将样本中某个合约的NLD小于0.35的合约视为潜在的庞氏骗局。两个值0.35和0.79相距足够远,这样确保低误报率,即初始样本的NLD低于0.35的合同,但它们还不一定是庞氏骗局。这一搜索结果是55个潜在的新庞氏骗局,不包括在我们最初收集的138份合同中。3.我们对第二阶段发现的55个合约的EVM字节码应用在线的反编译器,并手动将获得的Solidity代码与第一阶段发现的相应庞氏方案的Solidity代码进行比较。在46个案例中,我们发现合约代码之间存在实质性的匹配,因此我们将这些合约添加到我们的集合中。
最后,我们得到了一个184个庞氏骗局的数据集,我们可以在goo.gl/CvdxBp上找到这个数据集(摘录见第5节的表1)。我们强调,我们的数据集并不包括多年来在以太坊上发表的所有庞氏骗局。例如,合约PonziUnlimited7显然是一个Ponzi方案,但是它不能立即检测其逻辑是否满足图2中的要求,因此我们不将其包含在我们的集合中。
3.3. 提取交易记录
对于数据集中的每个庞氏骗局,我们从以太坊区块链收集其所有交易(外部和内部)。更具体地说,对于每个事务,我们记录以下数据:(i)封闭块的编号(ii)在区块链上发布的日期(iii)发起人的地址(iv)接收人的地址(v) 交易转移的以太币金额(vi)记录事务执行是否导致错误的布尔值(vii)一个布尔值,指示事务是外部的还是内部的。我们为此开发的脚本利用了Etherscan以太坊开发人员APIs9,可以在github.com/blockchain-unica/Ethereum-ponzi上找到它们。
4.庞氏骗局剖析
在本节中,我们将分析庞氏骗局的源代码,以了解它们的行为,并找出不同骗局之间的相似之处。然后我们讨论在分析的合约中发现的一些安全问题。4.1. 庞氏骗局的分类基于对第3.2节中执行的合约源代码的分析,我们设计了一个庞氏骗局的粗略分类,它根据用于重新分配货币的模式对它们进行分类。我们的分类法由四个类别组成,它们的原型代表如图3到6 所示。
树形庞氏方案使用树的数据结构来进行用户之间的排序。每当用户加入该方案时,她必须将另一个用户指定为邀请者,该用户将成为她的父节点。如果没有指定邀请者,则父节点将是根节点,即方案的所有者。在大多数方案中,要投资的金额由用户选择,并且该金额有一个下限。新用户的钱在她的邀请者或邀请者的邀请者等等(即树形结构下的“祖先”)之间分配,逻辑是距离她越近邀请者获得的份额越大。由于节点的子节点数量没有限制,节点的子节点(和后代)越多,它赚的钱就越多。
我们在图 3 中展示了这种原型方案。要加入该计划,用户必须发送一些钱,并且必须指明将成为其父节点的邀请者。如果金额太低(第 15 行),或者如果用户已经存在(第 16 行),或者如果邀请者不存在(第 17 行),则拒绝该用户;否则,她将被插入到树中(第 19 行)。用户加入后,她的投资将在其“祖先”之间共享(第 25-29 行),在每个级别将金额减半。在这个方案中,用户无法预见自己将获得多少:这取决于她能够邀请多少用户,以及他们将投资多少。唯一能保证盈利的是所有者,即树的根节点。这种方案的例子是 Etheramid 和 DynamicPyramid。
链式庞氏方案是树型方案的特例,树的每个节点只有一个子节点(因此,用户之间的排序是线性的)。这类方案通常将投资乘以一个预定义的常数因子,该常数对于所有用户都是相等的。该方案开始按照用户到达的顺序,一次一个地全额偿还用户:所有新的投资都被收集起来,直到获得到期的金额。在那一刻,合约在一个单一的时刻发送支付回来,并转移到链中的下一个用户。投资金额可以是固定的,也可以是自由的,或者有一个下限。通常,合同所有人从每项投资中收取费用。
我们在图4中展示了一个典型的链式方案,它使每个用户的投资增加了一倍。为了加入该方案,用户向合同发送msg.amount数量的 ETH,从而触发fallback函数(第14行)。合同要求最低收费1次:如果msg.amount低于此最低收费,则拒绝用户(第15行);否则,她的地址将添加到数组中(第17行),数组长度将递增1。合约所有人获得0%的投资(第22行)。用剩余的资金,合约试图偿还以前的用户。如果余额足以支付指数支付给用户,合同将支付用户的投资乘以2(第25行)。之后,合同会尝试向下一个用户付款,以此类推,直到余额足够为止。在这个方案中,只要方案继续运行,用户就可以准确地预测自己将获得多少收益;这个数额与她所投资的成比例。这类的例子有Doubler、dianaem和ZeroPonzi。
瀑布式方案类似于用户订购的链式方案,但在货币分配逻辑上有所不同。每一笔新的投资都沿着投资者的链条倾泻而出,这样每个人都可以分得一杯羹。由于采用先到先得的逻辑,并且分配总是从链的开头开始,因此链上的用户很可能永远得不到任何钱。我们在图 5 中展示了这种原型方案,入场费为 1ETH(第 19 行),所有者收取 10% 的费用(第 24 行),并且每轮支付用户投资的 6%。支付逻辑从第 27 行开始。如果合约余额足以支付数组中的第一个用户(位置 pos = 0),则合约将其原始投资的 6% 发送给该用户(第 29-30 行)。之后,合约尝试向数组中的下一个用户付款,依此类推,直到余额用完。在后续投资中,数组再次迭代,仍然从第一个用户开始。为确保所有用户都能收到付款(与要求 R3 一致),新用户的投资必须与用户数量成正比。这种方案的例子是TreasureChest 和PiggyBank。
移交方案是链式方案的一个例子,其入场费由合同确定,每有新的投资者加入,入场费就会增加。新投资者的通行费全额支付给前一位以及合约所有者:由于入场费增加,前一位投资者立即获利。在每个时刻,只有一位投资者在收款,一旦她获得付款,她便将这一特权移交给下一位用户。图 6 显示了一个原型示例。要加入该方案,用户必须至少向合约发送price数量的 ETH,从而触发第 11 行的回退功能。合约将这笔款项转发给前用户,减去保留的费用在合同中(第 13 行)。然后,记录新用户的地址(第 14 行),价格翻倍(第 15 行)。合约所有者可以通过调用sweepCommission 取出资金。在移交方案中,用户在进行投资时就知道他们将获得多少收益。然而,由于收费随着计划的进行而增加,后来的用户更有可能赔钱(与要求 R4 一致)。切换方案的典型代表是 KingOfTheEtherThrone。
(未更完,待续)