1. Solidity函数、权限、函数修饰符、事件

        a. 函数

            i. 概念:solidity也是一门函数式编程语言,函数可以做为其参数、变量、返回值

            ii. 函数属于值类型,支持多个返回值

            iii. 调用方式:

                1. 内部调用:

                    a. 内部调用采用的是EVM跳转调用,所以它能直接使用上下文环境中的数据,因为不用拷贝数据,所以在传递数据时会非常高效

                    b. 对合约内的函数,引入的库函数以及从父合约中继承的函数都可以进行内部调用

                2. 外部调用

                    a. 外部调用采用外部交易调用,使用external时,必须使用外部的方式调用其它合约的函数。对于一个外部调用,所有函数的参数必须拷贝到内存中。

                3. 注意:上面的internal以及external是指函数的调用方式,与可见性中的internal、external是两个概念

            iv. 函数定义类型

                1. View:只读,不改变合约内部状态

                    a. 以下操作会修改状态

                        i. 写入状态变量.

                        ii. 触发事件

                        iii. 创建其它合约.

                        iv. 使用自毁函数.

                        v. 发送以太币.

                        vi. 调用任何没有被标记为 view 或者 pure的函数.

                        vii. 底层调用.

                        viii. 使用包含一些操作码的内联汇编.

                    b. getter函数会默认标记为view

                    c. 注意,如果有修改状态操作的函数加上view,编译器不会报错,只会给出一个警告

                2. Pure:不会修改合约状态,也不能读取合约状态(可以读取与状态无关的数据)

                    a. 除去view中的限制,还包括以下内容

                        i. 读取状态变量

                        ii. 访问this.balance或者address.balance

                        iii. 访问block,tx,msg任何成员(msg.sig以及msg.data除外)

                        iv. 调用任何没有标记为pure的函数

                        v. 使用包含某些操作码的内联汇编

                    b. 注意:在版本0.4.17之前,编译器没有强制规定pure不能读取状态。

                3. Fallback

                    a. 每一个合约中都有一个没有名字的函数,该函数没有参数,没有返回值,这就是回调函数

                    b. 以下两种情况下会调用回调函数

                        i. 调用合约时,没有匹配上任何一个函数

                        ii. 给合约发送ether时,交易中根本没有提供数据

                    c. 给合约发送ether时,要注意以下情况

                        i. 合约没有定义回调函数的话,接收ehter会触发异常

                        ii. 如果回调函数需要接收ehter,必须要有payable修饰符

                4. 函数重载

                    a. 同名函数可以重载

                5. 自毁函数(selfdestruct)

                    a. 自毁函数可以摧毁当前合约,将该合约的以太币转移到给定的地址

                    b. 注意:如果合约被自毁后有人发送以太币到这个合约地址,那这些以太币会消失,无法赎回

                6. 常函数(constant)

                    a. 常函数不会修改区块链上的任何状态(没有强制规定、会警告)

                7. 访问函数(getter)

                    a. 编译器为自动为所有的public的状态变量创建访问函数

                    b. 访问函数有外部(external)可见性。如果通过内部(internal)的方式访问,比如直接访问,你可以直接把它当一个变量进行使用,但如果使用外部(external)的方式来访问,如通过this.,那么它必须通过函数的方式来调用

                8. 其它内置函数

                    a. 加密函数

                        i. Keccak256(…)returns (bytes32);使用以太坊的(keccak-256)计算hash(该函数会先将所有参数进行连接再计算)

                            1. keccka256("ab","cd")

                        ii. Sha3(…)returns(bytes32);同上

                            1. sha3("ab","cd");

                        iii. Ripemd160(…)returns(bytes20):使用ripemd-160计算hash值,返回bytes20

                            1. ripemd160("abc")

                        iv. Sha256(…)returns(bytes32);使用sha-256计算hash值,返回bytes32

                            1. sha256("def");

                        v. ecrecover(bytes32,byte,bytes32,bytes32) return(address);恢复与公钥相关的地址

                    b. 数据函数

                        i. addmod(uint x,uint y, uint k)returns(uint)// (x+y)%k

                        ii. mulmod(uint x, uint y, uint k)returns(uint)// (x*y)%k

        b. 可见性或权限

            i. 可见性

                1. Internal:不能在当前合约的上下文环境以外的地方执行,内部函数只能在当前合约内被使用。如在当前的代码块内,包括内部库函数,和继承的函数中。默认情况下,函数为internal

                2. external:

                    a. 外部函数由地址和函数方法签名两部分组成。可作为外部函数调用的参数,或者由外部函数调用返回

                    b. external可以通过交易调用、也可以通过其它合约调用

                    c. 如果是用this调用,那它是在通过external的方式调用

                    d. 不能在内部调用一个外部函数

            ii. 权限

                1. Public:公开函数是合约接口的一部分,可以通过内部,其它合约、或者消息来进行调用。对于public类型的状态变量,会自动创建一个访问器

                2. Private:私有函数和状态变量仅在当前合约中可以访问,在继承的合约内,不可访问

                3. 注意:所有在合约内的东西对外部的观察者来说都是可见,将某些东西标记为private仅仅阻止了其它合约来进行访问和修改,但并不能阻止其它人看到相关的信息

        c. 函数修改器(Modifier)

            i. 修改器的作用是在函数执行前检查某种前置条件是否满足,

            ii. Modifier是一种合约属性,可以被继承,还可以被派生的合约重写

            iii. 一个函数可以有多个修改器,其间采用空格或回车分隔,修改器的生效顺序与定义顺序是一样的

        d. 事件(event)

            i. 事件是使用EVM日志内置功能的方便工具,在DAPP的接口中,它可以反过来调用Javascript的监听事件的回调。

            ii. 为什么要有事件?在真实的环境中,发送交易调用智能合约的过程是如下:

                1. 交易发送->打包->被执行 在发送完之后,不会马上返回执行结棍,只能立刻返回交易HASH。所以我们需要通过事件来通知外部实体。

            iii. 事件在合约中可被继承。当被调用时,会触发参数存储到交易的日志中(一种区块链上的特殊数据结构)。这些日志与合约的地址关联,并合并到区块链中,只要区块可以访问就一直存在(至少Frontier,Homestead是这样,但Serenity也许会不一样)。日志和事件在合约内不可直接被访问,即使是创建日志的合约。