我们上一篇文章对 nest2.0 整体架构做了一个说明,本文则对每个文件进行进一步的解释。

前言

nest2.0 一共七个文件在上一篇文章里面已经说过了。其中最重要的两个文件是 token 部分和合约映射部分。前者是 nest 的 token 基石,而后者则为了 nest 合约的灵活升级做了准备。我们在本文对这两个合约做简要的解释。我们通过对合约地址的查询可以看到。最早的 NESTtoken,也就是 IBNEST,这个合约是 2019 年 5 月份部署的;而后面的几个合约都是 2020 年上半年部署的;这就是为什么整个 nest2.0 看起来似乎很不太协调,因为整个项目的跨度达到了一年左右

1. 基本概念——mapping

先特别说明一下,在 nest2.0 里面的很多地方都用到了 mapping。我在这里简单的讲一下。solidity 里的映射可以理解为 python 里的字典,建立键-值的对应关系,可以通过键来查找值,键必须是唯一的,但值可以重复。

定义方式为:mapping (键类型 => 值类型),例如 mapping(address=>uint) public balances,这个映射的名字是 balances,权限类型为 public,键的类型是地址 address,值的类型是整型 uint,在 solidity 中这个映射的作用一般是通过地址查询余额。键的类型允许除映射外的所有类型。maping 是根据定义的类型确定名次 mapping (a=>b) mmm。表示 mmm 是一个数组名字,其数组类型是 a,赋值的类型是 b。

例如:映射 balances 中包括三个键值对(user1:100,user2:145,user3:195), 输入 user2 即可得到 145

下面来看一个例子:

    contract MappingExample{  
        mapping(address => uint) public balances;  
        function update(uint amount) returns (address addr){  
            balances[msg.sender] = amount;  
            return msg.sender;  
        }  
    }  

说明:定义 balances 为一个映射,msg.sender 是合约创建者的地址,函数 update 有一个整型参数 amount (数量), balances[msg.sender]=amount 的意思是将参数 amount 的值和 msg.sender 这个地址对应起来。好了,接下来我们说两个合约,NESTtoken 和 IBMapping。

2. NESTtoken

NESTtoken 基于的是 IBNEST.sol 基本上就是一个 erc20,没有什么特别额外的功能。这个里面唯一值得注意的是 library IterableMapping 。library IterableMapping 在这里起到了一个顺序可查询与删除的功能。

3. IBMapping

然后是 IBMapping。主要是三个功能:第一个功能是制作一个智能合约映射图;第二个功能是在初始化中,将创建者的地址设置为管理员用户,并提供修改和查询功能;第三个功能是提供智能合约映射的修改和查询。我们一个个说。

3.1 Superman

我们注意到的第一个内容就是 Superman (超级管理者)。

    mapping (address => bool) owners;          // Superman address  
     /** 
        * @dev Initialization method  
        */  
     constructor () public {  
      owners[msg.sender] = true;  
     }  

所有者是一个数组。智能合约的构造者就是所有者里面的真。

3.2 地址对应

    function addContractAddress(string memory name, address contractAddress) public {  
      require(checkOwners(msg.sender) == true);  
      ContractAddress[name] = contractAddress;  
     }  

这个表示的是,发送者的所有者权限有效,那么将 ContractAddress 里面 name 赋值为 contractAddress) ,说白了就是将两者对应起来。这是一个非常关键的内容,应该学习。

3.3 合约引用

首先添加在要引用的合约里面结构体和函数

    contract IBMapping {  
        function checkAddress(string memory name) public view returns (address contractAddress);  
        function checkOwners(address man) public view returns (bool);  
    }  

在要执行的结构体里面定义这个结构体

    IBMapping mappingContract;   

然后在要执行的结构体里面初始化

     constructor(address map) public {  
            mappingContract = IBMapping(map);   
                    // 这句是对外部地址 map 进行结构体定义,这里定义的是 IBMapping.sol 的合约地址。  

并将 map 里面的 IBMapping 与 mappingContract 对接,也就是找到智能合约对接表。

            nestContract = IBNEST(address(mappingContract.checkAddress("nest")));  
     mappingContract.checkAddress("nest")=addrnest  
    // 这个获取的是 nest 对应的合约地址  

3.4 关于合约映射与引用的说明

关于合约映射与引用源码部分还有三个说明。首先之所以做成这样是,是为了可以随时升级合约地址的位置。其次,为了便于管理,将检测到的合约地址对接如下:address(addrnest) 表示显式转换,因此就是 nestContract 获得的是 token 的合约地址。最后,一个 addr 不用转换因为默认就是 addr,第二个因为是从列表里读的,所以从 address payable 转换为 address。区别在于,前者地址可用 .transfer() 和 .send() 方法,后者不可以,防止越权。但不不意味着 mappingContract 和 nestContract 不是 payable 类型。

关于 nest2.0 智能合约的架构解析二(NESTtoken 与 IBMapping)