智能合约是以太坊的精髓,也是比特币和以太坊最大的区别。智能合约是运行在区块链上的一段代码,代码的逻辑定义了合约的内容。智能合约的账户保存了合约当前的运行状态.

合约如何调用另一个合约的函数:

1.直接调用

错误处理:如果调用的合约在执行过程中出现错误,会导致发起调用的合约也会一起回滚

2.使用address类型的call()函数

错误处理:如果被调用的合约在执行中出现异常,call函数会返回false,发起调用的函数还是能够继续执行。

3.代理调用

智能合约

外部账户发起一个转账交易到0x0的地址,转账的jine为0,但是需要支付gas费,同时编写的智能合约代码放入data域,运行在EVM上。

gas费

为了防止智能合约中出现死循环、恶意节点攻击等,运行代码需要消耗gas费,全节点收到合约调用的时候,会在运行之前会扣除预计的最大gas费,如果代码消耗大于了预扣的gas费,合约还没有运行完成,那么这个时候就会回滚状态。已经消耗的gas费不会退回。

因为以太坊区块大小的限制,而智能合约需要消耗的资源很大,所以需要根据交易的具体操作进行收费。gas limit是区块中所有交易能够消耗的gas费的上限。发布区块的矿工,能够上调或者下调上一个区块的1/1024大小。

应该先挖矿还是先执行合约?

状态树、交易树、收据树都是由全节点在本地维护,所以扣gas费的时候就在状态树中自行减去预计的gas费,在发布区块的时候,需要先执行智能合约之后再进行挖矿,以太坊挖矿计算哈希的时候需要使用到三棵树的哈希值,所以需要先执行合约才能进行挖矿。

其他执行了智能合约的没有争取到记账权的挖矿全节点,以太坊不会给出补偿,并且每个区块还要独立验证发布区块的正确性。

如果存在矿工因为没有得到记账权而不验证新区块的合法性?

区块链的安全由所有全节点独立验证发布区块的合法性,防止恶意区块篡改等。但是区块一般不会不验证新区块的合法性,因为如果不在本地执行更新状态树、交易树、收据树那么区块将无法再进行新一轮的挖矿。

错误处理

以太坊的交易具有原子性:要么全部执行,要不执行失败,不会只执行一部分。

执行失败的几种情形:1.gas费不够

抛出错误的语句:

1. assert(bool condition)适用于内部错误的条件不满足抛出

2. require(bool condition)适用于输入或者外部组件引起错误-条件不满足抛掉

3. revert() 终止运行饼回滚状态变动

嵌套调用

在执行的时候,如果合约中调用了另一个合约,被调用的合约出现错误,如果是使用直接调会出现连锁式回滚,如果是call调用则不会

发布到区块链上的智能合约是否都是成功执行的?执行失败的交易是否要发到链上?

区块链上的合约并不是都是成功执行的,执行失败的智能合约也需要发布到区块链上,否则将无法扣除gas费(在本地状态树上将gas费扣点,如果不发布到区块链上形成共识,那么无法扣掉gas费)

如何知道交易执行成功?

每个交易执行完之后会形成一个收据

其中status就是存储交易执行情况内容

智能合约是否支持多核并行处理?

solidity不支持多线程,其没有支持多线程的语句。多线程中多个核对内存访问顺序不同的话,结果有可能是不确定的。

以太坊是一个交易驱动的状态机,给定的智能合约所产生的输出、状态都需要是完全相同。因为所有全节点都需要执行一组操作,到达同一个状态才能验证通过,如果状态不确定则三棵树的内容不同、根哈希也就不同、从而无法通过验证。

除了多线程之外,导致执行效果不相同的操作也就不被允许的,例如:随机数产生(如果不同的机器产生的随机数都相同的话,也就不能被成为随机数),以太坊下的智能合约无法产生真正意义上的随机数。

地址类型

如果转账失败 transfer会导致连锁性回滚,而send会返回一个false,不会导致连锁性回滚。两者都专门用来转账的,在发动时需要gas2300,导致除了转账其他的操作基本无法执行

call,本意是用来函数调用,但也能够进行转账(转账的时候会将剩余的gas都转过去),.call.value(uint256 amount)()。不会引起连锁式回滚

【注:是当前地址向address进行转账而不是,而不是address进行转账】