函数(Functions)
函数的声明方式如下:
function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]
函数调用
两种方式
- 内部调用,调用同一个合约的内部函数,不会发起EVM信息调用
- 外部调用,调用其它合约的外部函数,会发起EVM信息调用
View函数
view函数
是指不修改合约状态的函数。
修改合约状态的行为有:
- Writing to state variables.修改状态变量
- Emitting events.触发事件
- Creating other contracts.创建其它合约
- Using selfdestruct.使用销毁函数
- Sending Ether via calls.发送eth币
- Calling any function not marked view or pure.调用其它非view和pure的函数
- Using low-level calls.使用底层api
- Using inline assembly that contains certain opcodes.使用内联汇编
constant常量函数
和view函数
其实是一样的
Getter访问函数
也是view函数
Pure函数
Pure函数
是指不修改、且不读取合约状态的函数。
读合约状态的行为有:
- Reading from state variables.读取状态变量
- Accessing this.balance or <address>.balance.访问账户余额
- Accessing any of the members of block, tx, msg (with the exception of msg.sig and msg.data).访问block,tx,msg对象
- Calling any function not marked pure.调用其它非view和pure函数
- Using inline assembly that contains certain opcodes.使用内联汇编
Fallback函数
每一个合约有且仅有一个没有名字的、没有参数、没有返回值的函数——Fallback函数
。
contract SimpleFallback{
function(){
//fallback function
}
}
Fallback函数被调用的方式有:
- 没有匹配上任何一个函数
- 没有传哪怕一点数据
address.call()
调用合约函数时,如果没有匹配上任何一个函数,就会调用默认的回退函数。
address.send(ether to send)
向某个合约直接转帐时,由于这个行为没有发送任何数据,所以接收合约总是会调用fallback函数。
注意:
如果我们要在合约中通过send()函数接收,就必须定义fallback函数,否则会抛异常。
fallback函数必须增加payable关键字,否则send()执行结果将会始终为false。
Fallback函数的限制
send()
函数总是会调用fallback
,这个行为非常危险,著名的DAO被黑也与这有关。如果我们在分红时,对一系列帐户进行send()
操作,其中某个做恶意帐户中的fallback
函数实现了一个无限循环,将因为gas
耗尽,导致所有send()
失败。为解决这个问题,send()
函数当前即便gas
充足,也只会附带限定的2300gas
,故而fallback函数内除了可以进行日志操作外,你几乎不能做任何操作。如果你还想做一些复杂的操作,解决方案看这里:http://me.tryblockchain.org/blockchain-solidity-fallback-bestpractice.html。
下述行为消耗的gas都将超过fallback函数限定的gas值:
- 向区块链中写数据
- 创建一个合约
- 调用一个external的函数
- 发送ether
所以一般,我们只能在fallback函数中进行一些日志操作: