以太坊智能合约学习笔记(一)

什么是智能合约(Smart Contract):

最简单的理解,我们所说的智能合约就是区块链上自动运行的一段程序。而基于Ethereum的智能合约就是我们接下来所要学的以太坊智能合约。这里,在我们的Smart Contract中,具体的代码经过solidity编写后,发布到区块链上。而以太坊的智能合约也可以理解为一个特殊的交易(包括可执行的代码),被发送出去后会被矿工打包记录在某一区块中。


在这一系列笔记中,我们将以实例为基础,讲解智能合约开发的流程。首先我们将一起建立一个基础的单员工薪酬系统,并在后续一步步进行完善。

源码地址:https://github.com/Chlover/Team-J/blob/master/Lesson-1/orgin/payroll.sol


版本声明:

//声明程序版本
pragma solidity ^0.4.14
因为Solidity大多是开源的程序,所以要在程序的最开始声明程序版本,方便社区合作。

^表示向上兼容,^0.4.14表示solidity的版本在0.4.14~0.5.0(不包含0.5.0)的版本都可以对上面的合约代码进行编译,0.4.18,0.4.20等等可以用来修复前面solidity存在的一些bug


声明Contract:

// 声明一个Contract
contract Payroll {

} 

Solidity是一门面向对象编程的语言,语法较为贴近JavaScript。其中合同的声明就类似于声明一个Class。


状态变量声明:

// 声明一个Contract
contract Payroll {
    address Owner; 
    uint salary;
    address employee;
    uint lastPayday;
 } 

变量初始值均为0状态,address变量初始化即为0x0。

另外注意在solidity源代码中,地址就是一串十六进制数,不需要加双引号,但是在Remix的对话界面中输入address时,一定要加双引号,不然会报错。这是因remix传入是是json格式,对于不加双引号的值会作为为int处理,加了引号才算bignumber。这里的int指的是js的int,地址明显超过范围,类似的输入一个超大int256数也要加引号。


构造函数:

function Payroll() {
    owner = msg.sender;
}

函数名和合约名相同时,此函数是合约的构造函数,当合约对象创建时,会先调用构造函数对相关数据进行初始化处理。此处相当于在合约创建时就直接将合约的创建者设为owner,后续将保证只有owner可以更新雇员信息。


具体功能的函数实现:

function addFund() payable returns (uint) {
    return this.balance;
}

用addfund函数向合约里加钱。值得注意的是payable关键字,当函数有payable关键字的时候,就表明即可接受ether,并会把ether存在当前合约。http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html?highlight=payable

returns后面加函数返回值的类型。


接下来这一部分我们要实现的是更新雇员信息的功能:

function updateEmployee(address e, uint s) {
    require(msg.sender == owner);
    
    if (employee != 0x0) {
        uint payment = salary * (now - lastPayday) / payDuration;
        employee.transfer(payment);
    }
    employee = e;
    salary = s * 1 ether;
    lastPayday = now;
 }

首先可以发现新出现require语句。后面我们还将见到assert,这里我们放在一起讲解:

requireassert都是用于处理error的,二者可以用于判断某一条件,若条件不被满足则throw exception。其中,require主要用于检查输入值,而assert则主要用于检查internal error

  • The assert function should only be used to test for internal errors, and to check invariants.
  • The require function should be used to ensure valid conditions, such as inputs, or contract state variables are met, or to validate return values from calls to external contracts.
  • https://solidity.readthedocs.io/en/develop/control-structures.html#error-handling-assert-require-revert-and-exceptions

另外,触发assert会消耗所有的gas,而触发require则会把剩余的gas返还。

  • assert(false) compiles to 0xfe, which is an invalid opcode, using up all remaining gas, and reverting all changes.
  • require(false) compiles to 0xfd which is the REVERT opcode, meaning it will refund the remaining gas.
  • https://ethereum.stackexchange.com/questions/15166/difference-between-require-and-assert-and-the-difference-between-revert-and-thro


中间我们略过一下简单的函数不讲,直接进行最后getPaid函数的说明:

function getPaid() {
    require(msg.sender == employee);
    
    uint nextPayday = lastPayday + payDuration;
    assert(nextPayday < now);

    lastPayDay = nextPayday;
    employee.transfer(salary);
 }

这里我们就应用了上面提到的requireassert,这里的require要求调用getPaid也就是领取工资的人一定要是雇员。

对于employee.transfer(salary)和前面我就已经见到的msg,我们将在下一篇文章中一起总结。


接下来,我们将在https://remix.ethereum.org测试我们写的智能合约

以太坊智能合约学习笔记(一)_第1张图片

首先,我们现在的合约的environment是JavaScript VM,也就是没有真正部署上链的,在后面我们会讲到部署方法,但是最开始的阶段,我们的合约就在JavaScript VM上进行测试。选择以后,remix会自动帮我们生成一些地址,自己也可已经添加,供我们测试使用。

在Settings中我们可以选择solidity版本,由于是向上兼容的,我们只要选择高于0.4.14的版本即可,系统会自动为我们compile,没有报错的话就可以点击Create按钮了。

以太坊智能合约学习笔记(一)_第2张图片

我们会注意到右上角的Value有一个单位wei这是solidity里的最小单位,我们比较常用的是ether1 ether = 10^18 wei。这时候我们在Value填入我们想add的数值,并调用addFund函数就可以将该数量金额的eth转入合约。

切记,在测试updateEmployee和getPaid函数时,要把右上角的Account换成相应的owner或employee地址,这样才能满足require(msg.sender == 相应地址)


到目前为止,我们就跟着流程把一个简单的单员工薪酬系统的合约运行了起来,对Solidity也有了大体的了解,在下一篇文章中,我们将对在Solidity的一些基础知识、语法进行补充。



你可能感兴趣的:(智能合约,Solidity,以太坊)