【智能合约】Solidity 进阶编程 | 注意一下合约中的细节

简介: 目录1. 内置的全局变量2. 错误处理3. 访问函数4. 创建合约5. 合约继承6. 修饰器modifier最后

目录

1. 内置的全局变量

2. 错误处理

3. 访问函数

4. 创建合约

5. 合约继承

6. 修饰器modifier

最后

补充知识:


转账的话是与部署者无关,与交易者有关!

gas是以太坊网络中的一个计量单位,是为了对算力消耗进行量化而设计的指标,也就是说有了gas这个计算单位,我们可以方便的计算出用户完成一笔交易需要支出多少gas费用,矿工完成一个区块的打包确认能收到多少gas报酬。


1. 内置的全局变量

msg.sender:

获取调用者地址,下面的例子是部署者调用了,所以是部署者的地址,

比如a账户部署,但是是使用b账户调用下getOwner的话,那么这个时候的owner就是b账户的地址了。


pragma solidity 0.4.22;
contract Owner {
    address public owner;
    function getOwner() public {
        owner = msg.sender;   // 获取调用者的地址
    }
}


msg.value:

可以接收payable修饰的转账金额,单位:wei,必须要有payable


可以用接收的value进行判断限制,比如转账金额必须在某个范围,balance做不到

pragma solidity 0.4.22;
contract Value {
    uint256 public money;
    function getValue() public payable {
        money = msg.value;
    }
}


如果加if判断:


pragma solidity 0.4.22;
contract Value {
    uint256 public money;
    function getValue() public payable {
        if( msg.value == 666) {  // 转钱金额为666wei才赋值 
            money = msg.value;
        }
    }
}


注意:需要转钱,注意单位默认是wei

image.png

2. 错误处理

require:

require 式的异常不会消耗任何 gas,官方推荐使用require,相当于if {throw},没有else的

最终底层触发的也是assert式的错误

require(msg.value == 666);    // 如果不满足则报错,否则继续往下执行

类似于下面的:注意条件正好是相反的

if (msg.value <= 6 * 10 ** 18)  {
    // todo 涉及到错误处理
    throw;
}


assert:

即使有错误,也会执行并扣除gas

assert(msg.value == 666 );    // 如果不满足则报错,否则继续往下执行

revert():处理更复杂逻辑的场景,比如if/else

if (msg.value <= 6 * 10 ** 18){
    revert();
} else {
    b = 666;
}


require(条件); 如果满足条件则继续往下执行,如果不满足则报错,不扣除gas,推荐使用

assert(条件); assert扣除gas,不推荐使用

revert(): 负责逻辑中使用,if(条件){revert();}else{…}

3. 访问函数

原来要返回一个变量,得写个函数返回


pragma solidity 0.4.22;
contract Hello {
    string name = "hallen";
    function get_name() public view returns(string){
        return name;
    }
}


如果用public修饰了变量,会生成一个同名的访问函数,可以直接访问

pragma solidity 0.4.22;
contract Fan {
    string public name = "fanone";
    function getName() public view returns(string){
        return name;
        // return this.data(); 合约内部使用this也是要调用访问函数的
    }
}
contract One {
    function getHelloName() public view returns (string){
        Fan h = new Fan();   // 地址直接强转合约类型
        return h.name();    // 这里必须加括号,是个访问函数
    }
}

4. 创建合约

new : 返回的是地址,需要转合约类型

初始化合约的时候用到这种方式

Fan h = new Fan();  // 把地址直接强转为合约类型


和java有点像

合约变量(Fan public h),此时是空的,需要赋值地址才能使用,否则报错

合约类型作为参数的场景用到这种方式


Fan public h;
// 函数中赋值
address addr = new Fan();
h = Fan(addr); // 赋值地址


转账语法:

h.get_money.value(20).gas(800)();


h必须是赋值地址后的合约对象


pragma solidity 0.4.24;
contract Test1{
    // 获取转账钱
    function contractGetMoney() public payable{
    }
    // 查看余额
    function getBalance() public view returns(uint256){
        return address(this).balance;
    }
}
contract Test2 {
    // 查看余额
    function getBalance() public view returns(uint256){
        return address(this).balance;
    }
    // 获取转账钱
    function contractGetMoney()public payable{
    }
    // transfer:谁调用就给谁转钱
    Test1 public t1;
    function getAddr(address addr) public{
        t1 = Test1(addr);
    }
    // 转钱给Test1合约
    function payToT1() public{
        t1.contract_get_money.value(5 * 10 **18).gas(200)();
    }
    // 付钱得用payable修饰,使用匿名函数
    function () public payable {}
}

5. 合约继承

使用is关键字,多个父合约用逗号隔开

contract 合约名 is 父合约1,父合约2,… {}

constract Cat is Animail,Lactation{} // Lactation:哺乳动物

如果两个父合约中有相同的函数,则遵循最远继承原则(继承顺序,Animail最近,Lactation最远,所以是Lactation中的)

6. 修饰器modifier

在函数执行前检查是否满足前置条件,满足条件才执行函数


pragma solidity 0.4.22;
contract Value {
    uint256 public money;
    modifier check_money(){
        require(msg.value == 10);
        _;  // 修饰的代码,指进入函数后的所有代码
    }
    function get_value() public payable check_money{  // check_money就是前面定义的修饰器
        money = msg.value;
    }
}


可以结合构造函数,判断是不是管理员(部署者),只有是管理员才可以访问的函数可以加修饰器

pragma solidity 0.4.22;
contract Value {
    address public owner;
    uint256 public money;
    constructor() public{
        owner = msg.sender;
    }
    modifier check_owner(){
        require(msg.sender == owner);
        _;   // 修饰的代码,指进入函数后的所有代码
    }
    function get_value() public payable check_money{
        money = msg.value;
    }
}


最后

小生凡一,期待你的关注。

image.png


相关文章
|
存储 前端开发 JavaScript
区块链智能合约编程语言 Solidity
上文介绍了[区块链生态发展](https://wangbinguang.blog.csdn.net/article/details/131440404),我们知道以太坊的到来可以使开发人员基于区块链开发DApp,本文介绍 Solidity 编程语言的使用,然后基于 Solidity 编写一个简单的智能合约。
130 1
|
存储 前端开发 Unix
一文聊透 Solidity 语法:助你成为智能合约专家(二)
一文聊透 Solidity 语法:助你成为智能合约专家
109 0
|
存储 Rust JavaScript
一文聊透 Solidity 语法:助你成为智能合约专家(一)
一文聊透 Solidity 语法:助你成为智能合约专家
249 0
|
存储 安全 区块链
浅谈以太坊智能合约的设计模式与升级方法
浅谈以太坊智能合约的设计模式与升级方法 作者:fisco-dev  https://github.com/FISCO-BCOS/Wiki 浅谈以太坊智能合约的设计模式与升级方法 1.
1702 0
|
Go 数据安全/隐私保护
Solidity笔记-合约间的互相调用
Solidity笔记-合约间的互相调用
239 0
|
存储 区块链 数据库
Solidity开发智能合约
一个简单的智能合约 在Solidity中,一个合约由一组代码(合约的函数)和数据(合约的状态)组成。合约位于以太坊区块链上的一个特殊地址。
1521 0
|
存储 编译器 区块链
【一步步一起学DApp开发】(三)Solidity语言讲解 | 用Solidity编写智能合约 上
【一步步一起学DApp开发】(三)Solidity语言讲解 | 用Solidity编写智能合约
573 0
|
存储 JavaScript 前端开发
【一步步一起学DApp开发】(三)Solidity语言讲解 | 用Solidity编写智能合约 下
【一步步一起学DApp开发】(三)Solidity语言讲解 | 用Solidity编写智能合约
253 0
|
存储 JavaScript 前端开发
【智能合约】Solidity 基础知识 | 以太坊智能合约编程语言
目录 注意事项 编译器选择 一些说明 1. 变量 1.1 状态变量 1.2 局部变量 2. 数据类型 2.1 值类型 2.1.1 布尔类型(Booleans): 2.1.2 整型(Integers): 2.1.3 定长浮点型(Fixed Point Numbers): 2.1.4 定长字节数组(Fixed-size byte arrays) 2.1.5 有理数和整型常量(Rational and Integer Literals) 2.1.6 枚举(Enums) 2.1.7 函数类型(Function Types) 修饰符 函数定义 函数返回值 构造函数 2.1.8 地址类型(Address)
426 0
【智能合约】Solidity 基础知识 | 以太坊智能合约编程语言
|
存储 Java 区块链
6分钟以太坊实战 - 智能合约与Solidity高级语言(一)
1. 简介 合约是存放在以太坊区块链具有特定地址的代码和数据集合。 合约账户之间可以相互传递消息以实现图灵完备运算。 合约以以太坊特定的二进制字节码通过以太坊虚拟机(EVM)运行于区块链上。目前,合约通常是以Solidity(一门长得很像js的语言)高级语言编写,编译后传到区块链上运行。
9616 0