什么是智能合约?
- 智能合约是运行在区块链上的一段代码,代码的逻辑定义了合约的内容。
- 智能合约的账户保存了合约当前的运行状态
balance:当前余额
nonce:交易次数
code:合约代码
storage:存储,数据结构是一颗MPT树 - Solidity是智能合约最常用的语言,语法上与JavaScript很接近
- example
【payable】
以太坊规定如果合约账户要能接受外部转账,必须标注payable。
调用智能合约
如何调用智能合约
创建一个交易,接收地址为要调用的呢个智能合约的地址,data域填写要调用的函数及其参数的编码值。
一个合约调用另一个合约中的函数
- 直接调用
以太坊中规定一个交易只能由外部账户发起,合约账户不能主动发起。 - 使用address类型的call()函数
- 代理调用delegatecall()
智能合约的创建和运行
智能合约的代码写完后,要编译成bytecode
创建合约
- 外部账户发起一个转账交易到0x0的地址
- 转账的金额是0,但是要支付汽油费
- 合约代码放在data宇里
合约运行
- 智能合约运行在EVM(Ethereum Virtual Machine)上
- 以太坊是一个交易驱动的状态机,调用智能合约的交易发布到区块链上后,每个矿工都会执行这个交易,从当前状态确定性地转移到下一个状态。
汽油费
智能合约是个Tuning-complete Programming Model
(因此出现死循环时没办法,Halting Problem)
因此为了防止出现出现死循环,引入了汽油费机制。
- 执行合约中的指令要收取汽油费,由发起交易的人来支付。
AccountNonce:交易序号,防止replay attack
Price:单位汽油的价格
GasLimit:交易愿意支付的最大汽油量
(最大汽油费 = Price * GasLimit)
Recipient:收款人地址
Amount:转账金额
PayLoad:data域,用于存放数据 - EVM中不同的指令消耗的汽油费是不一样的,简单的指令很便宜,复杂或需要存储状态的指令就很贵。
错误处理
以太坊中的交易具有原子性,交易中的事物要么全部执行,要么全部不执行。发生错误之前消耗的汽油费不会退回,因为随意的发起复杂的调用而不给够多的汽油费会使矿工消耗巨大资源。
- 智能合约中不存在自定义的try-catch结构
- 一旦遇到异常,出特殊情况外,本次执行操作全部回滚
- 可以抛出错误的语句:
– assert(bool condition) 如果条件不满足就抛出—用于内部错误
– request(bool condition) 如果条件不满足就抛掉—用于输入或外部组件引起的错误。
– revert() 终止运行并回滚状态变动(无条件抛出异常)
嵌套调用
- 智能合约的执行具有原子性:执行过程中出现错误,会导致回滚
- 嵌套调用是指一个合约调用另一个合约中的函数
- 嵌套调用是否会触发连锁式的回滚?
有些调用方法会引起连锁式的回滚,有些则不会。 - 一个合约直接向一个合约账户里转账,没有指明调用哪个函数,任然会引起嵌套调用。
GasLimit:对区块消耗的资源进行限制(所有汽油费消耗的上限)
GasUsed:区块中所消耗的所有汽油费加在一起。
先执行智能合约再挖矿。
Receipt数据结构
交易执行完成后形成的收据。
address.balance:address的余额
address.transfer(金钱):当前合约向address转入多少金钱(会导致连锁式回滚)
举例
拍卖过程中不允许中途退出,可多次竞拍(补差价即可)。
使用上述代码会产生回滚。