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

相关推荐
boyedu16 小时前
区块链应用场景深度解读:从金融革命到社会治理的全方位革新
金融·区块链
_jacobfu1 天前
Foundry 学习笔记 005
笔记·学习·web3·区块链·智能合约
风一流世2 天前
Gas and Gas Price
区块链·solidity
电报号dapp1192 天前
治理代币的质押周期应该如何科学设定?
人工智能·web3·去中心化·区块链·智能合约
Web3_Daisy2 天前
想要抢早期筹码?FourMeme专区批量交易教学
大数据·人工智能·区块链·比特币
MetaverseMan2 天前
以太坊重放攻击
区块链
MicroTech20253 天前
微算法科技基于格密码的量子加密技术,融入LSQb算法的信息隐藏与传输过程中,实现抗量子攻击策略强化
区块链·量子计算
SCIS5883 天前
深入理解区块链 | 去中心化架构与密码学保障
区块链·密码学·数据安全
全栈还没全4 天前
什么是Gas?使用场景以及开发中如何不使用Gas进行开发
区块链