Ethereum(以太坊)里的那些事之第二篇

风险提示

根据银保监会等五部门于 2018 年 8月发布《关于防范以「虚拟货币」「区块链」名义进行非法集资的风险提示》的文件, 请广大公众理性看待区块链,不要盲目相信天花乱坠的承诺,树立正确的货币观念和投资理念,切实提高风险意识;对发现的违法犯罪线索,可积极向有关部门举报反映。

前情提示

上一篇文章大致讲了下什么是区块链和一个最基础的智能合约。合约基础到什么程度呢,基础到只有一个函数。这一篇文章主要带来一个具有写入函数以及权限控制的智能合约。因为是由浅入深,所以跨度不会太大,希望大家可以理解。话不多说,咱们直奔主题。

主题:我就是主题

智能合约的代码如下:

solidity 复制代码
contract SimpleStorage {
    uint public num;

    address internal owner;

    event LogSet(address owner, address caller);

    constructor() {
        owner = msg.sender;
    }

    function set(uint _num) public {
        emit LogSet(owner, msg.sender);
        require(msg.sender == owner, "no permission");
        num = _num;
    }

    function get() public view returns (uint) {
        return num;
    }

    function getOwner() external view returns(address) {
        return owner;
    }
}

Try on Remix

从代码里我们可以看到,定义一个类型为 uint256 且可见性为public的变量num和一个类型为 address 且可见性为internal的变量owner, 且在构造函数里将msg.sender 赋值给 owenr。 msg.sender 是由 solidity 内置的一个东西,其值是变化的。如果是钱包AddressA 部署了 SimpleStorage 合约,则 msg.sender 就是钱包AddressA的地址。如果 SimpleStorage 是通过合约 B 部署的,则 msg.sender 就是合约B的地址。着重看下权限控制代码

ini 复制代码
require(msg.sender == owner, "no permission");

这里通过内置函数require来检查权限,require函数接受两个参数,第一个参数是条件判断表达式,是必选的,第二个参数为要返回的异常消息提醒,该参数是可选的。如果第一个参数的结果为true,则执行require下面的代码,反之则抛出异常,后续的代码也不会执行。

话题好像跑远了,应该测试下功能的😅,为了方便查看owner和函数调用者,我特意加了一个LogSet事件

csharp 复制代码
event LogSet(address owner, address caller);

该事件抛出了owner和函数调用者

scss 复制代码
emit LogSet(owner, msg.sender);

调用set函数并传入参数10,我们看到了输出日志里 owner和caller地址都是我们账户地址0x5B38Da6a701c568545dCfcB03FcB875f56beddC4,并且 num已经被成功设置为10

那如果调用者不是合约的owner呢,让我们眼见为实

如上图所示,我将账户切换为0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2,并传参20给set函数,其结果是合约直接拒绝并抛出错误"no permission",并且num依旧是10,这就意味着权限控制生效了。

题外话

既然讲到了通过合约部署合约,那我们就来测试一下。代码如下:

solidity 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface ISimpleStorage {
    function getOwner() external returns(address);
}

contract SimpleStorage {
    uint public num;

    address internal owner;

    constructor() {
        owner = msg.sender;
    }

    function set(uint _num) public {
        require(msg.sender == owner, "no permission");
        num = _num;
    }

    function get() public view returns (uint) {
        return num;
    }

    function getOwner() external view returns(address) {
        return owner;
    }
}

contract FactoryContract {
    address public owner;

    uint public index;

    constructor() {
        owner = msg.sender;
    }

    function createContract() public returns(address) {
        address c = address(new SimpleStorage{salt: keccak256(abi.encode(msg.sender, index))}());

        index += 1;

        return c;
    }

    function getSimpleStorageOwner(address _addr) public returns(address) {
            return ISimpleStorage(_addr).getOwner();
    }
}

可以看到我们在 FactoryContract 合约里直接通过 new关键字直接创建合约。

我们试试通过 Factory 合约部署 SimpleStorage。

  1. 第一步,我们部署 Factory 合约(地址为:0xDA0bab807633f07f013f94DD0E6A4F96F8742B53),并调用 createContract 函数,并通过函数的返回值拿到了 SimpleStorage 合约地址为 0xAE77aeafd5569aa06Eef08Aff16Ba04e792AEf0f
  1. 第二步,我们通过调用FactoryContract的getSimpleStorageOwner 函数,并传入刚刚 拿到的 SimpleStorage 地址

调用FactoryContract的getSimpleStorageOwner,我们拿到了合约0xAE77aeafd5569aa06Eef08Aff16Ba04e792AEf0f 的owner为0xDA0bab807633f07f013f94DD0E6A4F96F8742B53,和Factory合约地址是一致的。

下集预告

这篇文章主要是给大家介绍了权限控制以及通过合约创建合约,下篇给大家讲下如何通过智能合约实现接收和发送Ether(老值钱了)。

相关推荐
yoona102015 小时前
Rust编程语言入门教程 (七)函数与控制流
开发语言·rust·区块链·学习方法
MetaverseMan2 天前
从sumsub获取用户图片
区块链
电报号dapp1192 天前
区块链虚拟币资产去中心化私钥钱包开发
人工智能·去中心化·区块链·智能合约
漠缠3 天前
股票与比特币投资困境分析及解决方案
人工智能·区块链
AC使者3 天前
解释区块链技术的应用场景和优势。
区块链
YSGZJJ3 天前
怎么查股指期货持仓量?
区块链
yoona10203 天前
Rust编程语言入门教程(三) Hello Cargo
开发语言·后端·rust·区块链·学习方法
yoona10205 天前
Rust编程语言入门教程(二)hello_world
开发语言·后端·rust·区块链·学习方法
电报号dapp1197 天前
开发去中心化应用(DApp)的完整路径:从0到1的实践指南
人工智能·去中心化·区块链·智能合约