以太坊智能合约简要教程


  • 管理员

    智能合约的构成

    智能合约就是一段执行在以太坊区块链上的脚本,也就是一段程序。程序的构成包括:数据、代码、数据结构,这是从内部构成看,计算机行业术语叫做白盒思路。另外一种思路是把这段程序看做一个黑盒,其组成就是输入、输出。两种思路都是把这段程序想象成一个盒子,第一种是拆开看里面具有有哪些部件,第二种是研究盒子跟外界的关系。我们会结合两种思路进行学习。

    开发环境

    为了更好的学习智能合约,我们需要选取一个好用、容易上手的工具,今天给大家介绍的就是truffle这个工具,这个工具是用nodejs/javascript开发的以太坊智能合约的开发框架,要使用truffle,必须安装一个以太坊的运行环境或模拟环境,我们学习,可以使用模拟环境,也就是以太坊的testrpc工具。下面我们介绍一下安装开发环境的步骤:

    1. 安装truffle
    $ npm install -g truffle
    
    1. 安装ethereumjs-testrpc
    $ npm install -g ethereumjs-testrpc
    
    1. 启动testrpc
    $ testrpc
    
    1. 重开一个命令行窗口,创建工程目录,进入并创建项目
    $ mkdir hellosol
    $ cd hellosol
    $ truffle init
    
    1. 编译智能合约
    $ truffle compile
    
    1. 分发
    $ truffle deploy
    

    语法概要

    注释

    单行注释(//)和多行注释(/.../)都是可以的,而在函数声明前的三斜线注释(///)要引入NatSpec注释(不属于这里的讨论范围)。

    类型

    目前实现的(基本)类型有布尔(bool),整数和固定长度的字符串(从string0到string32)类型。整数类型有不同位长的符号型和无符号型(从int8/uint8到int256/uint256,步长为8位。其中uint/int是uint256/ int256的别名),散列=hash(从hash8到hash256,步长为8位 hash是hash256的别名)及地址= addresses(160位)。

    比较运算符

    比较运算符(<=, !=,==,等)的比较最终会产生布尔型(booleans),而布尔型(booleans)可以用&&, || 和 !连接起来。通常的短路原则也适用于&& 和 ||,也就是说(0 < 1 ||fun()) 这样的形式的表述的话,函数func()永远不会被调用。因为0<1永远是返回true,所以 || 后面的结果无论如何都是返回true,这样 || 后面的语句不会被执行。

    类型转换

    如果操作符被应用到不同类型的整数,所述编译器试图隐式的转换操作数中的一个到另一个的类型(对于代入也是如此)。在一般情况下,如果在语义上讲得通,并且不丢失任何信息的话,隐式转换是可能的:uint8可以转换为uint16,int120到int256,但int是无法转换为uint256。此外,无符号整数可以被转换为相同的或更大的散列,反之则不成立。任何可以转换到hash160的类型也可以转换为地址(address)类型。

    整数字面值

    只要整数字面值与自己相结合,它的类型就没有被决定。最好用例子来解释:
    var x = 1 - 2;
    1 - 2的值是-1,它被分配给x,因而x得到int8类型- 包含-1的最小类型。但是下面的代码片段的表现则有所不同:
    var one = 1;
    var two = 2;
    var x = one - two;

    以太货币单位

    “Wei”、“Finneny”、“Szabo”、“Ether”等字面数字可以作为子货币面额的后缀,无后缀的数字被视为是Wei,如 : 2 Ether==2000Finney,判别为真。

    wei :音译为“微、卫、伟等”(后文中取“微”),Ethereum中最小货币面额单位,等同于Bitcoin的聪,类似美元中的美分,英镑中的便士;
    10^3: Kwei,千微。
    10^6: Mwei,百万微。
    10^9: Gwei,十亿微。
    10^12: szabo,取自Nick Szabo,译为“萨博”,简称“萨”。
    10^15: finney,取自Hal Finney,译为“芬尼”,简称“芬”。
    10^18: ether,以太,以太币基本货币单位,类似人民币元,Bitcoin的BTC单位。

    控制结构

    大多数C和JavaScript的控制结构都可以用在solidity里,除了switch(未计划)还有goto(貌似不严谨)。所以下列控制结构时可用的:if, else, while, for, break, continue, return。
    注意不像在C和JavasScript里,Solidity里没有从非布尔型转换布尔型的类型转换,所以if(1)在Solidty里是无效的。

    函数调用

    目前合约的函数,可以直接也可以递归的被调用,如在本示例(代码本身无意义)所显示的:

    contract c {
      function g(uint a) returns (uint ret) { return f(); }
      function f() returns (uint ret) { return g(7) + f(); }
    }
    

    举个简单的栗子

    • 数据存储
    // contract 关键字等同于java里面的class关键字
    contract SimpleStorage {
       
        // 成员字段声明:类型 名称
        uint storedData;
    
       // 函数声明,设置数据
        function set(uint x) {
            storedData = x;
        }
    
        // 获得数据,该函数不会修改内部字段
        function get() constant returns (uint retVal) {
            return storedData;
        }
    }
    
    • 货币
    contract Coin {
        // 关键字 "public" 把该字段设为外界可读取
        address public minter;   // minter表示零钱
        // 账户余额映射表
        mapping (address => uint) public balances;
    
        // 事件机制可以让客户端高效获得通知
        event Sent(address from, address to, uint amount);
    
        // This is the constructor whose code is
        // run only when the contract is created.
        function Coin() {
            minter = msg.sender;
        }
    
        function mint(address receiver, uint amount) {
            if (msg.sender != minter) return;
            balances[receiver] += amount;
        }
    
        function send(address receiver, uint amount) {
            if (balances[msg.sender] < amount) return;
            balances[msg.sender] -= amount;
            balances[receiver] += amount;
            Sent(msg.sender, receiver, amount);
        }
    }
    

    这个合约引入了一些新的概念。其中之一是address类型,这是一个不允许有任何算术运算的160位的值。此外,状态变量balance是一个复杂的数据类型,它映射address到无符号整数。映射可以被看作是哈希表,在实际初始化后,每一个可能存在的键都被映射到一个字节表示是全零的值。Coin这个特别的函数是构造函数,在合约被创建时运行,并且以后不能被调用。它永久存储这个合约创建人的地址。同tx和block一起,msg是一个神奇的全局变量,包含了一些属性,允许合约访问外部世界。函数queryBalance被声明为constant(常量类型),并且因此不允许修改合约的状态(注意,虽然尚未强制执行)。在Solidity中,返回“参数”被是命名的,本质上即建立了一个局部变量。所以返回balance时,我们只需使用bal = balance[addr]; 没有任何return语句。



  • @bitchain 是的, 只是看到货币 contract 下面的文字解释有 “函数queryBalance被声明为constant(常量类型),并且因此不允许修改合约的状态(注意,虽然尚未强制执行)”,才想着是不是没有贴出来。


  • 区块链研究

    @nanfanghaizi 你直接查询某人的address对应的余额就可以了


  • 区块链研究

    @nanfanghaizi 没有一个这样的函数



  • 最后的货币 contract , queryBalance函数没有贴出来



与 区块链大学 | qkldx.net 的连接断开,我们正在尝试重连,请耐心等待