# solidity安全，测试时对照使用

By [point](https://paragraph.com/@point) · 2022-05-03

---

1.  防止重入，涉及到交易的功能加锁先，反正solidity的锁开销很小，先加锁再说
    
2.  防止重入，要记录状态的，先记录再转账
    
3.  权限，每个函数都要想好给谁用的
    
4.  只要是计算，就用safeMath
    
5.  每个函数的调用要想想是否要校验成功，特别是转账
    
6.  前端和后端的数据源只能以solidity为准，保证数据一致性，后端利用事件做到
    
7.  考虑每个函数的可见性，能不暴露的就不暴露
    
8.  能复制绝不手写，能抄袭绝不原创
    
9.  如果可以的话用weth代替eth付款
    
10.  检查-生效-交互
    

solidity本身的坑
------------

可能因不了解solidity的某些机制而导致的bug

### 1\. 重入

这个老生常谈了，加锁，在重要步骤（如转账）前先修改状态

### 2.计算溢出

这个说是已经修复了，但还是老老实实用safeMath吧

### 3.call()和delegatecall()

call() 切换上下文,我->合约1->合约2,msg.sender的结果是合约1

delegatecall() 保持上下文,我->合约1->合约2,msg.sender的结果是合约我

### 4.随机数

区块链理论上无法产生随机数，要用的话用link提供的随机数

### 5.call返回值

首先不要用transfer和send，因为这两个函数本来就是为了解决重入问题的，不完美。

call有个问题，失败的话不会报错，返回个false，所以一定要检查返回值

### 6.时间戳

旷工可以改时间，导致bug。要求很高的话可以用block来确定，BAT币就是用的startBlock和endBlock来确定时间的。要求不怎么高的话可以用时间戳

### 7.浮点数和精度

如果a/b<1,会变成0，所以最好先变成高精度数字再计算

### 8.for循环

solidity能不for就千万不要for，能for也尽量不要for，总之就是不要for。solidity的for就像这句话一样又长又臭。首先太贵，贵到最后可能导致超过gas限制，合约就废了。而且效率不高

业务bug
-----

纯属写代码的人水平问题，开发经验问题。这些bug，很可能靠工具，审计是查不出来的。多了解别人的bug，以史为镜，自我反思

### 1.Akutar NFT 一行代码34M

[https://learnblockchain.cn/article/3946](https://learnblockchain.cn/article/3946)

这里讲得很详细，就是判断用错了变量。

反思：测试用例一定要覆盖全，每个逻辑在构思的时候就用小本子把可能出现的bug记录下来；写代码的过程中，再随时记录；产品，技术，测试最后再头脑风暴，查漏补缺，最后形成文档，case；还要内部code review，讲解，避免这些低级bug

### 2.NBA签名bug

没有验证签名是谁发过来的，并且签名有没有被用过

反思：这个bug我自己写的时候也没有注意到，还好NBA爆出来了，感恩。要注意所有的内容是否要有一次性的判断

### 3.APE空投漏洞

空投的要求只需要瞬时拥有NFT，而不是持有一段时间，导致可以通过闪电贷撸走

反思：这个应该是设计问题，产品没想到可以这么玩。这个就考验产品、编程、测试人员经验了。

### 4.opensea过期订单

有人很久前保存了签名，很久之后NFT涨价了，就把签名直接传到合约里，结果NFT被低价买走。合约没有校验签名的过期时间

反思：设计问题，和ape正好相反，看来合约开发的思维要比传统项目多一个时间维度。要思考在很短或者很长的时间里合约是否安全。

### 5.Sandbox burn他人土地

burn的函数可见性是external而不是internal

反思：每个关键字都要酌情考虑

---

*Originally published on [point](https://paragraph.com/@point/solidity)*
