怎么把网站链接做二维码,新手学做网站 pdf 网盘,保健品网站建设方案书模板,深圳公司网站开发智能合约
首先明确一下几个说法#xff08;说法不严谨#xff0c;为了介绍清晰才说的#xff09;#xff1a; 全节点矿工 节点账户
智能合约是基于Solidity语言编写的 学习Solidity语言可以到WFT学院官网#xff08;Hello from WTF Academy | WTF Academy#xff09;…智能合约
首先明确一下几个说法说法不严谨为了介绍清晰才说的 全节点矿工 节点账户
智能合约是基于Solidity语言编写的 学习Solidity语言可以到WFT学院官网Hello from WTF Academy | WTF Academy有初级和进阶课程
智能合约的结构
下面的函数的问题在文章最后讨论 上述是一个简单的智能合约的结构 一个合约可以看作是一个类 log通过emit触发事件在链上记录下来 构造函数是每个合约有且只有一个的可以为空只能在创建时调用一次 成员函数是部署合约后可以调用的一般有关键字modifier等限制权限 智能合约里的mapping不能遍历只能存储它的地址集合按照地址去查询
合约的调用
外部账户的调用 首先要填写外部账户的地址合约账户的地址 之后需要填写函数接收的参数之后细说 一般部署和调用合约的编译器是Remix
一个合约中调用另一个合约的函数
直接调用 合约B调用合约A的内容A a A(addr),addr指的是A的地址该语句将这个地址转换成A合约的实例a之后调用a里面的函数foo使用ua接收返回值。 由于以太坊规定一个交易只能由外部账户调用合约账户不能发起交易。因此只能当某个外部账户调用合约B的时候才能触发B中的那个语句进而调用A 这种调用方式下如果A在运行过程中发生什么异常会导致B合约的内容也连带回滚
call函数调用 这种方式的调用如果调用的合约addr的实例出现错误C合约不会回滚只会引起调用部分返回异常值其余部分正常
代理调用 这种调用不需要切换到被调用的合约环境中去执行在当前合约的环境中执行使用当前合约的属性等 fallback函数
注意只有向合约账户转账时才有fallback函数的生成 如果不需要调用函数或者调用函数错误时Solidity编译器自动生成fallback函数里面的payable函数也是自动添加的
注意gas费是给记录你这笔交易矿工的类似于BTC里面的交易手续费不是给合约账户的
合约节点会在以下情况下调用fallback函数 未知函数调用 当合约接收到一个未知的函数调用时即调用合约中不存在的函数时会触发fallback函数的执行。 以太币转账 当以太币被直接发送到合约地址即没有附带调用数据这时会触发fallback函数的执行。 低级调用 如果合约内部使用了call或delegatecall调用其他合约并且调用的合约不存在对应的函数时也会调用fallback函数。
错误处理
智能合约的调用具有原子性即一个合约部分出错整体回滚这个和前面讲的addr调用不冲突addr调用是使用一个判断语句将这个调用变成了一个返回值 gaslimit被耗完依旧不能实现调用被回滚而且gas费不退还 assert()语句检查内部错误类似于C语言 require()语句检查外部错误比如msg.senter!addr revert()语句自动弹出错误可用于if条件等
注意Solidity里面没有自定义报错类型try-catch
嵌套调用
一个合约调用另一个合约
如果向某个合约账户转账虽然表面上你没有调用但是编译器自动帮你生成了fallback函数还是调用了
智能合约的创建和运行
创建 外部账户发起转账到0x0地址中转账金额为0 合约代码编译成bytecode放在data域中 支付给矿工gas矿工将合约发布到区块链上返回合约的地址也就是智能合约的地址 此时智能合约就可以被所有人调用了
运行
智能合约运行在以太坊虚拟机EVMEthereum Virtual Machine上
EVM是一个256位的WWCWorldwide Computer使用EVM提高了智能合约的可移植性
汽油费gas
原因
图灵完备的语言需要避免死循环导致的停机
数据结构
调用合约的人支付相当于是把停机问题推给了调用方 GasLimit就是调用方此次调用这个合约能接受的最大汽油量可以在Remix部署时填写
GasLimit * Price 计算出的是花掉的最大汽油费
Payload就是data域
gas的价格是由调用者选择的价格高的更容易被矿工写入区块。 往往代码功能简单的汽油费低代码复杂的汽油费高。 存储状态变量汽油费高仅读取状态变量免费
调用过程 当一个全节点收到一个调用的时候它首先计算出调用花费的最大汽油费 将这笔最大汽油费从发起账户中扣掉。 然后根据实际执行的情况算出实际花费的汽油费剩下的退回去不够的话合约回滚gas耗完不退
数据结构
区块头
GasLimit
实际消耗gas的上限
BTC每个区块最大不能超过1M主要是带宽因素 由于ETH矿工的gas费收益是很可观的防止他为了多收钱把巨量的的交易包含进去影响传输速率也要进行限制 但是因为智能合约Solidity的结构复杂循环和调用往往大小不能完全反映复杂程度因此就使用最大gas费的方式限制
GasUsed
实际消耗的汽油费
每个区块发布的时候矿工可以对gaslimit进行微调上下不超过1/1024
三树
合约调用的时间应该在发布区块前还是发布区块后
先执行后挖矿。原因是执行完合约之后“三树”的信息会改变而区块头包含的是三树的根哈希值。只有得到根哈希值之后才可以组合数据尝试nonce值
本质上汽油费是为了补偿矿工执行合约消耗的资源。但是对于没有挖到区块的矿工他们的验证没有补偿的这会不会导致那些矿工不去验证发布的区块就默认发布的是对的。如果这样的话就会严重影响区块链的安全性
节点不验证了怎么办
如果它不执行不验证就无法更新三树之后它组装区块的时候算出的根哈希值是错的挖出区块的nonce值被其他区块验证为不合法环环相扣了属于是。
我还是不验证直接抄
这种做法类似于矿池的做法一个全节点进行验证其他矿工只负责计算哈希值。
但是如果你不是这个矿池的成员你敢不敢相信它发布的三树根哈希是正确的呢要知道挖矿的3Ether收益可是远远大于gas费的矿工不愿意冒着辛辛苦苦挖出区块作废的奉劝去节省验证的花销。
执行错误的交易要不要发布
要这样依旧可以扣除他的汽油费获得你的收益
智能合约是否支持多线程多核并行处理
不支持因为Solidity语言中不具有支持多线程的语句。原因是多核对于内存访问顺序不同的时候会导致最终的结果不同而以太坊需要的是状态机进入统一的确定的状态Papers (zhenxiao.com)可以参考肖老师的论文 Receipt 每个交易执行完形成一个收据receiptStatus这个变量代表的是交易的状态
地址类型 address.balance: address的余额
address.transfer(金额):当前合约向address转入的金额
address.call:当前合约调用address
转账的方法
address.transfer(uint256 amount)//会导致连锁型回滚 gas少
address.send(uint256 amount)//返回false 不会会滚 gas少
address.call.value(uint256 amount)//本意不是专门为转账设计的 不会会滚 发送剩余的所有gas 智能合约的信息获取
通过智能合约可以得到区块链的信息 智能合约可以获取的调用信息 msg.sender和tx.origin的区别 上图中A账户调用C1合约中的f1函数f1函数调用C2合约中的f2函数
则对于f2函数而言msg.sender指的是C1而tx.origin指的是A账户
智能合约的设计
不可篡改
智能合约是不可篡改的在发布之前一定要反复测试。
一旦发布就不可撤销无法更改。可能会导致资金的永久锁死或者被黑客利用漏洞进行攻击
测试的网址比如本地的truffleganache测试网等等确认完全没有问题再进行发布
后门
不存在的因为这与去中心化背道而驰
拍卖函数的修正
第一版问题 右侧最高出价的for循环有问题都拿不到钱
第二版 拆成两个函数第一个允许竞拍的失败者取回自己的钱只能取一次第二个是将最高出价给卖家
BUG 注意黑客合约的fallback函数右侧最下面当合约通过call函数调用时调用fallback函数忘记的话可以回顾一下上面的fallback函数部分。因此主合约的withdraw进入if语句的判断时就会调用fallback函数给黑客转账而fallback函数再次调用withdraw函数形成循环根本无法执行48行的清零语句...
循环截至的条件 合约存储的钱不足以支付下次转账 调用栈溢出 gas费不足
这也是黑客的fallback函数里面if语句判断的条件
第三版 先清零再转账这遵循了和其他合约发生交互的编程模式 先判断条件再改变条件最后交互
第二版纠正
另一种方法就是不用call 使用send和transfer都可以因为发送出的汽油费只有2300个单位不足以支撑再一次的调用只够写一个log
The DAO
造成以太坊分裂的一次攻击
DAODecentralized Autonomous Organization 去中心化机构
致力于去中心化投资的公司——The DAO
运行原理
这个公司本质上是ETH上的一个智能合约你想要投资就要把你的以太币发给这个合约换取合约的D代币简称。要投资什么项目由大家投票决定投票的权重按照所拥有的D代币分配收益也是按照规定按比例分配。
取款
取款的方式使用split DAO。当取钱时收回相应的代币将对应的以太币打到子基金Chile DAO之中这种做法也是给部分人投资小众项目拆分子基金用的极端例子就是单个投资者成立子基金也就是取钱
拆分之前有7天的讨论期用于商讨要不要拆出子基金以及要不要加入这个子基金
拆分后有28天的锁定期子基金里的钱要28天以后才能取出来
历史事件
2016年开始众筹引起很大关注在一个月时间筹集到价值1.5亿美元的Ether当时价格 这就违反了之前提到的先判断条件再改变条件最后交互的编程原则导致了黑客盗走价值5kw美元的资金
之后社区发生意见的分歧一方认为要回滚利用28天的锁定期来防止黑客取走资金。另一方认为合约的漏洞只是它自己的漏洞不能因为一个合约的问题就违背以太坊的不可篡改性。
社区的开发者认为The DAO是too big to fail垮掉会对以太坊造成毁灭性打击以太币价格跳水因此采取了回滚措施进行补救。
如何补救
首先以太坊开发团队想到的是一个软分叉方案
锁定黑客账户进行一次软件升级但凡与TheDAO相关的账户不能进行任何交易老认新软分叉。
问题是当时规定这些”非法“的账户发布交易不能上链也不收取gas因此引起了很多这种账户发布死循环攻击来骚扰矿工矿工不堪重负纷纷回滚这次软件的升级
由于软方案失败所剩时间不多团队只能采取硬分叉方案
将所有的资金要是只转黑客的其他的相关帐户都可以利用这个BUG实现攻击转入一个账户B该账户的唯一作用就是——退钱在第192W个区块强制将所有相关账户的钱转给账户B新认老固执节点不认可你没有人家账户签名就转账的操作
分歧
很多节点认为这种操作违背了去中心化的理念以太坊团队说转走谁的钱就转走因此以太坊团队发布两个合约进行投票支持哪一种方案就把以太币投进那个合约。最后大多节点按掌握资金数量分选择硬分叉。
但是另一方不认可这样的做法 并非所有资金都参与投票了 大多数人支持的就一定对吗
这些矿工挖出的旧链以太币被称为ETC
ETC
ETCclassic指的是在旧链上挖矿产出的以太币由于挖矿算力大幅削减不乏投机者选择在这条链上进行挖矿但是也有一部分矿工坚持挖矿是源自去中心化的信仰尽管开始的前景并不被人看好但是这条链依旧坚持至今。 2015年7月 Vitalik Buterin和以太坊基金会创建了第一个基于区块链的图灵完成智能合约平台。
2016年4月~6月 以太坊The DAO项目ICO以遭到黑客攻击告终
2016年7月20日 以太坊硬分叉实施产生了ETH和ETC两条独立的区块链ETC正式诞生
2016年8月 91pool上线
2016年9月23日微软加入对于ETC的支持
2016年10月17日ETC第一个ICO项目ETCWIN
2016年10月ETCFans上线
2016年12月24日全球第一个以太坊原链社区交易所ETCWin上线
2017年4月27日ETF基金会确定限产
2017年6月底ETC发起支持零知识证明改进建议。
......
为了更好的管理这两条链产生了新的数据标记——ChainID
Beauty Chain美链
背景介绍
美链(Beauty Chain)是一个部署在以太坊上的智能合约有自己的代币BEC。 ICOInitial Coin Offering没有自己的区块链代币的发行、转账都是通过调用智能合约中的函数来完成的 可以自己定义发行规则每个账户有多少代币也是保存在智能合约的状态变量里 ERC 20Ethereum Request for Comments是以太坊上发行代币的一个标准规范了所有发行代币的合约应该实现的功能和遵循的接口 美链中有一个叫batchTransfer的函数它的功能是向多个接收者发送代币然后把这些代币从调用者的帐户上扣除
很多代币上线之前是依附在以太坊上的。
实现 接收者的数目最多20个
问题
uint amount uint256(cnt) * _value
乘出的结果可能过大出现溢出即扣除的代币数字很小。也就是调用者转出的代币少接收者依旧收到海量代币。也就是系统发行代币量凭空增多。
攻击细节 每个黑客区块收到了很大一部分代币
反思
Is smart contract real smart
智能合约实际上只是一种改不了Bug的合同
不可篡改性是一个双刃剑
一方面增加了合约的公信力
但另一方面发布后的软件很难进行修改。发现了安全漏洞很难发布软分叉进行补救或者阻止调用哪怕发现了黑客也很难冻结其账户
如果你是theDAO的用户怎么补救
使用重入攻击转走剩余的资金之后再分给大家
Nothing is irrevocable
不要过度迷信区块链的不可篡改性代码是死的人是活的
比如美国宪法还有修正案以及被推翻的修正案禁酒令
Solidity语言设计的问题
安全性问题
有人认为Solidity语言是反自然的。本质上转账时调用fallback函数也就给了被转账方再次调用合约的机会。这和正常情况下转账接收方是被动接收相违背和常识不同。因此有人提议应该使用函数式的语言编写合约
语言表达能力
图灵完备的表达能力是不是太强了BTC的语言表达能力太差ETH写的程序又有些危险。能不能找一种适中的语言
在日常生活中我们使用自然语言编写合同自然语言写出的一些合同也有纠纷难道要写一套合同专用语言吗实际上的解决方法是在模板的基础上编写合同常用的智能合约会出现模板会出现专门编写智能合约的机构......
相信智能合约终究会走向成熟
透明性
中心化的公司很多是闭源的把源代码当作是商业机密。去中心化的公司为了让大家达成共识往往需要将代码开源比如更新查验等等
开源的好处 增加合约的公信力 开源代码很多人审查不容易出现漏洞
Many Eyeball Fallacy
虽然很多人有权限看但是大多人没动力看看不懂或者看懂了找不出漏洞
涉及到财产安全的合约要仔细检查漏洞。投资需谨慎将资金投入在自己了解擅长的领域不要孤注一掷天台见
去中心化
What does decentralization mean
去中心化不是说一切由代码决定也要有人的参与。
去中心化不是说制定好的规则一定不能修改而是规则的修改要按照去中心化的原则来完成。
分叉
存在分叉的选项是民主的体现因为在中心化的世界里你只能接受
这就像theDAO当时的子基金或者像还在挖矿的ETC亦或是创建以太坊的V神他们愿意构造一个世界不是少数服从多数而是只要有想法就可以走出自己的道路。
去中心化不等价于分布式
去中心化一定是分布式的但是分布式如果是由一个组织管辖或者占有绝对领导权也不能叫去中心化。
分布式的系统是不同的机器做不同的事情最后汇总成一个结果。本质目的是为了加速
状态机
而比特币和以太坊都是运行的一台状态机付出巨大的代价使得系统维持一个一致的状态。状态机的本质目的是为了容错。space shuttlestock exchange 等状态机多台计算机运行同一个状态防止某台机器宕机的风险。状态机由于同步的需要往往是机器越多运行越慢因此只有几台机器本来就是防止某台宕机的多了也没必要
而向BTCETH这种上千台计算机的分布式状态机是两者的混合体智能合约适用的不是分布式系统智能合约是用来在互不相识的机器之间建立共识机制的控制性语言而不是用于大规模云计算的。
溢出
Solidity 里的SafeMath有很对针对溢出的函数
ca*b
assert(c/ab)
不会存在像C语言的溢出
flag对于智能合约审计和黑客游戏的内容之后会学习分享