狗哥区块链与AI精品内容集@NonceGeek

2025年03月28日更新 75 人订阅
原价: ¥ 20 限时优惠
专栏简介 「造」最关键的是什么?| Hackathon 漫游指南(贰) Why Hackathon?| Hackathon 漫游指南(壹) 设计「众人维护」的 BuidlerBoard | BeWater.xyz Movement 白皮书中文版 Rebuidl RSS 生产因素与反生产因素 | 独立黑客创业手册(陆) 组织 | 独立黑客创业手册(伍) 生产 | 独立黑客创业手册(肆) 销售 | 独立黑客创业手册(叄) 最优先的能力 | 独立黑客创业手册(贰) 为什么从独立黑客开始 | 独立黑客创业手册(壹) Aptos Token Object V2 | Move dApp 极速入门(贰拾肆) 可編程交易塊 | Move dApp 極速入門(貳拾叁) Aptos 密鑰輪換 | Move dApp 極速入門(貳拾貳) Aptos 对象模型 | Move dApp 极速入门(贰拾壹) Aptos Moveflow SDK使用指南 | Move dApp 极速入门(贰拾) Sui 上简单 Swap 的实现 | Move dApp 极速入门(拾玖) 用 Elixir 交互 Aptos | Move dApp 极速入门(拾捌) Sui 链上数据查询 | Move dApp 极速入门(拾柒) SUI 合约测试攻略 | Move dApp 极速入门(拾陆) Sui 数据类型详解 | Move dApp 极速入门(拾伍) Airdropper Contract in Aptos | Move dApp 极速入门(拾肆) Sandwich合约源码解析 | Move dApp 极速入门(拾叁) Sui 极速上手 | Move dApp 极速入门(拾贰) scaffold-aptos 脚手架 | Move dApp 极速入门(拾壹) 对 DID Document 的思考 | Move dApp 极速入门(九) DID中地址聚合器的实现 | Move dApp 极速入门(八) 值的存取应用3.0 | Web3.0 dApp 开发(五) 合约数据类型综述 | Move dApp 极速入门(四) 操作资源 | Move dApp 极速入门(三) 第一个 Move dApp | Move dApp 极速入门(二) Hello Move | Move dApp极速入门(一) Staker | Web3.0 dApp 开发(九) Token 自动售卖机 | Web3.0 dApp 开发(七) SVG NFT 全面实践 | Web3.0 dApp 开发(六) 值的存取应用2.0 | Web3.0 dApp 开发(四) 值的存取应用1.0 | Web3.0 dApp开发(三) Scaffold-eth 快速上手 | Web3.0 dApp 开发(二) eth.build 快速上手 | Web3.0 dApp 开发(一) 1 小时理解比特币系统 【NonceGeek Workshop 0x01总结】基于链上数据生成游戏地图 Remix 完全本地化部署 NFT:实体与虚拟载体的主与辅 | 狗哥的元宇宙思辨(一) Web3Camp 内容大全@NonceGeek 用 Python 创建一条 Pow 区块链(上) 区块链与共识机制演变史 基于 Etherscan 实现 Blockchain Syncer 【论文分享】去中心化社会:寻找 Web3 的灵魂(上) 【论文分享】去中心化社会:寻找 Web3 的灵魂(下) Ted Yin | 2021 年的区块链基础设施将是什么? 0. 公链、联盟链与分布式未来(全文) 基于 Infura 与 Web3py 部署调用 Hello 合约全过程 | 以太坊开发极速入门 太上中的基因设计与Binary | 函数式与区块链(一) 理解以太坊合约数据读取过程 | 函数式与区块链(二) Hello, Ink! | 用 Rust 写智能合约(一) Mapping 数据结构 | 用 Rust 写智能合约(二) 用 Rust 程序和 Webase 交互 | Rust 学习笔记(四) 用 Sqlite 存储 WeId | Rust 学习笔记(五) 链上注册WeId与错误处理 | Rust 学习笔记(六) WeId 链上创建与本地存储的完整闭环 | Rust 学习笔记(七) 以太坊上的核心开发者 Austin | 以太坊上的最佳开发实践 1. FISCO BCOS 开发环境节点搭建全攻略 伪代码简述 ECDSA 签名过程 | 联盟链开发 WeIdentity 源码分析 | 狗哥解码 WeIdentity 源码分析 | 狗哥解码 FISCO BCOS 介绍 | 联盟链开发 给Remix升个级 | 联盟链开发 2. 控制台的安装与使用 3. 【实验】补全一个区块链应用 4. 控制台的Web化 5. Web化控制台2.0:打造团队共用区块链学习平台 6. 使用脚手架快速搭建 Java DApp 【视频+文字】分布式思维 Rebuidl RSS (EN)

值的存取应用3.0 | Web3.0 dApp 开发(五)

  • 李大狗
  • 发布于 2022-03-12 13:29
  • 阅读 4300

值的存取应用最终版

在 2.0 版本中,我们学习了通过require语句给函数添加权限控制。

现在,我们可以给它加上真正的经济机制,让purpose的值由真正的竞价拍卖机制所控制!

0x01 加入 Owner

如何知道合约的所有人owner是一个新手常见的问题。

最简单的方式是设置一个 public 的owner变量,在构造函数里传入_owner参数:

pragma solidity >=0.8.0 <0.9.0;
//SPDX-License-Identifier: MIT

contract PurposeHandler {

  string public purpose = "Building Unstoppable Apps";
  address public owner = owner;
  // 这里填写你自己的地址

  constructor(address _owner) {
    owner = _owner;
  }

  function setPurpose(string memory newPurpose) public {
      // about msg.sender:
      // https://cryptozombies.io/en/lesson/2/chapter/3
      // about require:
      // https://cryptozombies.io/en/lesson/2/chapter/4
      require( msg.sender == owner, "NOT THE OWNER!");

      purpose = newPurpose;
      console.log(msg.sender,"set purpose to",purpose);
  }
}

在生产实践中,一般通过引入ownable.sol来实现。

Openzepplin中的ownable.sol

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol

一个单文件ownable.sol:

pragma solidity ^0.4.25;

  /**
  * @title Ownable
  * @dev The Ownable contract has an owner address, and provides basic authorization control
  * functions, this simplifies the implementation of "user permissions".
  */
  contract Ownable {
    address private _owner;

    event OwnershipTransferred(
      address indexed previousOwner,
      address indexed newOwner
    );

    /**
    * @dev The Ownable constructor sets the original `owner` of the contract to the sender
    * account.
    */
    constructor() internal {
      _owner = msg.sender;
      emit OwnershipTransferred(address(0), _owner);
    }

    /**
    * @return the address of the owner.
    */
    function owner() public view returns(address) {
      return _owner;
    }

    /**
    * @dev Throws if called by any account other than the owner.
    */
    modifier onlyOwner() {
      require(isOwner());
      _;
    }

    /**
    * @return true if `msg.sender` is the owner of the contract.
    */
    function isOwner() public view returns(bool) {
      return msg.sender == _owner;
    }

    /**
    * @dev Allows the current owner to relinquish control of the contract.
    * @notice Renouncing to ownership will leave the contract without an owner.
    * It will not be possible to call the functions with the `onlyOwner`
    * modifier anymore.
    */
    function renounceOwnership() public onlyOwner {
      emit OwnershipTransferred(_owner, address(0));
      _owner = address(0);
    }

    /**
    * @dev Allows the current owner to transfer control of the contract to a newOwner.
    * @param newOwner The address to transfer ownership to.
    */
    function transferOwnership(address newOwner) public onlyOwner {
      _transferOwnership(newOwner);
    }

    /**
    * @dev Transfers control of the contract to a newOwner.
    * @param newOwner The address to transfer ownership to.
    */
    function _transferOwnership(address newOwner) internal {
      require(newOwner != address(0));
      emit OwnershipTransferred(_owner, newOwner);
      _owner = newOwner;
    }
  }

0x02 通过一条 require 判断建立「拍卖机制」

规则即是,如果出价比当前的 price 高,那么就可以修改set-purpose的值;如果不如当前的 price 高,则抛出错误。

pragma solidity >=0.8.0 <0.9.0;
//SPDX-License-Identifier: MIT

contract PurposeHandler {

  string public purpose = "Building Unstoppable Apps";
  address public owner = owner;
  uint256 public price = 0.001 ether;
  // 这里填写你自己的地址

  constructor(address _owner) {
    owner = _owner;
  }

  function setPurpose(string memory newPurpose) payable public {
      require( msg.value > price, "NOT ENOUGH!");
      purpose = newPurpose;
      // update price when guy set 
      price = msg.value;
      console.log(msg.sender,"set purpose to",purpose);
  }

}

0x03 提现机制

通过函数getBalance()`owner可以查看合约中的余额,通过函数getMyMoney可以让合约中的余额提现出来:

pragma solidity >=0.8.0 <0.9.0;
//SPDX-License-Identifier: MIT

contract PurposeHandler {

  string public purpose = "Building Unstoppable Apps";
  address public owner;
  uint256 public price = 0.001 ether;

  constructor(address _owner) {
    owner = _owner;
  }

  function setPurpose(string memory newPurpose) payable public {
      require( msg.value > price, "NOT ENOUGH!");
      purpose = newPurpose;
      // update price when guy set 
      price = msg.value;
  }

  function getBalance() view public returns(uint256) {
      return address(this).balance;
  }

  function getMyMoney(address _to, uint256 amount) public {
        require(msg.sender==owner);
        address payable receiver = payable(_to);
        receiver.transfer(amount);
  }
}

0x04 通过 Event 记录 set purpose 的历史

什么是事件?

区块链是一个区块列表——它们基本上都是由交易构成。 每一笔交易都有一个附加的收据(receipt),其中包含零个或多个日志条目。这些日志条目代表着智能合约中的事件被触发后生成的结果。

在Solidity源代码中,要定义一个事件event,需要在其前面加上event关键字(类似于function关键字的用法)来标记它。 然后,你可以任何你希望生成事件的函数体内调用或触发该事件。 你可以从任何函数中使用emit关键字触发事件。

有人可能会添加关于如何“监听”DAPP中事件的信息。 它使用Web 3.0的过滤功能(filtering functionality of Web 3.0)。

——https://learnblockchain.cn/question/29

我们可以给 setPurpose 函数添加event, 以记录 set purpose 的历史。

pragma solidity >=0.8.0 <0.9.0;
//SPDX-License-Identifier: MIT

contract PurposeHandler {

  event SetPurpose(address sender, string purpose);

  string public purpose = "Building Unstoppable Apps";
  address public owner;
  uint256 public price = 0.001 ether;

  constructor(address _owner) {
    owner = _owner;
  }

  function setPurpose(string memory newPurpose) payable public {
      require( msg.value > price, "NOT ENOUGH!");
      purpose = newPurpose;
      // update price when guy set 
      price = msg.value;
      emit SetPurpose(msg.sender, purpose);
  }

  function getBalance() view public returns(uint256) {
      return address(this).balance;
  }

  function getMyMoney(address _to, uint256 amount) public {
        require(msg.sender==owner);
        address payable receiver = payable(_to);
        receiver.transfer(amount);
  }
}

总结

值的存取系列就到这里了。

在下一篇,我们进入下一章—— NFT dApp 的设计与实现!

点赞 1
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

2 条评论

请先 登录 后评论