区块链智能合约( solidity) 安全编程
引言:本文由天玄链开源开发者提供,欢迎报名公益天玄链训练营
https://blockchain.163.com/trainingCamp
一、重入和竞态
重入和竞态在solidity 编程安全中会多次提及,历史上也造成了重大的损失。
1.1 问题分析
竞态的描述不严格,竞态是在并发编程中的概念。而以太坊智能合约是单线程运行的。不存在并发。它的问题来自于重入。
我们在实现智能合约无法做到可重入的,所以就要添加重入的保护。一般情况下,重入问题来自于fallback 或者 recevie 方法,因为以太坊转账是最常用的功能。
当然如果调用了其他不安全的合约一样有这个问题。
1.2 可重入保护
一般的解决方案,“检查-生效-交互”,这个方法是现在常用的,也是推荐使用的。
|
另外,既然它表现的像多线程并发。还有一种解决方案,就是加锁。openzeppelin 中 ReentrancyGuard合约中的nonReentrant
modifier也是阻止重入的一种方法。
但是需要注意的是,这个modifier 只能对单个方法起作用,需要在所有状态相关方法上添加才能防止交叉重入。
综上,“检查-生效-交互” 推荐使用来防止重入。
1.3 显示标示untrust
在调用不安全外部合约的方法时,需要将该方法标示为untrust。同时,调用该untrust 的方法也应该是untrust。
对待untrust 方法规范是,首先处理完内部状态,最后调用untrust 方法。向外部地址转账,显然也是调用了外部合约方法,属于untrust 调用
二、安全转账
在uniswap中有很多转账的范例,比如下面的代码,将常用的ERC20 转账,注意,在safeTransferETH 中,它使用了to.call 而不是 to.transfer,因为而.send 或者 .transfer 是发送固定gas,
solidity 升级后,一些操作码的gas 可能有变化。这就导致之前的fallback 方法可能会失败。对建立在uniswap上的生态造成影响。
但是直接使用.call 有很多风险,比如要校验返回值,再比如重入攻击问题。所以尽量使用成熟的范式,是增强代码安全的有效手段。这里可能引入的重入风险,我们后面再单独分析。
|
三、以太发送方法
3.1 常用方法
常用的两种方法,send, transfer
send与transfer对比简析
相同之处
(1)均是向address发送ETH(以Wei做单位)
(2)发送的同时传输2300gas(gas数量很少,只允许接收方合约执行最简单的操作)
不同之处
(1)send执行失败返回false,transfer执行失败则会throw。这也就意味着使用send时一定要判断是否执行成功。
推荐
(1)默认情况下最好使用transfer(因为内置了执行失败的处理)
安全推荐是transfer,相信大家都知道。那么为什么transfer 更好,在于它是更高级的方法,封装了校验返回值,并抛出异常。
3.2 引申一下
我想引申一点是,在我们写方法的时候,当校验时,应该使用require 而不是 if,使用if 使得方法没有完成必要逻辑,而交易成功。这其实有隐患的。
除非你非常清楚这个差别,并认为只有if 才能满足函数需求。
比如有一个编程模式做频率检查,模式设计推荐的是
|
其实这个设计就有我上面说的问题,虽然达到了限制频率的目的,但是整个交易时成功的。正常使用就会有很多困惑,一旦被集成到其他合约,就会造成攻击的隐患。
建议是使用require,一旦失败,交易会revert,而且原因清晰。
|
3.3 转账成功的条件
如果对方是合约地址,那么它需要具备receive 方法,或者payable 的fallback 方法。如果两者都没有则转账失败。但是从另一面说,没有这两个方法不代表不能收取以太。
这还是要从概念上区分一下。
这就引申出两个问题,
3.3.1 合约为用户转账
要考虑到失败的可能。尽量使用pull 而不是push 方法。也就是让用用户发起withdraw收取以太,而不是合约dispatch。
3.3.2 合约需要收帐的。
即便没有设置payable 的fallback,和 receive 方法,你依然不能阻止绕过收款方法,直接转账给合约,使得合约balance 跟合约内账本对不上。
所以,业务逻辑要使用自己的账本。
3.3.3 非标准ERC20 的影响
业务逻辑建立在自己的账本上就够了吗?对于有些token 虽然符合ERC 标准,但是具体实现却又做了一些改动,比如有个项目做了转账收手续费的操作,
在转账过程中收取。也就是实际到账比交易执行的要少,如果只关注交易是否成功,然后记账是造成漏洞,所以这种情况,还需要去查balance 的变化。
以上是在转账过程需要注意的,不仅要合约记录账本,还需要核对balance,以保证业务逻辑没有漏洞。
当然如果业务确信没有此类问题。可以简化,比如只涉及USDT 的入账,那么可以不考虑3.3.3。
四、慎用tx.origin
永远不要 tx.origin 用于授权,另一个合约可以有一个方法来调用你的合约(例如,用户有一些资金)并且你的合约将授权该交易,因为你的地址位于tx.origin
.
contract MyContract {address owner;function MyContract() public {owner = msg.sender;}function sendTo(address receiver, uint amount) public {require(tx.origin == owner);(bool success, ) = receiver.call.value(amount)("");require(success);}}contract AttackingContract {MyContract myContract;address attacker;function AttackingContract(address myContractAddress) public {myContract = MyContract(myContractAddress);attacker = msg.sender;}function() public {myContract.sendTo(attacker, msg.sender.balance);}}
这是最常见的错误。
如果我们用tx.origin 能用来干嘛?我们先引申一下。EOA 的概念。
4.1 如何判断一个账户是EOA 账户而不是contract。
一种做法是如下,很多业务是这么写的。但其实是有问题。某些情况会失效,比如constructor中。
|
那么如何判断EOA 呢,这里就用到了tx.origin.
|
相关文章:
区块链智能合约( solidity) 安全编程
引言:本文由天玄链开源开发者提供,欢迎报名公益天玄链训练营 https://blockchain.163.com/trainingCamp 一、重入和竞态 重入和竞态在solidity 编程安全中会多次提及,历史上也造成了重大的损失。 1.1 问题分析 竞态的描述不严格…...

GUNS搭建
一、准备工作 源码下载: 链接: https://pan.baidu.com/s/1bJZzAzGJRt-NxtIQ82KlBw 提取码: criq 官方文档 二、导入代码 1、导入后端IDE 导入完成需要,需要修改yml文件中的数据库配置,改成自己的。 2、导入前端IDE 我是用npm安装的yarn npm…...
【ETCD】【源码阅读】stepWithWaitOption方法解析
在分布式系统中,ETCD 作为一个强一致性、高可用的 key-value 存储系统,广泛应用于服务发现、配置管理等场景。ETCD 在内部采用了 Raft 协议来保证集群的一致性,而日志预提案(log proposal)是 Raft 协议中至关重要的一部…...
redis 怎么样查看list
在 Redis 中,可以通过以下方法查看列表的内容或属性: 1. 查看列表中的所有元素 使用 LRANGE 命令: LRANGE key start endkey 是列表的名称。start 是起始索引,0 表示第一个元素。end 是结束索引,-1 表示最后一个元素…...
E: 无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend),是否有其他进程正占用它?
我们在使用Ubuntu系统时经常性使用sudo apt install命令安装所需要的软件库,偶尔会出现如下问题: E: 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用) E: 无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend),是否有其…...

创建型设计模式
一、设计模式介绍 1.设计模式是什么 设计模式是指在软件开发中,经过验证的,用于解决在特定环境下,重复出现的,特定问题的解决方案; 2.设计模式怎么来的? 满足设计原则后,慢慢迭代出来的。 3.设…...

仿iOS日历、飞书日历、Google日历的日模式
仿iOS日历、飞书日历、Google日历的日模式,24H内事件可自由上下拖动、自由拉伸。 以下是效果图: 具体实现比较简单,代码如下: import android.content.Context; import android.graphics.Canvas; import android.graphics.Color;…...

vuedraggable
官方文档:https://www.npmjs.com/package/vuedraggable 中文文档:http://www.itxst.com/vue-draggable/tutorial.html 案例下载地址: https://github.com/SortableJS/Vue.Draggable.git vuedraggablehttps://sortablejs.github.io/Vue.Dr…...

新手从事直播软件源码开发搭建经验与技巧
如果从YY或六间房的PC秀场直播间系统软件算起,直播软件已经在国内风云了至少10年了,站在用户角度提到直播系统大家基本都知道核心功能有开直播刷礼物等,那么如果站在直播软件源码开发搭建的技术角度去看呢?是不是要从需求调研分析…...
相机不动,机构动作----Hands Eyes
最近在研究 手眼标定,发现大家都需付费,搞啥子,说好的开源。。。 以相机在上固定不动,机械手为 EPSON_Robot 为例,详细的一步一步实例操作指引 EPSON_Robot 的192.168.0.1 2004 Server 详细操作步骤 1. 启动程序 运…...

Scala的导入
//导入 //(1) 创建包:在src上右键,新建软件包 //(2)填写包名:小写 //(3)在包上右键,创建类。自动加入包名 //(4)导入。import 包名.类名 //导入多个类 //import jh.yuanlixueyuan.bigdata.scala03.{A,B,C} //导入包下的所有的类 /…...
vue2中父子组件传值案例总结
在 Vue 2 中,父子组件之间的传值是通过 props 和事件来实现的。下面是详细的解释和总结: 1. 父组件向子组件传值 父组件可以通过 props 向子组件传递数据。以下是一个简单的示例: 父组件 (Parent.vue) <template><div><h1…...
功能篇:springboot中实现文件导出
### Spring Boot 中实现文件导出功能 #### 概述 在现代Web应用程序中,文件导出是一个常见的需求,允许用户将数据以特定格式(如CSV、Excel、PDF等)下载到本地。本文将详细介绍如何使用Spring Boot实现文件导出功能,并…...
Redis客户端(Jedis、RedisTemplate、Redisson)
1. 简介 Redis作为一个当下很火热的非关系型数据库,Java从业人员基本都离不开对Redis的使用。在Java程序中该数据库,需要借助于市面上的开源客户端,如Jedis、Spring Data Redis、Redisson,它们可以作为操作Redis非关系型数据库的桥…...

Mybatis中SQL的执行过程
文章目录 Mybatis 框架SQL执行过程数据库操作映射方式SQL的执行过程- SQL解析- SQL参数映射- SQL预编译- SQL执行- 结果映射- 事务处理- 缓存处理- 日志记录与监控 扩展#与$的区别- $ 符号- # 符号总结示例 Mybatis SQL分类- 动态 SQL- 静态 SQL静态SQL和动态SQL选择${}、#{}与…...

【数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
目录😋 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:编写一个程序实现顺序栈的基本运算。 相关知识 为了完成本关任务,你需要掌握: 初始化栈、销毁栈、判断栈是否为空、进栈、出栈、取…...

【论文阅读】PRIS: Practical robust invertible network for image steganography
内容简介 论文标题:PRIS: Practical robust invertible network for image steganography 作者:Hang Yang, Yitian Xu∗, Xuhua Liu∗, Xiaodong Ma∗ 发表时间:2024年4月11日 Engineering Applications of Artificial Intelligence 关键…...
在Linux桌面系统普及化方面的一些建议
在推动Linux桌面系统普及化的过程中,可以考虑以下几个方案和策略: 用户友好性改进: 界面设计:提升用户界面的美观性和易用性,使其更接近或超越主流操作系统的用户体验。软件兼容性:确保常用软件(…...

LLM - 多模态大模型的开源评估工具 VLMEvalKit 部署与测试 教程
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/144353087 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 VLMEva…...

数据结构(Queue队列)
前言: 在计算机科学中,数据结构是构建高效算法和程序的基础,而队列(Queue)作为一种经典的线性数据结构,具有重要的地位。与栈(Stack)不同,队列遵循“先进先出”…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...

Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...

从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...

CSS3相关知识点
CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...

高效的后台管理系统——可进行二次开发
随着互联网技术的迅猛发展,企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心,成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统,它不仅支持跨平台应用,还能提供丰富…...