智能合约特征:
1 合约一旦部署完成,就无法修改。
2 调用合约时触发既定的合约规则,并且执行过程是原子性执行(All or Nothing)
3 以太坊中合约是公开可见的,出发合约的交易也是透明存储
通过solidity编写的合约在线编译网址:
https://remix.ethereum.org/
以太坊账户分为:
外部账户,由账户私钥控制
合约账户,通过CREATE或CREATE2(主要应用于状态通道中,在链下执行未部署的合约)
交易类型:
合约创建、触发合约交易、转账交易。
交易中,通过gas评估交易执行过程中的计算和存储花销。
交易发起人通过指定gasLimit限制gas的花销。
合约方法执行
只有明确的合约方法能被执行。
执行未定义的合约方法触发fallback()external{}回调函数
发送eth到合约地址触发receive()external payable{}回调函数。
合约中确定的业务规则,当给定同样的输入,总会执行同样的业务逻辑,产生同样的输出。
EVM
合于被编译成能够在EVM中执行的字节码,通过EVM遍历字节码改变状态。
栈宽256
16进制下opcode表示的范围为:00-ff,一共能有256个不同的关键字
字节码的网址:
https://ethervm.io/
https://www.evm.codes/playground
https://www.4byte.directory/
通过字节码反编译推出合约代码的研究是下一步的研究热点
Specific features
tx.origin:当前交易的签名者,交易执行过程中不会发生变化
msg.sender:交易的即时调用者,在交易执行中可能会发生变化(call)
合约交易注意事项
1 交易中当前交易的发起者是谁
call合约会改变被调用者的msg.sender,可以判断即时的交易调用者身份。但是tx.origin标识交易签名者,执行过程不会发生变化。因此,tx.origin无法判断在执行过程中的交易发起者身份。【contract-in-the-middle attack】
2 交易执行过程中是否超出gas (roo)
交易中执行循环时,指定最大的循环
3 交易执行过程执行其他合约的调用
call,delegatecall,send等调用在roo时不会返回异常,只会返回bool,因此,进行必须调用的判断[require,if…else,assert]
transfer在调用失败后返回异常。
并且send和transfer执行调用时只会发送2300gas到调用者,避免重入攻击
call和delegatecall会发送当前剩余的所有的gas,存在gas多花销风险
4 当前合约依赖其他合约时
依赖的合约一旦销毁,依赖它的合约的数据状态便无法修改。因此,在依赖其他合约的时候一定要确定所依赖的合约无法销毁,没有selfdestruct关键字。
或者,通过library关键字调用合约库,库合约中的方法不会占据存储空间,所有的存储都在自己的合约上。
5 DoS的潜在风险
合约拥有者身份变换–》复杂的授权机制[owner判断、多签验证、前置条件的判断]
合约中存在依赖动态数组的循环,且目前的数组很大–》指定循环的最大次数
依赖具有selfdestruct的外部合约—》改为使用库合约,所有的数据存储在本地
外部调用的合约roo或者通过proxy合约改变了实现合约
6 依赖Ether判断的合约无法保证安全性
自毁合约会实现现合约余额的退款,给指定的账户退款。
7 交易的执行需要矿工排序,存在抢跑者高gasprice抢跑风险
8 当业务逻辑的执行顺序不对时,存在重入攻击风险。
为保证安全性,执行cheak-effects-interfacts的执行逻辑:
check:前置条件的判断,验证所有的输入数据和当前的状态
effects:更新本地状态,假设交易执行成功
interfacts:执行合约交互,触发其他合约的业务逻辑

在合约部署之前,通过合约验证工具检查:

oracle contract
合约无法直接获取外界数据,所以通过oracle contract简介获取链下数据
oracle contract 验证链下数据,并存储供其他合约调用。
合约的更新
通过proxy合约实现合约的更新
更新合约时,旧合约地址的数据无法迁移,或者代理合约分为存储合约和逻辑合约

合约factory
通过 contract com = new contract();return address(con)新实例化一个合约,新实例化的合约都具有相同的合约代码。
合约工厂通过实例化合约,允许部署带有相同代码的合约账户。
合约攻击锻炼
https://ethernaut.zeppelin.solutions/
https://www.damnvulnerabledefi.xyz/
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent