solidity基础-值类型
数据和变量
- Solidity 是一种静态强类型的语言
- 变量类型和需要赋值的数据类型必须匹配,或者所赋值的数据可以隐式转换为变量类型
两种类型的数据
值类型
- 值类型传值时会将值拷贝一份,传递的是值本身
- 始终按值来传递
引用类型
- 引用类型进行传递时,传递的是其指针
- 引用类型进行传递时,可以为值传递,也可以为引用传递
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
uint256 public u = 123;
string public str1 = "b00l";
string public str2 = "b00l";
function test() external {
// 修改值类型
uint256 x = u;
x = 1;
// 修改引用类型,引用传递
string storage str3 = str1;
bytes(str3)[0] = bytes1("B"); // str1 的值变为 B00l
// 修改引用类型,值传递
string memory str4 = str2;
bytes(str4)[0] = bytes1("B"); // str2 的值不变
}
}
值类型
布尔类型
- 只有 true 和 false 两个值
布尔值除了赋值得到外,还可以通过运算符的运算结果得到
- ! 逻辑非
- == 等于, != 不等于
- && 逻辑与,|| 逻辑或
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
bool public b1 = true;
bool public b2 = false;
bool public b3 = b1 == b2;
bool public b4 = b1 != b2;
bool public b5 = true && true;
bool public b6 = true || false;
}
整数类型
类型
- 有符号整型,用 int 标识
- 无符号整型,用 uint 标识
属性
- type(T).min 获取整型 T 的最小值
- type(T).max 获取整型 T 的最大值
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
int256 public u = 123; // 123
int8 public u8Min = type(int8).min; // -128
int8 public u8Max = type(int8).max; // 127
int256 public u256Min = type(int256).min; // -(2的128次方)
int256 public u256Max = type(int256).max; // 2的128次方减1
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
uint256 public u = 123; // 123
uint8 public u8Min = type(uint8).min; // 0
uint8 public u8Max = type(uint8).max; // 0
uint256 public u256Min = type(uint256).min; // 0
uint256 public u256Max = type(uint256).max; // 2的256次方减1
}
整数字面常量
- 整数字面常量中用 _ 增加可读性,不能出现在数字开头和结尾,且不能连写
- 字面常量支持任意精度
- 除法截断
- 优先使用较小类型计算
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
uint public c1 = 123_456_789;
int public c2 = -123_456_789;
uint public c3 = 123456_789;
}
定长浮点型
- Solidity还没有完全支持定长浮点型
- 可以声明定长浮点型的变量,但不能给它们赋值或把它们的值给其他变量
可以通过用户定义的值类型的 wrap / unwrap 来模拟出来
- fixed / ufixed 表示各种大小的有符号和无符号的定长浮点数
定长字节数组
定义方式 bytesN ,其中 N 可以取 1~32 中任意整数
- bytes1 / bytes32
bytesN 和 bytes 不同
- bytesN:是定长的字节数组,是值类型
- bytes:是变长字节数组,是引用类型
属性
- length,通过 length 属性可以获取定长字节数组的长度
- [index],获取定长字节数组的某个字节,但是不能修改
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
bytes1 public a1 = 0x66;
bytes2 public a2 = 0x6600;
bytes4 public a3 = 0x66000000;
bytes6 public a4 = 0x660000000000;
bytes7 public a5 = 0x66000000000000;
bytes8 public a6 = 0x6600000000000000;
bytes16 public a7 = 0x66000000000000000000000000000000;
bytes32 public a8 =
0x6600000000000000000000000000000000000000000000000000000000000000;
uint8 public len8 = a8.length;
bytes1 public index1 = a8[0];
}
字符串字面常量
- 表现形式:" " 或 ' '
- 字符串字面常量赋值给bytesN 时被解释为原始的字节形式
转义字符
- \':单引号
- \":双引号
- \\:反斜杠
- \b:退格
- \f:换页
- \n:换行符
- \r:回车
- \t:标签tab
- \v:垂直标签
- \<newline>:(转义实际换行)
Unicode字符串字面常量
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
string public ustr = unicode'你好'; // 你好
}
十六进制字面常量
- 十六进制字面常量以关键字 hex 开头,后面紧跟着用单引号或双引号包裹的字符串,例:hex"66"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
bytes1 public h = hex"66"; // 0x66
bytes3 public h3 = hex"66" hex"66" hex"66"; // 0x666666
}
Enum枚举
enum 是一种用于自定义的类型,用于表示多种状态
- 主要作用是用于限制某个事务的有限选择,比如将咖啡容量限制为:大、中、小,这样就可以确保任何人都不能购买其他容量的咖啡
- 枚举类型返回值是索引,默认值是0
- 枚举类型至少应该有一个成员
- 枚举不能多于256个成员
用户定义的值类型
Solidity允许我们在一个基本的值类型上创建一个零成本的抽象,类似于别名,但有更严格的类型要求
- 定义
type UserType is DefaultType;
方法
- UserType.wrap():从底层类型转换到自定义类型
- UserType.unwrap():从自定义类型转换到底层类型
- 没有运算符,没有成员变量,连基本的 == 都没有
地址类型
地址类型分为外部地址和合约地址,每个地址都有一块持久化内存区,称为存储
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
address a = 0x690B9A9E9aa1C9dB991C7721a92d351Db4FaC990;
}
address/uint/bytesN之间的转换
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
// 0x111122223333444455556666777788889999aaaabbbbccccddddeeeeffffcccc
bytes32 public a1 =
0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC;
// 0x111122223333444455556666777788889999aAaa
address public a2 = address(uint160(bytes20(a1)));
// 0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc
address public a3 = address(uint160(uint256(a1)));
}
两种形式的地址
- address
- address payable
属性
- balance:返回以 wei 为单位的余额
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
// 获取输入地址的余额
function getBalance1(address addr) public view returns (uint256) {
return addr.balance;
}
// 获取调用账户的余额
function getBalance2() external view returns (uint256) {
return address(msg.sender).balance;
}
}
- code:返回当前地址的代码字节码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
function getCode() public view returns (bytes memory) {
return address(this).code;
}
}
- codehash:返回地址的hash
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
function getCodeHash() public view returns (bytes32) {
return address(this).codehash;
}
}
方法
- address():将地址转换到地址类型
- payable():将普通地址转换为可支付地址
- transfer(uint256 amount):将余额转到当前地址(合约地址转账)
- send(uint256 amount):将余额转到当前地址,并返回交易成功状态(合约地址转账)
- call(bytes memory):用给定的有效载荷(payable)发出低级 CALL 调用,并返回交易成功状态和返回数据(调用合约的方法并转账)
- delegatecall(bytes memory):用给定的有效载荷(payable)发出低级 DELEGATECALL 调用,并返回交易成功状态和返回数据(调用合约的方法并转账)
- staticcall(bytes memory):用给定的有效载荷(payable)发出低级 STATICALL 调用,并返回交易成功状态和返回数据(调用合约的方法并转账)
合约类型
在合约中可以将另一个合约当做类型使用