Solidity拓展:数学运算过程中数据长度溢出的问题

news2024/11/27 1:21:55

 

 

在数学运算过程中假如超过了长度则值会变成该类型的最小值,如果小于了该长度则变成最大值

  • 数据上溢
uint8 numA = 255;
numA++;

 uint8的定义域为[0,255],现在numA已经到顶了,numA++会使num变成0(由于256已经超过定义域,它会越过256,变成0),即数据发生上溢(越过上边界,叫上溢)。255 --> 256 -->0 上溢。

  • 数据下溢
uint8 numB = 0;
numB--;

numB本身是低水位线,现在numB-- 会使num变成255(由于-1已经超过定义域,所以它会越过-1,变成255),即数据发生下溢(越过下边界,叫下溢)。0–> -1 --> 255 下溢。  

 可以通过引用 OpenZeppelin的 SafeMath v2.5.x 库,或者自定义一个SafeMath合约,来避免该问题。
    库是 Solidity 中一种特殊的合约,它给原始数据类型增加了一些方法: add(), sub(), mul(), 以及 div()。
    先引用或者import SafeMath库,然后声明 using SafeMath for uint256 ,再通过变量名来调用这些方法。
 

方法1:

导入库import "SafeMath"  

给变量使用库 using SafeMath for 变量类型

传递参数给库中add函数

uint e=255;

e=参数1.add(参数2)           底层是 参数1传给a,参数2传给b 

方法2:

也可以自己创建一个库,用library声明,而不是contract

library SafeMath {

func add(uint8 a,uint b) internal pure returns(uint 8){ 检验加法

       uint8 = a+b;

       assert(c>=a);

       assert()函数可以用来判断参数是否成立,若不成立则弹出一个错误

       return c;}}

试例

import "./safemath.sol";          //1)引用库
using SafeMath for uint256;       //2)声明指定的类型

uint256 a = 5;
uint256 b = a.add(3); // 5 + 3 = 8  //3)用变量名来调用方法
uint256 c = a.mul(2); // 5 * 2 = 10

库合约源码

pragma solidity ^0.4.18;

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  /**
  * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

/**
 * @title SafeMath32
 * @dev SafeMath library implemented for uint32
 */
library SafeMath32 {

  function mul(uint32 a, uint32 b) internal pure returns (uint32) {
    if (a == 0) {
      return 0;
    }
    uint32 c = a * b;
    assert(c / a == b);
    return c;
  }

  function div(uint32 a, uint32 b) internal pure returns (uint32) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint32 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint32 a, uint32 b) internal pure returns (uint32) {
    assert(b <= a);
    return a - b;
  }

  function add(uint32 a, uint32 b) internal pure returns (uint32) {
    uint32 c = a + b;
    assert(c >= a);
    return c;
  }
}

/**
 * @title SafeMath16
 * @dev SafeMath library implemented for uint16
 */
library SafeMath16 {

  function mul(uint16 a, uint16 b) internal pure returns (uint16) {
    if (a == 0) {
      return 0;
    }
    uint16 c = a * b;
    assert(c / a == b);
    return c;
  }

  function div(uint16 a, uint16 b) internal pure returns (uint16) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint16 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint16 a, uint16 b) internal pure returns (uint16) {
    assert(b <= a);
    return a - b;
  }

  function add(uint16 a, uint16 b) internal pure returns (uint16) {
    uint16 c = a + b;
    assert(c >= a);
    return c;
  }
}

library SafeMath8 {

  function mul(uint8 a, uint8 b) internal pure returns (uint8) {
    if (a == 0) {
      return 0;
    }
    uint8 c = a * b;
    assert(c / a == b);
    return c;
  }

  function div(uint8 a, uint8 b) internal pure returns (uint8) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint8 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint8 a, uint8 b) internal pure returns (uint8) {
    assert(b <= a);
    return a - b;
  }

  function add(uint8 a, uint8 b) internal pure returns (uint8) {
    uint8 c = a + b;
    assert(c >= a);
    return c;
  }
}

1.自增修改

简单变量

uint numA;
numA++;

优化后 

import "./safemath.sol";
using SafeMath for uint256;

uint numA;
//numA++;
numA = numA.add(1);

map

mapping(address => uint) ownerAppleCount;
ownerAppleCount[msg.sender]++;

优化后 

import "./safemath.sol";
using SafeMath for uint256;

mapping(address => uint) ownerAppleCount;
//ownerAppleCount[msg.sender]++;
ownerAppleCount[msg.sender] = ownerAppleCount[msg.sender].add(1);

结构体 

struct Apple {
    uint32 id;	
	uint   weight;
	string color;
}
Apple zhaoApple = Apple(100,150,"red");
zhaoApple.weight++;

优化后 

import "./safemath.sol";
using SafeMath for uint256;
using SafeMath32 for uint32;

struct Apple {
    uint32 id;	
	uint   weight;
	string color;
}
Apple zhaoApple = Apple(100,150,"red");
//zhaoApple.weight++;
zhaoApple.weight = zhaoApple.weight.add(1);

2.自减修改

简单变量

uint8 numB;
numB--;

优化后 

import "./safemath.sol";
using SafeMath8 for uint8;

uint8 numB;
//numB--;
numB = numB.sub(1);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/577875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

结构体 --- C语言

目录 1.结构体的声明 2.结构体变量的定义和初始化 3.结构体成员访问 4.结构体传参 1.结构体的声明 结构是一些值的集合&#xff0c;这些称为成员变量&#xff0c;结构的每个成员可以是不同类型的变量。 而数组是一组类型相同的元素的集合。 生活中的描述 人&#xff1a;名…

测试C#分词工具jieba.NET(续1:提取关键词及并行分词)

jieba.NET支持通过两种算法提取文本关键词&#xff1a;TF-IDF算法和TextRank算法&#xff0c;关于这两种算法的介绍详见参考文献10-11&#xff0c;在jieba.NET中对应的类为TfidfExtractor和TextRankExtractor&#xff0c;这两个分词都都支持调用ExtractTags和ExtractTagsWithWe…

文件上传至公有云Nos及对接CDN

项目开发中&#xff0c;需要将图片文件上传至网易公有云的Nos,并且结合CDN做加速服务&#xff0c;记录一下开发过程。流程图&#xff1a; 1. 文件上传到公有云Nos 网易对象存储服务&#xff08;Netease Object Storage&#xff0c;简称NOS&#xff09;是网易数帆提供的高可用…

pycharm环境下打开Django内置的数据库Sqlite出错问题解决

问题描述 在数据库库文件中写入一条记录后&#xff0c;在pycharm的terminal终端下执行查看表的命令出错 执行语句为&#xff1a; 连接数据库报错 python manage.py dbshell CommandError: You appear not to have the sqlite3 program installed or on your path. Error:…

JavaScript之DOM基础

1. 初识DOM DOM: 文档对象模型 是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。 w3c已经定义了一系列的DOM接口&#xff0c;通过这些DOM接口可以改变网页的内容&#xff0c;结构和样式。 DOM树&#xff1a;文档&#xff1a;一个页面就是一个文档, DOM中使用d…

Android逆向猿人学2022年app比赛第四题grpc与Protobuf使用(步步验证)

教程 前言一、起步二、抓包三、分析四、验证五、HOOK借鉴 前言 前面2-3题和第一题解题思路基本上一样的&#xff0c;这里就不出教程了&#xff0c;这篇文章比较繁琐&#xff0c;基本上描述了我做这题的思路&#xff0c;有很多走不通的地方也有对应的方法&#xff0c;所以会比较…

linux网络初探

linux网络 1.1查看本机ip IP地址 IP地址网络地址主机地址&#xff0c;网络地址&#xff08;网络号&#xff09;相同的主机为本地网络中的主机&#xff0c;可以直接相互通信&#xff0c;而网络地址不同的主机为远程网络中的主机&#xff0c;相互通信必须通过本地网关&#xf…

Flutter Windows开发环境搭建教程与学习资料推荐

Windows应用软件开发有很多框架可以选择&#xff0c;例如比较流行的Electron、Qt、CEF、WPF、WinForm、MFC、DuiLib、SOUI等等。Flutter是近几年流行的全平台应用开发框架&#xff0c;可以进行Android、IOS、Web、MacOS、Windows、Linux等平台的应用软件开发。 一、Flutter介绍…

启动U盘制作工具Rufus 4.0.2035

Rufus是是一款小巧实用免费开源的帮助格式化和创建可启动USB闪存驱动器的工具&#xff0c;如USB钥匙/软盘、记忆棒等&#xff0c;可快速制作linux系统或者win启动u盘&#xff0c;可快速的将ISO镜像文件制作成可引导启动的USB启动盘&#xff0c;支持ISO镜像、GPT和UEFI&#xff…

设置参考文献编号与文中插入引用的具体步骤

目录 一、前言 二、操作步骤 &#xff08;一&#xff09;参考文献设置编号 &#xff08;二&#xff09;文章中引用参考文献方式 一、前言 本教程使用的软件是WPS 二、操作步骤 &#xff08;一&#xff09;参考文献设置编号 1.把引用文献的这个编号全部删掉 2.右键点击段…

学习笔记——vue中使用el-dropdown组件报错

今天在工作中&#xff0c;发现使用el-select做的下拉框&#xff0c;下拉菜单展开后&#xff0c;鼠标点击下拉框之外的区域时&#xff0c;下拉菜单没有收起。然后&#xff0c;我打开控制台&#xff0c;发现了这个错误。 Uncaught TypeError: Cannot read properties of null (re…

《Linux0.11源码解读》理解(四) head之重新设置IDT/GDT

上节提到&#xff0c;现在cs:ip指向0地址&#xff0c;此处存储着作为操作系统核心代码的system模块&#xff0c;是由head.s和 main.c以及后面所有源代码文件编译链接而成。head.s(以下简称head)紧挨着main.c&#xff0c;我们先执行head。 重新设置内核栈 _pg_dir: _startup_3…

堆(堆排序 模拟堆)

目录 一、堆的数据结构二、堆的操作方法往下调整的示意图往上调整的示意图相关功能的实现思路1.插入一个数2.求最小值3.删除最小值4.删除任意一个元素5.修改任意一个元素 三、堆的实战运用堆排序模拟堆 一、堆的数据结构 堆是一个完全二叉树&#xff1a;除了最后一层结点以外&…

C语言三子棋,五子棋,n子棋的代码实现

C语言三子棋&#xff0c;五子棋&#xff0c;n子棋的代码实现 这里以五子棋为例&#xff0c;来说明开发过程开发思路菜单打印棋盘的打印棋子的打印电脑下棋&#xff08;随机数&#xff09;判断输赢代码整合注意事项 这里以五子棋为例&#xff0c;来说明开发过程 其中该项目包含…

《用户增长方法论》从产品、渠道、营销创意等多个维度,搭建了一套完整的用户增长方法体系

关于作者 黄永鹏&#xff0c;目前在阿里巴巴担任高级用户增长专家。黄永鹏是一个典型的 “ 斜杠青年 ” &#xff0c;十年前从广告咨询行业转战互联网&#xff0c;在 BAT 三家 公司都待过&#xff0c;负责过多款用户和日活过亿的产品&#xff0c;比如腾讯手机管家、百度地图…

chatgpt赋能python:Python练手:提高你的SEO技能

Python练手&#xff1a;提高你的SEO技能 在当今数字化时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;成为了网站和企业在线成功的关键。优化技巧既可以提高网站的排名&#xff0c;还可以增加网站的可见性&#xff0c;从而吸引更多的流量和潜在客户。Python是一个适…

网络通信协议-ARP协议

目录 一、ARP协议 二、ARP协议通信过程 应用情景一&#xff1a;同一广播域内通信 &#xff08;1&#xff09;第一步&#xff1a;ARP协议通信 1.交换机接受消息 2.电脑2接收到广播消息 3.电脑2回复 4.交换机转发回复给电脑1 5.电脑1记录 &#xff08;2&#xff09;第二…

Go快速上手之基础语法 | 青训营笔记

Go快速上手之基础语法 &#xff5c; 青训营笔记 文章目录 Go快速上手之基础语法 &#xff5c; 青训营笔记系列介绍本文摘要1. Go 介绍2. Go 的环境配置2.1 :sparkles: IDE2.2 Gitpod 和 Jetbrians Gateway 的使用 3. Go的基础语法3.1 Hello World3.2 变量与常量3.3 条件控制语句…

Linux(进程间通信)

目录&#xff1a; 1.进程间通信的介绍 2.管道通信 3.管道的原理 ------------------------------------------------------------------------------------------------------------------------------- 1.进程间通信的介绍 2.管道通信 当我们在创建子进程时&#xff0c;我们的…

chatgpt赋能python:Python生成pyc文件的介绍

Python生成pyc文件的介绍 Python是一种解释型语言&#xff0c;但是在执行某些操作时&#xff0c;它会生成缓存文件&#xff0c;以便提高执行效率。这些缓存文件以 .pyc 扩展名保存在同一目录中。 在本文中&#xff0c;我们将重点介绍Python生成pyc文件&#xff0c;并探讨它们…