基本类型 | 说明 | 示例 |
---|---|---|
string | 字符串,UTF8编码 | "Hello World","世界" |
bool | 布尔类型 | true,false |
int ( int8,int16,int24... int256 ) |
有符号整数(负数,0,正数) 从8位开始到256位,每次步长8位 int = int256 |
-100,0,2980 |
uint (uint8,uint16,uint24... uint256 ) |
无符号整数(0,正数) 从8位开始到256位,每次步长8位 uint = uint256 |
0,1016 |
address | 地址,表示外部账户或合约账户,可用来转账 | 0x35eb43fxxxx78c905dc148f21 |
pragma solidity^0.6.0;
contract demo{
string public name;
int8 public age;
int32 salary;
bytes32 public authHash;
constructor(string memory _name,int8 _age, int32 _salary) public{
name = _name;
age =_age;
salary = _salary;
authHash = keccak256(abi.encode(_name,_age,_salary));
}
}
若使用0.8.7版本,则会出现2个警告提示:
解决:(1)警告一:在首行增加SPDX许可标识符;(2)constructor去除修饰符public
// SPDX-License-Identifier: MIT
pragma solidity^0.8.7;
contract demo{
string public name;
int8 public age;
int32 salary;
bytes32 public authHash;
constructor(string memory _name,int8 _age, int32 _salary) {
name = _name;
age =_age;
salary = _salary;
authHash = keccak256(abi.encode(_name,_age,_salary));
}
}
内建对象 | 类型 | 说明 |
---|---|---|
block.coinbase | address | 当前块的矿工地址 |
block.difficulty | uint | 当前块的难度系数 |
block.gaslimit | uint | 当前块gas的上限 |
block.number | uint | 当前块的编号 |
blockhash | bytes32 | 返回指定块的哈希值 |
block.timestamp | uint | 当前块的时间戳,等于now |
内建对象 | 类型 | 说明 |
---|---|---|
msg.data | bytes | 完整的calldata |
msg.gas | uint | 剩余的gas量 |
msg.sender | address | 消息发送方(调用者)地址 |
msg.sig | bytes4 | calldata的前四个字节(即函数标识符) |
msg.value | uint | 所发送的消息中以太的数量(单位wei) |
pragma solidity^0.6.0;
contract random{
address public sender;
bytes32 public block_hash;
uint256 public time;
uint256 public random_num;
constructor() public {
sender = msg.sender;
block_hash = blockhash(0);
time = block.timestamp;
random_num = uint256(keccak256(abi.encode(sender,block_hash,time))) % 100;
}
}
定义:function func_name(paramlist...) modifiers returns (returnlist...)
定义内容 | 说明 |
---|---|
function | 函数声明的关键字 |
func_name | 自定义函数名 |
paramlist | 参数列表,可以有0或多个参数;格式:参数类型 参数名称 |
modifiers | 函数修饰符 |
returns | 返回值关键字 |
returnlist | 返回值类型列表,可以同时返回多个值,不超过7个 |
pragma solidity^0.6.0;
contract sum{
function addFrom1to100() public view returns(int16) {
int16 sum;
int8 i;
for (i=1; i <101; i++) {
sum += i;
}
return sum;
}
}
pragma solidity^0.6.1;
contract compareString{
function compareStr(string memory a, string memory b) public pure returns(bool) {
bytes32 a_hash = keccak256(abi.encode(a));
bytes32 b_hash = keccak256(abi.encode(b));
return a_hash == b_hash;
}
}
编译部署后如下图所示:
修饰符 | 分类 | 说明 |
---|---|---|
public | 调用控制类 | 都可以调用该函数,和private互斥 |
private | 调用控制类 | 只有该合约可以调用,和public互斥,子类不可继承 |
external | 调用控制类 | 外部函数,外部正常访问,内部不可以调用,子类可继承 |
internal | 调用控制类 | 内部函数,内部正常访问,外部不可以访问,子类可继承 |
view | 状态变量访问控制类 | 合约不修改状态变量 |
constant | 状态变量访问控制类 | 合约不修改状态变量,与view一样,目前已废除 |
pure | 状态变量访问控制类 | 合约不修改状态变量,也不读取状态变量,如上面例子 “比较两个字符串是否相等” 的例子 |
payable | 资金控制类 | 涉及以太币转移,即可支付的 |
自定义修饰 | 自定义控制类 | 支持自定义修饰符号modifier |
pragma solidity^0.6.0;
contract functionModifier{
//状态变量
uint16 count;
//设置状态变量,使用外部函数修饰符external
function setCount(uint16 _count) external {
count = _count;
}
//获取状态变量,使用修饰符view
function getCount() public view returns(uint16) {
return count;
}
//充值,使用支付修饰符payable
//通过 设置value的值 给合约账户充值
function deposit() public payable {
}
//查询合约账户余额,使用view修饰符
function getContractAccountBalance() public view returns (uint256){
return address(this).balance; //this为本合约对象
}
}
以上在Remix可以看到不同修饰符对就的颜色也不一样:
红色:产生资金交易,消耗gas,使用修饰符payable;
桔色:修改状态变量,消耗gas,使用修饰符external;
蓝色:不修改状态变量,使用修饰符view
例:充值&提现
pragma solidity^0.6.0;
contract depositAndWithdraw{
//充值,从调用者账户向合约账户充值
function deposit() public payable{
}
//提现,从合约账户向调用者账户转账
function withdraw(uint256 _amount) public payable{
msg.sender.transfer(_amount);
}
//查询合约余额
function getContractAccountBalance() public view returns(uint256) {
return address(this).balance;
}
//查询调用者账户余额
function getSenderAccountBalance() public view returns (uint256) {
return msg.sender.balance;
}
}
使用0.8.7版本编写遇到错误:TypeError: "send" and "transfer" are only available for objects of type "address payable", not "address".
//提现,从合约账户向调用者账户转账
function withdraw(uint256 _amount) public payable{
payable(msg.sender).transfer(_amount);
}
类型 | 说明 |
---|---|
T[N] | 定长数组,N为数组长度 |
T[] | 动态数组,使用push推入 |
struct | 结构体 |
mapping(T1=>T2) | 映射表 |
bytesN | 字节数组,N为1~32整数 |
pragma solidity^0.6.0;
contract array{
//定长数组
string[3] public names;
//动态数组
int8[] public ages;
constructor() public {
names[2] = "tracy";
ages.push(25);
}
//获取数组长度
function getLength() public view returns(uint256,uint256) {
//使用数组变量名.length获取长度
return (names.length,ages.length);
}
//定长数组转换变长数组
function arrayToslice() public view returns (string[] memory) {
//定义一个变长数组,将定长数组值copy
string[] memory _names = new string[] (names.length);
for (uint256 i = 0; i < names.length; i++) {
_names[i] = names[i];
}
return _names;
}
}
pragma solidity^0.6.0;
contract mappingEx{
//定义一个mapping,key表示地址,value表示地址对应的用户名
mapping(address=>string) public addr_name;
constructor() public {
//调用者账户地址对应的用户初始化
addr_name[msg.sender] = "tracy";
}
//设置地址对应的用户名
function setName(string memory _name) public {
addr_name[msg.sender] = _name;
}
//根据地址获取用户名
function getName(address _addr) public view returns (string memory) {
return addr_name[_addr];
}
}
memory 值传递
storage 引用传递
pragma solidity^0.6.1;
//定义一个结构体
struct User{
string name;
int8 age;
}
contract structEx{
//定义状态变量,结构体类型
User public user;
constructor() public {
user.name = "Tracy";
user.age = 25;
}
//设置结构体变量中的属性值(使用memory)
function setName_memory(string memory _name) public{
User memory user_memory = user;
user_memory.name = _name;
}
//设置结构体变量中的属性值(使用storage)
function setAge_storage(int8 _age) external {
User storage user_storage = user;
user_storage.age = _age;
}
}
使用0.8.7版本时,提示警告信息:
需要在函数后面加上修饰符view
//设置结构体变量中的属性值(使用memory)
function setName_memory(string memory _name) public view{
User memory user_memory = user;
user_memory.name = _name;
}
断言用于条件不成立时回退之前的操作。
function assert(bool cond_expr);
对用户惩罚,扣光所有gas。用于内部变量判断,pure函数或检测系统错误。
function require(bool cond_expr, string msg);
相对温和,退还剩余的gas。用于业务逻辑判断。
pragma solidity^0.6.0;
contract assertEx{
function deposit(uint256 _amount) public payable {
//充值判断
require(msg.value == _amount, "msg.value 必须等于_amount参数值");
assert(_amount > 0);
}
}
当执行assert时,扣光所有gas
使用0.8.7版本时,报错如下:
// SPDX-License-Identifier: MIT
pragma solidity^0.8.7;
contract assertEx{
function deposit(uint256 _amount) public payable {
//充值判断
require(msg.value == _amount);
assert(_amount > 0);
}
}
modifier modifier_name(){
require(bool cond_expr, "error message");
//...
_; //占位符号,标识modifier的结束
}
//减少重复代码产生
pragma solidity^0.6.0;
contract modifierEx{
//定义的一个地址状态变量
address public admin;
string name;
//初始化状态变量为调用者,即部署合约的账户地址
constructor() public {
admin = msg.sender;
}
//自定义修饰符,只有部署合约的账户地址才能访问
modifier onlyadmin{
require(msg.sender == admin, "只有部署合约的用户才能访问此函数");
_;
}
//此函数只有部署合约的用户才能访问
function setValue() external onlyadmin {
name = "tracy";
}
}
更多信息可参见官网文档:Solidity — Solidity develop 文档