# solidity 上的坑

Original: <https://lifelonglearn.ing/wtf-solidity>

Author: [奶爸](https://lifelonglearn.ing/users/3b04650c-8231-499b-8ef0-381fc4d7efb0)

Published: 2020-08-07T01:45:32Z

Updated: 2026-09-27T06:57:43Z

Version: 1

Solidity 是一种类 JavaScript 语法的运行与以太坊 EVM 上的智能合约语言，目前（v0.7.1）限制还是很大，很多业务逻辑受限于 Solidity 的蹩脚设计无法实现。

从 0.4.x 一路用到 0.7.x，也算是使用了一年多了，记忆比较深刻，比较难定位到问题的两个坑，在这里跟大家分享一下。

## uint 越界

一般来说使用 **OpenZeppelin** 的 `SafeMath` 库可以避免大多数情况下的越界情况，但是在一个简单的循环中，我们可能考虑不到，比如说这种情况：

```javascript
uint[10] memory aUintArray;
for (uint i = aUintArray.length - 1; i >= 0; i--) {
   do something
}
```

在这个情境下你是否发现了什么问题？这个循环到 0 的时候，会越界，0--，这样智能合约就会出错了。

## delete 用法

`delete` 是个比较常用的用法，而且使用 `delete` 还会返还部分 Gas 费用，在 `mapping` 类型的数据中使用 `delete` 是十分正常的，比如 `mapping(address => uint) _addressToID` 这种，`delete _addressToID(msg.sender)` 会将 `msg.sender` 这个 key 的 value 置为目标数据类型的默认值（布尔值：false，数字：0），这也是我们期望的。

那么在数组中，`delete` 就显得比较奇怪了，比如说：

```javascript
uint[] uintArray;

function deleteIndex(uint i) public {
   uint len = uintArray.length;
   assert(i >= 0 && i < len); // 编号 ①
   delete uintArray(i);
   assert(uintArray.length == len-1); // 编号 ②
}
```

你认为 `编号②` 是 `true` 还是 `false` ？实际上是 `false` ，solidity 在 `delete` 删除数组元素时只会将该元素位置置为数组类型的默认值，并不会改变数组长度。
文档地址：[delete](https://lifelonglearn.ing/r/go?url=aHR0cHM6Ly9zb2xpZGl0eS5yZWFkdGhlZG9jcy5pby9lbi92MC43LjAvdHlwZXMuaHRtbD9oaWdobGlnaHQ9ZGVsZXRlI2RlbGV0ZQ==)

```
delete a[x] deletes the item at index x of the array and leaves all other elements and the length of the array untouched. This especially means that it leaves a gap in the array. If you plan to remove items, a mapping is probably a better choice.
```

## 删除数组元素

如上面一个部分所述，​**删除数组元素时只会将该元素位置置为数组类型的默认值，并不会改变数组长度**​，那么我们应当如何正确的删除数组内的元素呢？

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

contract Test {
    uint[] public arr;
  
    function add(uint item) public {
        arr.push(item);
    }
  
    function remove(uint item) public {
        bool flag;
        for (uint i = 0; i < arr.length; i++) {
            if (arr[i] == item) {
                // 将要删除的元素与最后一个元素互换
                arr[i]=arr[arr.length-1];
                // 删除最后一个元素
                arr.pop();
                flag = true;
            }
        }
        if (!flag) revert("item not found");
    }
  
    function len() public view returns(uint) {
        return arr.length;
    }

}
```
