数据类型¶
智能合约中没有浮点数
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract SimpleStorage {
People public person0 = People("Lisa", 11); // 顺序传入
People public person1 = People({name: "Chonge", favoriteNumber: 22}); // 关键字传入,要用{}
// 自定义结构体
struct People {
string name;
uint256 favoriteNumber;
}
// 可以创建不同元素类型的数组
People[] public personList; // []里为空表示动态数组
function addPerson(string memory _name, uint256 _favoriteNumber) public {
// 向数组中添加元素
// personList.push(People(_name, _favoriteNumber));
// 也可以分开写
People memory newPerson = People(_name, _favoriteNumber);
personList.push(newPerson);
}
// 声明一个映射
mapping(string => uint256) public nameToFavoriteNumber;
function addPerson(string memory _name, uint256 _favoriteNumber) public {
nameToFavoriteNumber[_name] = _favoriteNumber;
}
}
布尔型¶
bool public b1 = true;
bool public b2 = false;
整型¶
- 整数
// 同uint
int256 public i = -1; // -2**255 ~ 2**255-1
type(int).min; // 最小值
type(int).max; // 最大值
- 无符号整数,即正整数
// 长度:8~256
// uint等价于uint256,建议显性标识
uint8 public u2 = 20221209; // 0 ~ 2**8-1
unit16 public u3 // 0 ~ 2**16-1
uint256 public u1 = 1; // 0 ~ 2**256-1
字符串¶
string Text = "7c"
字节数组¶
// 长度:1~32
// bytes 等价于 bytes32
bytes32 public bt32 = "MiniSolidity"; // 存储为32字节:0x4d696e69536f6c6964697479...
bytes32 public bt32 = 0x4d696e69536f6c6964697479...; // 也可以直接写为字节形式
bytes1 public bt = bt32[0]; // bt32的第一个字节:0x4d
地址类型¶
地址类型存储一个 20 字节的值,20 字节用十六进制表示共 40 位,所以以太坊的钱包地址算上前缀 0x
,一共 42 位。
\(1Byte = 8bit\),每 4 位二进制可表示为 1 个十六进制数,即一个字节可表示为 2 个十六进制数
- 普通地址
address public addr = 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71;
- 可转账地址
payable
address payable public addr = payable(addr);
// 可转账地址有两个成员,方便查询余额和转账
addr.balance; // 地址余额
addr.transfer(1) // 合约向 addr 转账 1wei
数组¶
数组是存储相同数据类型元素的数据结构
- 固定数组
data_type[size] array_name = <elements>;
uint256[3] public a1 = [1, 2, 3];
address[100] public a2;
bytes32[5] public a3;
- 动态数组
data_type[] array_name = <elements>;
uint256[] public a1 = [1, 2, 3];
address[] public a2;
bytes32[] public a3;
// 数组的方法
uint[] public nums = [1, 2, 3];
uint public len = nums.length; // 获取数组长度:3
// 需要在函数中操作
function demo() external {
nums[2] = 33; // 修改第3个元素:[1, 2, 33, 4],index溢出会报错
nums.push(4); // 向数组末尾插入元素:[1, 2, 3, 4]
nums.push(); // 默认插入元素0:[1, 2, 3, 0]
delete nums[2]; // 将第三个元素重置为0,就相当于删除,但不改变数组长度:[1, 2, 0, 4]
nums.pop(); // 删除数组末尾元素,真删除,会改变数组长度:[1, 2, 3]
}
- 在内存中创建数组
// 需要使用 memory 修饰
// 需要用 new 操作符
// 需要声明长度,且声明后不能改变,所以改变长度的方法都不能用,可以修改值
uint[] memory a = new uint[](5);
- 返回数组中所有元素
// 需要加 memory
function returnArray() external view returns (uint[] memory) {
return nums;
}
删除数组指定索引的元素,需要自定义函数¶
- 通过移动位置,实现删除
Gas 消耗很大
uint[] public arr;
function remove(uint _index) public {
require(_index < arr.length, "index out of bound");
for (uint i = _index; i < arr.length - 1; i++) {
arr[i] = arr[i + 1];
}
arr.pop();
}
function test() external {
arr = [1, 2, 3, 4];
remove(1); // [1, 3, 4]
assert(arr.length == 3);
assert(arr[0] == 1);
assert(arr[1] == 3);
assert(arr[2] == 4);
remove(2); // [1, 3]
assert(arr.length == 2);
assert(arr[0] == 1);
assert(arr[1] == 3);
remove(0); // [3]
assert(arr.length == 1);
assert(arr[0] == 3);
remove(0); // []
assert(arr.length == 0);
}
- 通过元素替换,实现删除
Gas 消耗想对较少,但会改变数组顺序
uint[] public arr;
function remove(uint _index) public {
require(_index < arr.length, "index out of bound");
arr[_index] = arr[arr.length - 1];
arr.pop();
}
function test() external {
arr = [1, 2, 3, 4];
remove(1); // [1, 4, 3]
assert(arr.length == 3);
assert(arr[0] == 1);
assert(arr[1] == 4);
assert(arr[2] == 3);
remove(2); // [1, 4]
assert(arr.length == 2);
assert(arr[0] == 1);
assert(arr[1] == 4);
remove(0); // [4]
assert(arr.length == 1);
assert(arr[0] == 4);
remove(0); // []
assert(arr.length == 0);
}
结构体¶
// 定义结构体
struct Student{
uint256 id;
uint256 score;
}
// 使用自定义的结构体声明一个变量
Student storage st;
st.id = 11;
st.score = 100;
映射¶
// 格式:mapping(KeyType => ValueType)
// 映射的KeyType不能使用自定义的结构体
// 映射的存储位置必须是storage
mapping(uint => address) public idToAddress; // id映射到地址
mapping(address => address) public swapPair; // 币对的映射,地址到地址
idToAddress[_Key] = _Value; // 新增
枚举¶
主要用于为 uint 分配名称,使程序易于阅读和维护
enum ActionSet {Buy, Hold, Sell}; // 自定义枚举类型ActionSet
ActionSet action = ActionSet.Buy // 创建ActionSet类型变量并赋值
// 枚举类型可以显式的和uint相互转换
uint(action); // 0