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(老值钱了)。

相关推荐
星尘安全2 小时前
安全工程师入侵加密货币交易所获罪
安全·区块链·漏洞·加密货币
Thanks_ks5 小时前
探索计算机互联网的奇妙世界:从基础到前沿的无尽之旅
物联网·云计算·区块链·tcp/ip协议·计算机互联网·万维网·未来科技
BlockOne115 小时前
应用链风口下,一键发链该如何选择?
区块链
Footprint_Analytics5 小时前
Footprint Analytics 助力 Sei 游戏生态增长
游戏·web3·区块链
BSV区块链5 小时前
如何在BSV区块链上实现可验证AI
人工智能·区块链
电报号dapp1195 小时前
DeFi 4.0峥嵘初现:主权金融时代的来临
金融·区块链
搬砖的小码农_Sky9 小时前
什么是零知识证明?
区块链·密码学·零知识证明
TinTin Land9 小时前
高活跃社区 Doge 与零知识证明的强强联手,QED 重塑可扩展性
区块链·零知识证明
Roun31 天前
去中心化存储:Web3中的数据安全新标准
web3·去中心化·区块链
请不要叫我菜鸡1 天前
分布式——一致性模型与共识算法
分布式·后端·区块链·raft·共识算法·zab