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

相关推荐
软件工程小施同学11 小时前
区块链可投会议CCF C--ICDF2C 2025 截止5.31 附录用率
区块链
Sui_Network13 小时前
Sui Basecamp 2025 全栈出击
大数据·游戏·web3·去中心化·区块链
金融数据出海1 天前
黄金、碳排放期货市场API接口文档
java·开发语言·spring boot·后端·金融·区块链
cainiao0806051 天前
Bitcoin跨链协议Clementine的技术解析:重构DeFi生态的信任边界
区块链
这个懒人2 天前
ERC-20与ERC-721:区块链代币标准的双星解析
人工智能·区块链
数据与人工智能律师2 天前
私服与外挂:刑事法律风险的深度剖析
大数据·人工智能·算法·云计算·区块链
电报号dapp1192 天前
DeFi开发系统软件开发:技术架构与生态重构
重构·架构·web3·去中心化·区块链·智能合约
电报号dapp1192 天前
公链钱包开发:技术逻辑与产品设计实践
web3·去中心化·区块链·智能合约
QQ39903850232 天前
香港国际交易节奏解析:结构性波动背后的信号逻辑
区块链
这儿有一堆花3 天前
什么是智能合约?区块链上的自动化契约
自动化·区块链·智能合约