区块链技术与应用【肖臻老师】笔记整理之------22-ETH-智能合约
作者:互联网
注:没有全部复原,抽取了主体知识,加入了一些自己的理解,强烈建议去学习肖臻老师的课程,这绝对算得上是国内区块链讲解的顶级教程,纯学术和技术
智能合约是以太坊的精髓。
智能合约是运行在区块链上的一段代码,代码的逻辑定义了合约的内容。
智能合约的账户保存了合约当前的运行状态
- balance 当前余额
- nonce 交易次数
- code 合约代码
- storage 存储,数据结构是一棵MPT
Solidity是智能合约最常用的语言,语法上与JavaScript很接近
强类型语言,
mapping不支持遍历,需要自己记录hash表中有哪些元素
event事件,是用来记录日志的
有两种方式,第一种是与合约同名的函数,没有返回值,第二种是使用constructor函数
构造函数constructor只能有一个
如何调用智能合约
调用合约与转账类似,
A->B,如果B是外部账户那就是最普通的交易,如果B是合约账户,那么就相当于发起对B的合约的一次调用
具体调用的是哪个函数,是在数据域中说明的,data域
emit的作用就是写一个Log
一个交易只能由外部账户发起,而不能由合约账户发起,
另一种交易方式:
delegatecall():与call()的方法基本上是一样的,一个主要的区别是,Delegatecall()不需要切换到被调用的合约的环境中去执行,而是在当前的环境中执行就可以了。
以太坊中凡是接受外部转账的交易都必须标记为payable(),否则给这个函数转钱的时候会抛出错误异常。
没有别的函数可调用时就调用fallback()函数
如果fallback()函数不是payable的,那么别的函数向该合约地址转账会引发异常
只有合约账户才有这些智能合约
转账金额是0,但是Gas 不能为0,那是给Miner的,否则miner不会打包区块
JVM:增强可移植性
EVM:世界计算机,256位寻址空间
- Payload就是data域,用于存放调用的是合约中的哪个函数,函数的参数取值是什么
- 当全节点收到对智能合约的调用的时候,首先是按照GasLimit算出可能需要的最大Gas费,然后一次性将Gas费从发起账户中扣除,然后再根据实际的汽油费,多退少了就回滚机制
- 不同的指令消耗的Gas费是不一样的,一些简单的指令很便宜,比如加减操作,复杂的指令很贵,比如取哈希,需要存储状态的指令也很贵,读取公众数据是可以免费的
-
以太坊中的交易具有原子性,一个交易要么全部执行 要么完全不执行,不会只执行一部分,交易既包含对普通的转账也包含对合约的调用。所以如果在执行智能合约的过程中出现错误,会导致整个交易的回滚,退回到开始执行之前的状态。比如交易进行到一半时,Gas消耗完了,那么交易要回滚,但是Gas费是不退回的。
-
revert()函数是无条件的终止
- 直接调用会引起连锁式回滚
- 使用call()的方式不会引起连锁式回滚
-
GasLimit:是整个区块所有交易Gas消耗的上限
-
每个区块可以上调和下调上一个区块GasLimit的 1 1024 \frac{1}{1024} 10241,所以最后趋近于所有矿工的平均值
-
先Mining还是先执行智能合约?
- 三棵树都是全节点在本地维护的数据结构
- 执行智能合约是改变自己本地的状态,只有达成了共识,发布到区块上,当与发布区块的状态不一致时,Miner会丢弃自己的状态转而更新本地三棵树,进行同步。都是需要重新执行一遍
- 所以先执行,后挖矿。
- 得先更新Blockheader里面的Root,TxHash,ReceiptHash。确定了Block Header,然后才可以进行Minging
-
会不会因为没有奖励,有的Miner就不去验证区块的正确性?
- 可能会存在,但是如果不验证的话,那么其Block header就得不到更新,本地的状态不对,以后就无法Mining,发布的区块得不到别人的验证
-
发布到区块链上的交易是不是都是成功执行的?:不一定
- 如果智能合约出现了错误要不要也发布到区块链上去?
- 要,否则Gas费用扣不掉,要达成共识,这样Miner才能收钱
- 如果智能合约出现了错误要不要也发布到区块链上去?
-
status就是告诉你交易执行的情况是什么样
-
智能合约支不支持多核并行处理?
-
Solidity不支持多线程,没有多线程的语句。
-
给定 一个 智能合约,给定输入,它转移到的状态或者说是输出必须是完全确定的
-
因为所有的全节点都得执行同一组操作到达同一种状态,如果状态不确定的话,那三个根哈希值根本对不上,必须完全确定才可以
-
多线程的问题在于,多个核对内存访问顺序不同的话,执行结果有可能是不确定的
-
导致执行结果不确定的操作:产生随机数。伪随机数的产生也是不确定的
-
-
- 智能合约里没有办法获得精确的时间,只能获得和当前区块的时间信息
callcode
<address>.transfer
是指往address里转,只有一个参数,转入的地址
例子:简单拍卖
- 有什么问题?
-
最后都收不到钱,
hackV1
没有fallback
函数,退款时会出现问题- 当一个合约收到转账没有调用任何函数时,会调用fallback,但是没有fallback函数,所以会调用失败,会抛出异常,而
transfer
函数,会引起连锁式的回滚,最后导致所有人都收不到钱。
- 当一个合约收到转账没有调用任何函数时,会调用fallback,但是没有fallback函数,所以会调用失败,会抛出异常,而
-
出现这种问题怎么办?
- 没有办法233
- Code is law,改不了,没有人篡改规则,坏处是规则不好也无法改变
- 智能合约设计的不好的话,ether可能永久锁起来,谁都取不出来
- 类似于不可撤销的信托。irrevocable trust
- 一定要测试,测试再测试
-
能不能留一个后门,以后改,类似系统管理员
- 与去中心化理念是背道而驰的
- 这样可以了吗?
- 重入攻击
- 直到什么时候结束?
- 余额不够
- 调用栈溢出
- Gas费不够了
- send和transfer有一个共同的特点:
- 转账过去的Gas费只有2300Wei
- 不足以让接收者再发起一次新的调用,只够写一个Log
标签:肖臻,函数,22,Gas,智能,调用,------,区块,合约 来源: https://blog.csdn.net/qq_38123961/article/details/117092324