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

 

 

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

  • 数据上溢
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);

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis事务及网络处理

一 Redis事务 redis开启事务后&#xff0c;会把接下来的所有命令缓存到一个单独的队列中&#xff0c;在提交事务时&#xff0c;使这些命令不可被分割的一起执行完成。 如果使用了watch命令监视某一个key&#xff0c;如果在开启事务之后&#xff0c;提交事务之前&#xff0c;有…

FreeRTOS:队列

目录 前言一、队列简介1.1数据存储1.2多任务访问1.3出队阻塞1.4入队阻塞1.5队列操作过程图示1.5.1创建队列1.5.2向队列发送第一个消息1.5.3向队列发送第二个消息1.5.4从队列中读取消息 二、队列结构体三、队列创建3.1创建函数3.2函数xQueueCreateStatic()3.3函数xQueueCreate()…

Spring Security入门

1. Spring Security 简介 Spring Security 是一个高度可定制的身份验证和访问控制框架&#xff0c;它基于 Spring 框架&#xff0c;并可与 Spring 全家桶无缝集成。该框架可以精确控制用户对应用程序的访问&#xff0c;控制用户的角色和权限等。 Spring Security 最早是由 Be…

又名管道和无名管道

一、进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09; 概念&#xff1a;就是进程和进程之间交换信息。 常用通信方式 无名管道&#xff08;pipe&#xff09; 有名管道 &#xff08;fifo&#xff09; 信号&#xff08;signal&#xff09; 共…

JMeter性能测试:JMeter多用户并发模拟及压测结果分析

目录 JMeter设置 JMeter线程组 JMeter压测实例 View Results Tree Aggregate Report 命令行方式执行压测 jtl文件解析 JMeter多用户并发模拟 JMeter设置 多用户并发数的多少与计算机内存有关&#xff0c;设置 jmeter.bat (Windows) 或者 jmeter.sh (Linux)&#xff1a;…

Faster R-CNN网络架构详解和TensorFlow Hub实现(附源码)

文章目录 一、RPN网络1. RPN网络简介2. backbone网络简介 二、Faster R-CNN网络架构1. Faster R-CNN网络简介2. 基于TensorFlow Hub实现Faster R-CNN 前言&#xff1a;Faster R-CNN的简介见 上一篇文章 一、RPN网络 1. RPN网络简介 RPN网络全称Region Proposal Network&#…

vscode配置flutter开发环境,不需要安装第三方安卓模拟器

文章目录 1.获取Flutter SDK2.配置Android环境3. 在Android Studio配置Android设备3.1 进入Device Manager配置安卓设备3.2 创建安卓虚拟机3.3 选择x86 镜像3.4 配置硬件加速3.5 启动模拟器 4.配置vscode1.安装 Flutter 和 Dart 插件 5. 新建flutter程序创建应用 6.启动程序1.选…

nodejs+vue社区母婴幼儿用品商城系统

本系统实现了管理员对用户、商品信息、交流论坛、订单信息的管理&#xff0c;是为了满足用户更深层次的需求。除了上述优势外&#xff0c;本系统还具有&#xff1a;查询迅速&#xff0c;搜索资料方便&#xff0c;可靠性强等等在如今这个高速发展的时代&#xff0c;效率决定着你…

day10 - 使用canny算子进行人像勾勒

本期主要介绍canny算子&#xff0c;了解canny算子的流程以及各个流程的原理和实现。 ​ 完成本期内容&#xff0c;你可以&#xff1a; 了解canny算子的流程和应用 若要运行案例代码&#xff0c;你需要有&#xff1a; 操作系统&#xff1a;Ubuntu 16 以上 或者 Windows10 工…

第五篇、基于Arduino uno,获取超声波(HC04)传感器的距离数据——结果导向

0、结果 说明&#xff1a;先来看看串口调试助手显示的结果&#xff0c;显示的是一个距离值&#xff0c;如果是你想要的&#xff0c;可以接着往下看。 1、外观 说明&#xff1a;虽然超声波传感器形态各异&#xff0c;但是原理和代码都是适用的。 2、连线 说明&#xff1a;只…

秒杀系统常见问题—如何避免库存超卖?

大家好&#xff01;我是sum墨&#xff0c;一个一线的底层码农&#xff0c;平时喜欢研究和思考一些技术相关的问题并整理成文&#xff0c;限于本人水平&#xff0c;如果文章和代码有表述不当之处&#xff0c;还请不吝赐教。 以下是正文&#xff01; 先看问题 首先上一串代码 …

Vue.js 比较重要知识点总结一

概述 谈一谈你对 Vue.js 的响应式数据的理解Vue3 出现解决了什么问题&#xff1f;它有哪些优势&#xff1f;Vue3 新特性有哪些vue2 和 vue3 的响应式有什么区别&#xff1f; 谈一谈你对 Vue.js 的响应式数据的理解 Vue 2.x 对象类型&#xff1a;通过 object.defineProperty(…

实时频谱-3.1实时频谱分析仪测量

RSA 测量类型 泰克RSA 可以在频域、时域、调制域和统计域中工作。 频域测量 基本频域测量是实时 RF 数字荧光显示(DPX)频谱显示测量、频谱显示测量和频谱图显示测量功能。 DPX 频谱 DPX 频谱测量对 RSA 发现其它分析仪漏掉的难检信号的能力至关重要。在所有泰克 RSA 中&am…

SAP-MM-内向外向交货单

1、内向&外向交货单概念 外向交货&#xff08;outbound delivery&#xff09;是用在客户与企业之间的交货单&#xff0c;而内向交货&#xff08;inbound delivery&#xff09;则是用在供应商与企业之间的交货单&#xff1b;换言之&#xff0c;外向交货多用于SD 模块&#…

PriorityQueue优先级队列

前言 优先级队列就是在堆的基础上进行改造&#xff0c;那么什么是堆&#xff0c;又什么是优先级队列呢&#xff1f; 我们一起来看看吧&#xff01; 目录 前言 一、堆 &#xff08;一&#xff09;堆的创建 &#xff08;二&#xff09;堆的插入 &#xff08;三&#xff09;堆…

群晖DS920 video station使用教程

群晖DS920 video station使用教程 为了更好的浏览体验&#xff0c;欢迎光顾勤奋的凯尔森同学个人博客http://www.huerpu.cc:7000 安装video station在群晖套件里点一下就好&#xff0c;这里不说了。 一、添加视频库 可以添加电视剧、电视节目等类型。 比如我在国产剧这个视频…

uniapp滚动加载 下拉刷新

前言 在日常开发中&#xff0c;滚动加载和下拉刷新是非常常见的功能&#xff0c;页面数据过多时&#xff0c;需要滚动加载优化性能&#xff0c;本篇技术分享博客将介绍如何在uniapp中实现滚动加载和下拉刷新。 预览 滚动加载 下拉刷新 一、滚动加载 滚动加载指的是当用户滑…

PHP 反序列化漏洞

PHP反序列化漏洞在实际测试中出现的频率并不高&#xff0c;主要常出现在CTF中。 PHP序列化概述 PHP序列化函数&#xff1a; serialize&#xff1a;将PHP的数据&#xff0c;数组&#xff0c;对象等序列化为字符串unserialize&#xff1a;将序列化后的字符串反序列化为数据&…

java 利用poi根据excel模板导出数据(二)

本文是 java 利用poi根据excel模板导出数据&#xff08;一&#xff09; 的续篇 经常有poi的开发一定会碰到三个名词&#xff1a; HSSFWorkbook 、 XSSFWorkbook、SXSSFWorkbook&#xff1b; 这三个都是导出excel的形式&#xff0c;具体区别&#xff1a; HSSFworkbook,XSSF…

Golang每日一练(leetDay0080) 矩形面积、翻转二叉树

目录 223. 矩形面积 Rectangle Area &#x1f31f;&#x1f31f; 226. 翻转二叉树 Invert Binary Tree &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏…