Solidity学习笔记2——Webase积分合约

2023-11-09

代码段学习笔记

代码来源:Webase合约仓库
我只做了增加注释的工作用来记录相关知识点。

pragma solidity ^0.4.24;

import "./SafeMath.sol";
import "./Roles.sol";
import "./Address.sol";

contract IssuerRole {
    using Roles for Roles.Role;    给Role合约里的role结构体附加Role里的三个函数功能

    event IssuerAdded(address indexed account);
    event IssuerRemoved(address indexed account);

    Roles.Role private _issuers;

    constructor () internal {   //初始化合约,合约的发起者拥有权限
        _addIssuer(msg.sender);
    }

    modifier onlyIssuer() {    //修饰器 用来设置执行函数前的检查条件
        require(isIssuer(msg.sender), "IssuerRole: caller does not have the Issuer role");
        _;     //执行函数的代码段
    }

    function isIssuer(address account) public view returns (bool) {   //判断是否有权限
        return _issuers.has(account);
    }

    function addIssuer(address account) public onlyIssuer {  //只有有权限的角色才能赋予别人权限
        _addIssuer(account);
    }

    function renounceIssuer() public {   //移除权限  (这边代码有点怪:把自己权限删了?)
        _removeIssuer(msg.sender);
    }

    function _addIssuer(address account) internal {
        _issuers.add(account);
        emit IssuerAdded(account);
    }

    function _removeIssuer(address account) internal {
        _issuers.remove(account);
        emit IssuerRemoved(account);
    }
}

contract SuspenderRole {
    using Roles for Roles.Role;

    event SuspenderAdded(address indexed account);
    event SuspenderRemoved(address indexed account);

    Roles.Role private _suspenders;

    constructor () internal {
        _addSuspender(msg.sender);
    }

    modifier onlySuspender() {
        require(isSuspender(msg.sender), "SuspenderRole: caller does not have the Suspender role");
        _;
    }

    function isSuspender(address account) public view returns (bool) {
        return _suspenders.has(account);
    }

    function addSuspender(address account) public onlySuspender {
        _addSuspender(account);
    }

    function renounceSuspender() public {
        _removeSuspender(msg.sender);
    }

    function _addSuspender(address account) internal {
        _suspenders.add(account);
        emit SuspenderAdded(account);
    }

    function _removeSuspender(address account) internal {
        _suspenders.remove(account);
        emit SuspenderRemoved(account);
    }
}

contract Suspendable is SuspenderRole {  / //继承合约

    event Suspended(address account);
    event UnSuspended(address account);

    bool private _suspended;

    constructor () internal {
        _suspended = false;
    }

    /**
     * @return True if the contract is suspended, false otherwise.
     */
    function suspended() public view returns (bool) {
        return _suspended;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not suspended.
     */
    modifier whenNotSuspended() {
        require(!_suspended, "Suspendable: suspended");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is suspended.
     */
    modifier whenSuspended() {
        require(_suspended, "Suspendable: not suspended");
        _;
    }

    /**
     * @dev Called by a Suspender to suspend, triggers stopped state.
     */
    function suspend() public onlySuspender whenNotSuspended {
        _suspended = true;
        emit Suspended(msg.sender);
    }

    /**
     * @dev Called by a Suspender to unSuspend, returns to normal state.
     */
    function unSuspend() public onlySuspender whenSuspended {
        _suspended = false;
        emit UnSuspended(msg.sender);
    }
}

contract IBAC001Receiver {    //抽象合约
    /**
     * @notice Handle the receipt of an NFT
     * @dev The BAC001 smart contract calls this function on the recipient
     */
    function onBAC001Received(address operator, address from, uint256 value, bytes data)
    public returns (bytes4);
}

contract BAC001Holder is IBAC001Receiver {
    function onBAC001Received(address, address, uint256, bytes) public returns (bytes4) {
        return this.onBAC001Received.selector;  
        //表示获取当前合约中onBAC001Received函数的选择器(即函数签名)。Solidity编译器会根据函数名称和参数列表生成相应的函数选择器。这个选择器可以用来唯一地标识一个函数。
    }
}


/**
 * @title Standard BAC001 asset
 */
contract BAC001 is IssuerRole, Suspendable {
    using SafeMath for uint256;
    using Address for address;

    mapping(address => uint256) private _balances;  //地址映射代币余额
    mapping(address => mapping(address => uint256)) private _allowed; //地址映射到被允许代表其花费代币的地址
    //相当于一个二维映射,可以将这个二维映射看作是一个表格,其中每行表示代币的一个所有者(owner),每列表示被授权者(spender)。因此,通过在表格中指定一个所有者(owner)和一个被授权者(spender),可以获得被授权者(spender)可以花费的代币数量。比如_allowed[0x1111][0x2222] = 100;
    
    uint256 private _totalAmount;  //代币总量
    string private _description;  
    string private _shortName;
    uint8 private  _minUnit;  //代表代币的最小单位

    // Equals to `bytes4(keccak256("onBAC001Received(address,address,uint256,bytes)"))`
    bytes4 private constant _BAC001_RECEIVED = 0xc73d16ae;  //函数签名是由函数名和函数参数类型组成的哈希值,用于唯一标识函数。  用于在代币转移过程中通知合约的接收方(通常是另一个智能合约),以便接收方可以采取相应的操作,如检查代币的有效性等。


    event Send( address indexed from, address indexed to, uint256 value, bytes data);
    event Approval( address indexed owner, address indexed spender, uint256 value);


    constructor(string memory description, string memory shortName, uint8 minUnit, uint256 totalAmount) public {
        _description = description;
        _shortName = shortName;
        _minUnit = minUnit;
        _issue(msg.sender, totalAmount * (10 ** uint256(minUnit)), "");
    }


    function totalAmount() public view returns (uint256) {
        return _totalAmount;
    }

    function balance(address owner) public view returns (uint256) {
        return _balances[owner];
    }

    /**
     * @dev Function to check the amount of assets that an owner allowed to a spender.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowed[owner][spender];
    }

    function send(address to, uint256 value, bytes data) public whenNotSuspended {
        _send(msg.sender, to, value, data);
        require(_checkOnBAC001Received(msg.sender, to, value, data), "BAC001: send to non BAC001Receiver implementer");

    }

//    function safeSend(address to, uint256 value, bytes data) public whenNotSuspended {
//        send(to, value, data);
//        require(_checkOnBAC001Received(msg.sender, to, value, data), "BAC001: send to non BAC001Receiver implementer");
//    }


    /**
     * @dev Approve the passed address to spend the specified amount of assets on behalf of msg.sender.
     */
    function approve(address spender, uint256 value) public whenNotSuspended returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev Send assets from one address to another.
     */
    function sendFrom(address from, address to, uint256 value, bytes data) public whenNotSuspended {
        _send(from, to, value, data);
        _approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
        //add
        require(_checkOnBAC001Received(from, to, value, data), "BAC001: send to non BAC001Receiver implementer");


    }

 safe todo
//    function safeSendFrom(address from, address to, uint256 value, bytes data) public whenNotSuspended {
//        sendFrom(from, to, value, data);
//        require(_checkOnBAC001Received(from, to, value, data), "BAC001: send to non BAC001Receiver implementer");
//    }


    function batchSend(address[] to, uint256[] values, bytes data) public whenNotSuspended {

        // MUST Throw on errors

        require(to.length == values.length, "to and values array lenght must match.");

        for (uint256 i = 0; i < to.length; ++i) {
            require(to[i] != address(0x0), "destination address must be non-zero.");

            send(to[i], values[i], data);
        }
    }


    function _checkOnBAC001Received(address from, address to, uint256 value, bytes data)
    internal returns (bool)
    {
        if (!to.isContract()) {
            return true;
        }

        bytes4 retval = IBAC001Receiver(to).onBAC001Received(from, to, value, data);
        return (retval == _BAC001_RECEIVED);
    }

    /**
     * @dev Increase the amount of assets that an owner allowed to a spender.
     */
    function increaseAllowance(address spender, uint256 addedValue) public whenNotSuspended returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Decrease the amount of assets that an owner allowed to a spender.
     * approve should be called when _allowed[msg.sender][spender] == 0. To decrement
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public whenNotSuspended returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    function destroy(uint256 value, bytes data) public {
        _destroy(msg.sender, value, data);
    }

    /**
     * @dev Burns a specific amount of assets from the target address and decrements allowance.
     */
    function destroyFrom(address from, uint256 value, bytes data) public {
        _destroyFrom(from, value, data);
    }


    function description() public view returns (string memory) {
        return _description;
    }

    /**
     * @return the shortName of the asset.
     */
    function shortName() public view returns (string memory) {
        return _shortName;
    }

    /**
     * @return the number of minUnit of the asset.
     */
    function minUnit() public view returns (uint8) {
        return _minUnit;
    }


    function issue(address to, uint256 value, bytes data) public onlyIssuer returns (bool) {
        _issue(to, value, data);
        return true;
    }
    /**
     * @dev Send asset for a specified addresses.
     */
    function _send(address from, address to, uint256 value, bytes data) internal {
        require(to != address(0), "BAC001: send to the zero address");

        _balances[from] = _balances[from].sub(value);
        _balances[to] = _balances[to].add(value);
        emit Send( from, to, value, data);
    }

    /**
     * @dev Internal function that issues an amount of the asset and assigns it to
     */
    function _issue(address account, uint256 value, bytes data) internal {
        require(account != address(0), "BAC001: issue to the zero address");

        _totalAmount = _totalAmount.add(value);
        _balances[account] = _balances[account].add(value);
        emit Send( address(0), account, value, data);
    }

    /**
     * @dev Internal function that destroys an amount of the asset of a given
     */
    function _destroy(address account, uint256 value, bytes data) internal {
        require(account != address(0), "BAC001: destroy from the zero address");

        _totalAmount = _totalAmount.sub(value);
        _balances[account] = _balances[account].sub(value);
        emit Send( account, address(0), value, data);
    }

    /**
     * @dev Approve an address to spend another addresses' assets.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "BAC001: approve from the zero address");
        require(spender != address(0), "BAC001: approve to the zero address");

        _allowed[owner][spender] = value;
        emit Approval( owner, spender, value);
    }

    /**
     * @dev Internal function that destroys an amount of the asset of a given
     */
    function _destroyFrom(address account, uint256 value, bytes data) internal {
        _destroy(account, value, data);
        _approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
    }
}
pragma solidity ^0.4.24;
//检查地址是否为合约地址和是否为零地址
library Address {

    function isContract(address addr) internal view returns(bool) {
        uint256 size;
        assembly { size := extcodesize(addr) }  
        return size > 0;
    }//在汇编代码中使用extcodesize指令来检查给定地址上的代码长度,如果长度大于0,则说明该地址是一个合约地址,返回true;否则,它是一个非合约地址,返回false。

    function isEmptyAddress(address addr) internal pure returns(bool){
        return addr == address(0);
    }
}
pragma solidity ^0.4.24;


library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

pragma solidity ^0.4.24;

library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    function add(Role storage role, address account) internal {
        require(!has(role, account), "Roles: account already has role");
        role.bearer[account] = true;
    }

    function remove(Role storage role, address account) internal {
        require(has(role, account), "Roles: account does not have role");
        role.bearer[account] = false;
    }

    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Solidity学习笔记2——Webase积分合约 的相关文章

随机推荐

  • vuex动态路由

    import router asyncRoutes constantRoutes from router import getRouters from api menu import Layout from layout index imp
  • 联想票务系统服务器,联想中国(Lenovo China)_服务频道_服务政策

    Lenovo ThinkServer Partner Pack for Microsoft System Center 重要通知 ThinkServer RD350 RD450 RD550 RD650 TD350 中Lenovo Think
  • APP开发如何批量生成不同尺寸的图标?

    在我们开发APP的时候 我们使用到大量的不同尺寸的APPLogo的图片 如下图 通常 我们的做法是和设计师沟通 让他们切出这儿所以的图片 然后我们一个一个图片放在对应的位置 这样处理的话 我们比较容易出错 比如说 图片的格式 苹果对图片的格
  • 4-数据结构-顺序表的查找

    说明 顺序表的查找 分为按照位置查找 返回对应值和按照值查找 返回该值位置 思路 getlist sqlist l int k 为按位查找 返回具体数值 locatelist sqlist l int k 按照值 去查找位置 因为顺序表都是
  • 吐血整理,性能测试-Jmeter分布式压测实战(超细详解)

    目录 导读 前言 一 Python编程入门到精通 二 接口自动化项目实战 三 Web自动化项目实战 四 App自动化项目实战 五 一线大厂简历 六 测试开发DevOps体系 七 常用自动化测试工具 八 JMeter性能测试 九 总结 尾部小
  • wiringPi引脚编号方式

    树莓派引出的20 2排针引脚 引脚定义使用gpio readall命令查看 如下 可以看到wiringpi库有三种引脚编号方式 分别为 BCM编号方式 就是使用芯片的GPIO引脚编号 wiringpi库编号方式 使用wiringpi库自己规
  • LR(1)项目集族的构造:如何确定前向搜索符(新版)

    旧版链接 https blog csdn net hhhhhhhhhhkkkkkkkkkk article details 19990287 按照这个标题搜进来的各位是不是以为这也是和课本一样的内容呢 其实这是我看了两天课本才理解出来的内容
  • C++ Primer笔记——查找算法

    目录 一 简单查找 find first last val find if find if not count count if all of any of none of 二 重复值的查找 adjacent find first end
  • Centos8 重新安装yum

    手残卸载了cnetos8自带的yum命令 然后各种搜索重新安装 有centos7下重新安装的 也有dnf重新安装yum的 结果都不好用 一 准备工作 重新安装yum前 请自行卸载yum相关参与包 卸载python rpm qa grep p
  • umi中操作mock中的数据实现搜索操作

    我们定义两个属性 分别是我们的原始数据和渲染的数据 const book setbook useState 原始数据 const sear setSear useState 用于渲染的数据 input搜索框绑定onChange事件 通过e
  • dedecms自定义内容模型怎么采集

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 在用织梦cms系统进行网站开发时 经常会碰到各种各样复杂的需求 因此我们需要用到dedecms提供的自定义内容模型功能去添加自定义内容模型来满足需求 那么dedecms自定
  • 输入第一个字符串A,输入第二个字符串B,统计B在A中出现的次数 abcabcabd abc

    public class strCount public static void main String args 定义字符串 String str abc String ss abcabcabc 定义返回的次数 int count 0 f
  • 【C++ windows多线程使CPU 100%】

    用于windows 平台的CPU 100 预警测试程序 c 实现 cpp程序文件名 win32HighCpuTest cpp include
  • vue3中的setup方法

    一 vue2中的定义变量和方法的写法 在介绍v3的setup之前 我们先来看看在v2中是如何定义变量和方法的
  • stm32——PWM概述

    一 PWM生成方波 C51是用软件的方式进行模拟出方波 STM32F103C8T6中硬件就可以生成PWM方波 芯片中的PWM资源 高级定时器 TIM1 7路 通用定时器 TIM2 TIM4 各4路 共19路PWM 二 PWM输出模式 pwm
  • 【Redis】主从复制

    Redis主从复制 文章目录 Redis主从复制 搭建一主多从 复制原理 常用3招 一主二仆 薪火相传 反客为主 哨兵模式 sentinel 使用步骤 故障恢复 主机数据更新后根据配置和策略 自动同步到备机的master slaver机制
  • 每个程序员都必须遵守的编程原则

    每个程序员都必须遵守的编程原则 来源 外刊IT评论 发布时间 2011 09 03 16 15 阅读 1781 次 原文链接 全屏阅读 收藏 摘要 好的编程原则跟好的系统设计原则和技术实施原则有着密切的联系 本文是从 The Princip
  • Kafka消费者组重平衡(二)

    文章目录 概要 重平衡通知机制 消费组组状态 消费端重平衡流程 Broker端重平衡流程 概要 上一篇Kafka消费者组重平衡主要介绍了重平衡相关的概念 本篇主要梳理重平衡发生的流程 为了更好地观察 数据准备如下 kafka版本 kafka
  • 猫和老鼠服务器维修有问题,猫和老鼠手游老是掉线怎么办 频繁网络中断解决方法...

    猫和老鼠手游为什么老是掉线呢 许多玩家在玩的过程中频繁遇到这个掉线的问题 导致体验非常糟糕 有什么方法可以减轻或者彻底避免掉线的问题呢 下面小编就为大家介绍一下吧 1 信号不好 如果你是身处于火车 地铁 地下室 电梯 或者比较偏远信号不好的
  • Solidity学习笔记2——Webase积分合约

    代码段学习笔记 代码来源 Webase合约仓库 我只做了增加注释的工作用来记录相关知识点 pragma solidity 0 4 24 import SafeMath sol import Roles sol import Address