调用不受信任的外部合约可能会引发一系列意外的风险和错误。外部调用可能在其合约和它所依赖的其他合约内执行恶意代码。因此,每一个外部调用都会有潜在的安全威胁,尽可能的从你的智能合约内移除外部调用。当无法完全去除外部调用时,可以使用这一章节其他部分提供的建议来尽量减少风险。
someAddress.call.value()()
将会发送指定数量的Ether并且触发对应代码的执行。被调用的外部智能合约代码将享有所有剩余的gas,通过这种方式转账是很容易有可重入漏洞的,非常 不安全。
使用send()
或transfer()
可以通过制定gas值来预防可重入, 但是这样做可能会导致在和合约调用fallback函数时出现问题,由于gas可能不足,而合约的fallback函数执行至少需要2,300 gas消耗。
需要注意的是使用send()
或transfer()
进行转账并不能保证该智能合约本身重入安全,它仅仅只保证了这次转账操作时重入安全的。
如果你选择使用底层方法,一定要检查返回值来对可能的错误进行处理。
calls,如果这个ExternalContract
是不受信任的都应该假设存在恶意代码。即使ExternalContract
不包含恶意代码,但它所调用的其他合约代码可能会包含恶意代码。一个具体的危险例子便是恶意代码可能会劫持控制流程导致竞态。(浏览获取更多关于这个问题的讨论)
外部调用可能会有意或无意的失败。为了最小化这些外部调用失败带来的损失,通常好的做法是将外部调用函数与其余代码隔离,最终是由收款发起方负责发起调用该函数。这种做法对付款操作尤为重要,比如让用户自己撤回资产而不是直接发送给他们。(译者注:事先设置需要付给某一方的资产的值,表明接收方可以从当前账户撤回资金的额度,然后由接收方调用当前合约提现函数完成转账)。(这种方法同时也避免了造成
当你自己的函数调用外部合约时,你的变量、方法、合约接口命名应该表明和他们可能是不安全的。
当断言条件不满足时将触发断言保护 -- 比如不变的属性发生了变化。举个例子,代币在以太坊上的发行比例,在代币的发行合约里可以通过这种方式得到解决。断言保护经常需要和其他技术组合使用,比如当断言被触发时先挂起合约然后升级。(否则将一直触发断言,你将陷入僵局)
注意断言保护 不是 严格意义的余额检测, 因为智能合约可以不通过deposit()
函数被 !
在条件不满足也会抛出异常,但是最好只用于固定变量:内部错误或你的智能合约陷入无效的状态。遵循这些范例,使用分析工具来验证永远不会执行这些无效操作码:意味着代码中不存在任何不变量,并且代码已经正式验证。
所有整数除数都会四舍五入到最接近的整数。 如果您需要更高精度,请考虑使用乘数,或存储分子和分母。
(将来Solidity会有一个fixed-point类型来让这一切变得容易。)
谨慎编写用来检查账户余额的不变量。
攻击者可以强制发送wei到任何账户,而且这是不能被阻止的(即使让fallback函数throw
也不行)
攻击者可以在合约创建之前向合约的地址发送wei。合约不能假设它的初始状态包含的余额为零。浏览 获取更多信息。
许多应用需要提交的数据是私有的,直到某个时间点才能工作。游戏(比如,链上游戏rock-paper-scissors(石头剪刀布))和拍卖机(比如,sealed-bid second-price auctions)是两个典型的例子。如果你的应用存在隐私保护问题,一定要避免过早发布用户信息。
0.4.11中被引入的,和Abstract合约很像但是不能定义方法只能申明。Interfaces存在一些限制比如不能够访问storage或者从其他Interfaces那继承,通常这些使Abstract合约更实用。尽管如此,Interfaces在实现智能合约之前的设计智能合约阶段仍然有很大用处。另外,需要注意的是如果一个智能合约从另一个Abstract合约继承而来那么它必须实现所有Abstract合约内的申明并未实现的函数,否则它也会成为一个Abstract合约。
不要让退款和索赔流程依赖于参与方执行的某个特定动作而没有其他途径来获取资金。比如,在石头剪刀布游戏中,一个常见的错误是在两个玩家提交他们的行动计划之前不要付钱。然而一个恶意玩家可以通过一直不提交它的行动计划来使对方蒙受损失 -- 事实上,如果玩家看到其他玩家泄露的行动计划然后决定他是否会损失(译者注:发现自己输了),那么他完全有理由不再提交他自己的行动计划。这些问题也同样会出现在通道结算。当这些情形出现导致问题后:(1)提供一种规避非参与者和参与者的方式,可能通过设置时间限制,和(2)考虑为参与者提供额外的经济激励,以便在他们应该这样做的所有情况下仍然提交信息。
在合约执行消息发送没有携带参数(或当没有匹配的函数可供调用)时将会被调用,而且当调用 .send()
or .transfer()
时,只会有2,300 gas
用于失败后fallback函数的执行(译者注:合约收到Ether也会触发fallback函数执行)。如果你希望能够监听.send()
或.transfer()
接收到Ether,则可以在fallback函数中使用event(译者注:让客户端监听相应事件做相应处理)。谨慎编写fallback函数以免gas不够用。
明确标明函数和状态变量的可见性。函数可以声明为 external
,public
, internal
或 private
。 分清楚它们之间的差异, 例如external
可能已够用而不是使用
public
。对于状态变量,external
是不可能的。明确标注可见性将使得更容易避免关于谁可以调用该函数或访问变量的错误假设。
智能合约应该应该使用和它们测试时使用最多的编译器相同的版本来部署。锁定编译器版本有助于确保合约不会被用于最新的可能还有bug未被发现的编译器去部署。智能合约也可能会由他人部署,而pragma标明了合约作者希望使用哪个版本的编译器来部署合约。
(译者注:这当然也会付出兼容性的代价)
早于0.4版本, 当一个数尝试除以零时,Solidity 并没有 throw
一个异常。确保你使用的Solidity版本至少为 0.4。
为了防止函数和事件(Event)产生混淆,命名一个事件使用大写并加入前缀(我们建议LOG)。对于函数, 始终以小写字母开头,构造函数除外。
调用外部合约的主要危险之一是它们可以接管控制流,并对调用函数意料之外的数据进行更改。 这类bug有多种形式,导致DAO崩溃的两个主要错误都是这种错误。
这个版本的bug被注意到是其可以在第一次调用这个函数完成之前被多次重复调用。对这个函数不断的调用可能会造成极大的破坏。
(译者注:使用msg.sender.call.value()())传递给fallback函数可用的gas是当前剩余的所有gas,在这里,假如从你账户执行提现操作的恶意合约的fallback函数内递归调用你的withdrawBalance()便可以从你的账户转走更多的币。)
在给出来的例子中,最好的方法是 。这将避免多余的代码被执行。
然而,如果你没法完全移除外部调用,另一个简单的方法来阻止这个攻击是确保你在完成你所有内部工作之前不要进行外部调用:
注意如果你有另一个函数也调用了 withdrawBalance()
, 那么这里潜在的存在上面的攻击,所以你必须认识到任何调用了不受信任的合约代码的合约也是不受信任的。继续浏览下面的相关潜在威胁解决办法的讨论。
攻击者也可以使用两个共享状态变量的不同的函数来进行类似攻击。
0;这里,那么他们的余额就没有被清零,那么他们就能够调用transfer()
转走代币尽管他们其实已经收到了代币。这个弱点也可以被用到对DAO的攻击。
同样的解决办法也会管用,在执行转账操作之前先清零。也要注意在这个例子中所有函数都是在同一个合约内。然而,如果这些合约共享了状态,同样的bug也可以发生在跨合约调用中。
由于竞态既可以发生在跨函数调用,也可以发生在跨合约调用,任何只是避免重入的解决办法都是不够的。
作为替代,我们建议首先应该完成所有内部的工作然后再执行外部调用。这个规则可以避免竞态发生。然而,你不仅应该避免过早调用外部函数而且应该避免调用那些也调用了外部函数的外部函数。例如,下面的这段代码是不安全的:
另一个经常被提及的解决办法是(译者注:像传统多线程编程中一样)使用。它会"lock" 当前状态,只有锁的当前拥有者能够更改当前状态。一个简单的例子如下:
如果用户试图在第一次调用结束前第二次调用 withdraw()
,将会被锁住。 这看上去很有效果,但当你使用多个合约互相交互时问题变得严峻了。 下面是一段不安全的代码:
攻击者可以只调用getLock()
,然后就不再调用
releaseLock()
。如果他们真这样做,那么这个合约将会被永久锁住,任何接下来的操作都不会发生了。如果你使用mutexs来避免竞态,那么一定要确保没有地方能够打断锁的进程或绝不释放锁。(这里还有一个潜在的威胁,比如死锁和活锁。在你决定使用锁之前最好大量阅读相关文献(译者注:这是真的,传统的在多线程环境下对锁的使用一直是个容易犯错的地方))
以上是涉及攻击者在单个交易内执行恶意代码产生竞态的示例。接下来演示在区块链本身运作原理导致的竞态:(同一个block内的)交易顺序很容易受到操纵。
由于交易在短暂的时间内会先存放到mempool中,所以在矿工将其打包进block之前,是可以知道会发生什么动作的。这对于一个去中心化的市场来说是麻烦的,因为可以查看到代币的交易信息,并且可以在它被打包进block之前改变交易顺序。避免这一点很困难,因为它归结为具体的合同本身。例如,在市场上,最好实施批量拍卖(这也可以防止高频交易问题)。 另一种使用预提交方案的方法(“我稍后会提供详细信息”)。
请注意,块的时间戳可以由矿工操纵,并且应考虑时间戳的所有直接和间接使用。 区块数量和平均出块时间可用于估计时间,但这不是区块时间在未来可能改变(例如Casper期望的更改)的证明。
考虑如下这个简单的转账操作:
如果余额到达uint的最大值(2^256),便又会变为0。应当检查这里。溢出是否与之相关取决于具体的实施方式。想想uint值是否有机会变得这么大或和谁会改变它的值。如果任何用户都有权利更改uint的值,那么它将更容易受到攻击。如果只有管理员能够改变它的值,那么它可能是安全的,因为没有别的办法可以跨越这个限制。
对于下溢同样的道理。如果一个uint别改变后小于0,那么将会导致它下溢并且被设置成为最大值(2^256)。
对于较小数字的类型比如uint8、uint16、uint24等也要小心:他们更加容易达到最大值。
考虑如下简单的智能合约:
当有更高竞价时,它将试图退款给曾经最高竞价人,如果退款失败则会抛出异常。这意味着,恶意投标人可以成为当前最高竞价人,同时确保对其地址的任何退款始终失败。这样就可以阻止任何人调用“bid()”函数,使自己永远保持领先。建议向之前所说的那样建立 。
另一个例子是合约可能通过数组迭代来向用户支付(例如,众筹合约中的支持者)时。 通常要确保每次付款都成功。 如果没有,应该抛出异常。 问题是,如果其中一个支付失败,您将恢复整个支付系统,这意味着该循环将永远不会完成。 因为一个地址没有转账成功导致其他人都没得到报酬。
再一次强调,同样的解决办法: 。
在先前的例子中你可能已经注意到另一个问题:一次性向所有人转账,很可能会导致达到以太坊区块gas limit的上限。以太坊规定了每一个区块所能花费的gas limit,如果超过你的交易便会失败。
即使没有故意的攻击,这也可能导致问题。然而,最为糟糕的是如果gas的花费被攻击者操控。在先前的例子中,如果攻击者增加一部分收款名单,并设置每一个收款地址都接收少量的退款。这样一来,更多的gas将会被花费从而导致达到区块gas limit的上限,整个转账的操作也会以失败告终。
如果你实在必须通过遍历一个变长数组来进行转账,最好估计完成它们大概需要多少个区块以及多少笔交易。然后你还必须能够追踪得到当前进行到哪以便当操作失败时从那里开始恢复,举个例子:
如上所示,你必须确保在下一次执行payOut()
之前另一些正在执行的交易不会发生任何错误。如果必须,请使用上面这种方式来处理。
由于 进行的硬分叉,Call Depth攻击已经无法实施 (由于以太坊限制了Call Depth最大为1024,确保了在达到最大深度之前gas都能被正确使用)
正如我们先前在 章节所讨论的那样,避免自己遭受已知的攻击是不够的。由于在链上遭受攻击损失是巨大的,因此你还必须改变你编写软件的方式来抵御各种攻击。
我们倡导“时刻准备失败",提前知道你的代码是否安全是不可能的。然而,我们可以允许合约以可预知的方式失败,然后最小化失败带来的损失。本章将带你了解如何为可预知的失败做准备。
注意:当你向你的系统添加新的组件时总是伴随着风险的。一个不良设计本身会成为漏洞-一些精心设计的组件在交互过程中同样会出现漏洞。仔细考虑你在合约里使用的每一项技术,以及如何将它们整合共同创建一个稳定可靠的系统。
如果代码中发现了错误或者需要对某些部分做改进都需要更改代码。在以太坊上发现一个错误却没有办法处理他们是太多意义的。
关于如何在以太坊上设计一个合约升级系统是一个正处于积极研究的领域,在这篇文章当中我们没法覆盖所有复杂的领域。然而,这里有两个通用的基本方法。最简单的是专门设计一个注册合约,在注册合约中保存最新版合约的地址。对于合约使用者来说更能实现无缝衔接的方法是设计一个合约,使用它转发调用请求和数据到最新版的合约。
无论采用何种技术,组件之间都要进行模块化和良好的分离,由此代码的更改才不会破坏原有的功能,造成孤儿数据,或者带来巨大的成本。 尤其是将复杂的逻辑与数据存储分开,这样你在使用更改后的功能时不必重新创建所有数据。
当需要多方参与决定升级代码的方式也是至关重要的。根据你的合约,升级代码可能会需要通过单个或多个受信任方参与投票决定。如果这个过程会持续很长时间,你就必须要考虑是否要换成一种更加高效的方式以防止遭受到攻击,例如。
Example 1:使用注册合约存储合约的最新版本
在这个例子中,调用没有被转发,因此用户必须每次在交互之前都先获取最新的合约地址。
这种方法有两个主要的缺点:
1、用户必须始终查找当前合约地址,否则任何未执行此操作的人都可能会使用旧版本的合约 2、在你替换了合约后你需要仔细考虑如何处理原合约中的数据
另外一种方法是设计一个用来转发调用请求和数据到最新版的合约:
例2: 转发数据和调用
这种方法避免了先前的问题,但也有自己的问题。它使得你必须在合约里小心的存储数据。如果新的合约和先前的合约有不同的存储层,你的数据可能会被破坏。另外,这个例子中的模式没法从函数里返回值,只负责转发它们,由此限制了它的适用性。(这里有一个 想通过内联汇编和返回大小的注册表来解决这个问题)
无论你的方法如何,重要的是要有一些方法来升级你的合约,否则当被发现不可避免的错误时合约将没法使用。
由于断路器在满足一定条件时将会停止执行,如果发现错误时可以使用断路器。例如,如果发现错误,大多数操作可能会在合约中被挂起,这是唯一的操作就是撤销。你可以授权给任何你受信任的一方,提供给他们触发断路器的能力,或者设计一个在满足某些条件时自动触发某个断路器的程序规则。
速度碰撞使动作变慢,所以如果发生了恶意操作便有时间恢复。例如, 从发起分割DAO请求到真正执行动作需要27天。这样保证了资金在此期间被锁定在合约里,增加了系统的可恢复性。在DAO攻击事件中,虽然在速度碰撞给定的时间段内没有有效的措施可以采取,但结合我们其他的技术,它们是非常有效的。
速率限制暂停或需要批准进行实质性更改。 例如,只允许存款人在一段时间内提取总存款的一定数量或百分比(例如,1天内最多100个ether) - 该时间段内的额外提款可能会失败或需要某种特别批准。 或者将速率限制做在合约级别,合约期限内只能发出发送一定数量的代币。
在将大量资金放入合约之前,合约应当进行大量的长时间的测试。
在合约测试期间,你可以在一段时间后强制执行自动弃用以阻止任何操作继续进行。例如,alpha版本的合约工作几周,然后自动关闭所有除最终退出操作的操作。
在早期阶段,你可以限制任何用户(或整个合约)的Ether数量 - 以降低风险。
运行赏金计划的一些提示:
有关三级奖励的例子,参见 :
奖励的价值将根据影响的严重程度而变化。 奖励轻微的“无害”错误从0.05 BTC开始。 主要错误,例如导致协商一致的问题,将获得最多5个BTC的奖励。 在非常严重的漏洞的情况下,更高的奖励是可能的(高达25 BTC)。
当发布涉及大量资金或重要任务的合约时,必须包含适当的文档。有关安全性的文档包括:
Linters通过约束代码风格和排版来提高代码质量,使代码更容易阅读和查看。
链集市 · 让区块链落地更简单
上周,区块链应用落地无论是在政策,还是在实践上都有很好的进展。
首先,全国已有超过33个省市出台区块链专项政策,除了财政奖励、房租减免、人才补贴等支持措施,有16个地方明确提出由政府国有资本主导设立区块链产业投资基金或子基金,其中,海南、广州、娄底、苏州的文件中明确(子)基金金额为10亿元或不低于10亿元。国内虽然经历了数月的大刀阔斧的监管整治,但是在应用落地方面始终不遗余力的推行。进而激发了一大批优秀的开发人员参与其中。
中国区块链专利申请量全球第一,数量达 10月31日报道,乌克兰试图规范加密领域的“虚拟资产法”已被再次修订并建议最终通过。本月,乌克兰总统否决该法案,议会的一个重要委员会表示支持该法案。乌克兰代表将于11月就更新的“虚拟资产法”进行投票,乌克兰期待已久的监管加密货币和相关活动的立法即将结束。乌克兰议会最高拉达的数字化转型委员会(The Digital Transformation Committee)本周讨论了修订后的“虚拟资产”法律草案,并支持最新的修改。
据悉,该法案在10月初由乌克兰总统Volodymyr Zelensky退回立法机构后,已得到更新。乌克兰总统做出这一决定的主要理由是,法案中设想的为加密市场建立新的监管机构对国家来说过于昂贵。Zelensky提议由国家证券和股票市场委员会(NSSMC)来负责监督。NSSMC还将监管基于证券的虚拟资产,如果这些资产由法定货币支持,乌克兰国家银行(NBU)将负责监管。
据Forklog报道,修订后的法案将于11月2日在议会上进行讨论,并将在议会特别会议上审议。如果立法者再次通过该法案,这一次乌克兰总统将有义务根据国家宪法在10天内将其签署成为法律。
【北京外汇管理部开展区块链平台资本项目收入支付便利化真实性审核应用场景实地调研】
据国家外汇管理局北京外汇管理部 10月 31日消息,2020年12月,北京大兴自贸区启动跨境金融区块链服务平台资本项目收入支付便利化真实性审核应用场景试点。平台以接口直联方式共享税务部门发票数据,极大提升了银行审核企业发票信息真实性的效率。2021年8月,试点扩容至北京市全辖,8家银行备案开展试点业务。
为了解试点扩容后的业务开展情况,近期,北京外汇管理部赴兴业银行北京分行和招商银行北京分行开展实地走访调研,全流程体验了兴业银行北京分行通过平台处理资本项目收入支付便利化真实性审核抽查数据,研讨招商银行北京分行“发票云”系统核验发票的优势。调研发现,区块链平台运行顺畅,企业配合度较高,抽查效率较手工核验发票大大提高。
下一步,北京外汇管理部将进一步优化完善区块链平台应用操作细节,提升跨境投融资便利化水平,服务北京经济高质量发展。
【赣州经开区开展虚拟货币排查整治】
10月28日,赣州经济技术开发区党务公开网发布消息,为进一步做好防控虚拟货币挖矿和交易炒作风险,近日,赣州经济技术开发区处非办联同中国人民银行赣州市中心支行、市政府金融办、区公安分局、区市监分局前往恒科产业园、国际企业中心开展打击虚拟货币挖矿和交易行为专项排查整治工作。
排查现场,工作人员通过查访公司内部设置、核验营业执照、询问公司员工、核查公司业务、发放风险提示函等方式对园区内企业进行风险排查整治。下一步,州经济技术开发区将加强宣传教育,通过典型案例剖析、投资风险教育等方式,向社会公众宣传虚拟货币炒作等相关业务活动的违法性、危害性及其表现形式等,增强社会公众风险防范意识。
【希尔顿酒店继承人Paris Hilton在苏富比元宇宙拍卖其NFT藏品】
希尔顿酒店继承人、美国社交名媛Paris Hilton发推表示,将在苏富比的NFT市场“苏富比元宇宙”拍卖她的NFT藏品,其中包括Chelsea Evenstar和Maalavidaa等NFT艺术家的作品,拍卖将于10月26日结束。
【万向峰会丨李礼辉:去中心化金融是未来国际金融竞争及全球金融监管的热点】
巴比特现场报道,10月26日,由万向区块链实验室主办的第七届区块链全球峰会在上海举行。中国银行原行长、中国互联网金融协会区块链研究工作组组长李礼辉在题为《区块链:技术创新与产业升级》的开幕演讲中表示,去中心化金融既是未来国际金融竞争的热点,更是未来全球金融监管的热点。他还指出,开源正在渗透越来越多的软件产品。一些专家认为,开源已经成为数字技术创新的主流,开源可以跨越公司边界、国家边界,赋能产业的转型与升级。需要注意的是,开源也将构成系统绑定和技术依赖,一些开源软件缺乏明确的安全责任主体和权威性的安全性能认证,可能存在安全漏洞。
【扎克伯格:Facebook目标是让元宇宙规模达到10亿人】
10月25日消息,Facebook首席执行官马克·扎克伯格在最新一次的财报会议上表示,Facebook目前一个重要事项是构建元宇宙愿景,但扎克伯格并未就Facebook计划改名以体现AR/VR业务重心的报道进行任何评论,仅承认自己对这一领域的确抱有很大的野心。他强调,Facebook目标是让元宇宙的规模达到10亿人,元宇宙可能会带来价值数千亿美元的数字商业市场。此外,马克·扎克伯格坦言来自TikTok、iMessage的竞争压力一直在加剧,Facebook将采取更多措施来赢得18岁至29岁间的“年轻人”用户。
【万向峰会丨万向区块链董事长兼总经理肖风:分布式商业有9大基础设施,包括数字货币、NFT、DAO等】
10月27日,由万向区块链实验室主办的第七届区块链全球峰会在上海举行。中国万向控股副董事长兼执行董事,万向区块链董事长兼总经理肖风发表了题为《分布式商业基础设施前瞻》的闭幕致辞。他表示,分布式商业指的是数字原生(孪生)的商业活动。支撑分布式商业的基础设施包括,数字货币(Coin);数字资产(Token);数字通证(NFT);比特币闪电网络;去中心化全球存储系统;去中心化全球算力系统;去中心化全球隐私计算系统;共识算法与分布式记账;去中心化商业自组织(DAO)。
核心提示:合约交易app开发合约交易所开发_量化合约跟单交易系统搭建_数字货币合约杠杆交易平台开发技术开发公司为您解读131+电/微。
大家都知道,交易所其实就是用来交换数字货币的一个平台,它们部分平台可进行杠杆交易、量化交易、合约交易等操作。
使用区块链交易所的好处是什么
在区块链上交换的好处在于交易所并不持有使用者大量的加密货币,所有的加密货币会储存在区块链上使用者的钱包或智能合约控管。本来需要信任中心化的交易所,现在仅需要信任区块链以及智能合约即可。而用于交易所的智能合约大多会公开源码让所有人可以确认这份合约的细节。
而中心化交易所通常不会公开交易细节的源码,实际上如何运作也只有其内部人员可得知。公开智能合约维持了交易过程的透明与安全性,就算其中有利润的拆分也会公开在区块链上。
依附性强:应用软件必须得到计算机硬件及系统软件的支持才可以发挥作用,而不能独立存在并发挥作用;
互动性强:即使是z简单的应用软件也有一定的交互功能,比如说对操作人员的错误的提示,这是IT行业产品z本的优越性体现;
数量上无限:数字资产作为资产是稀缺的(因为并不是所有的企业或个人都能创造出数字资产),但它的供应可以是无限的。而有形资产由于企业的财产和存储空间的限制,总是有限的;
成本递己有形资产的生产成本与生产数量成正比例关系递增。数字资产的成本主要是在前期的研究开发阶段以及在销售过程中发生的销售费用和其他经营费用,由于数字产品产量的无限性,其开发成本按传统财务会计的方法被分摊到产量上,因此数字产品的成本随着销售量的不断扩大,其成本是越来越低的。
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。