Solidity常见关键字
- public,可以修饰变量和函数, 被修饰的函数或变量可以被任何合约调用(或访问),默认的变量和函数使用该属性。
- private,可以修饰变量和函数,被修饰者只能被当前合约内部的代码所调用(或访问),不能被外部合约调用或继承它的子合约调用(或访问)。
- extermal,只能修饰函数,被修饰的函数可以被当前合约之外的合约所调用(或访问),不能被自己和继承它的合约调用(或访问)。
- internal,可以修饰变量和函数,被修饰者可以被当前合约内部以及继承它的合约调用(或访问),但不能被外部合约调用(或访问)。
- view,只能修饰函数,函数内部能够对外部变量进行读取操作,但是不能进行修改。
- pure,只能修饰函数,函数内部不能对外部的变量进行读取和修改操作,它只能对传参进入的参数量进行读写操作。
ABI(Application Binary Interface):应用程序二进制接口
它的直观形式是一串Json字符串,Json里面有如下Key:
name: 字符串类型,对应的是当前项的名称。name只知道这个项的名称,究竟对于它是函数function还是uint8变量还是什么,并不清楚。
type: 字符串类型,标明当前项的项是什么类型(具体是一个函数还是一个变量)。常见的type有下面的取值
1.function 函数
2. construct 构造函数
3. event 事件
4. 变量类型,如: address, uint8, bool ...
constant: 布尔类型,代表当前项的操作结果是否会被写进区块链上,是则为true,否则为false。
stateMutability: 字符串类型。stateMutability有如下取值
1. pure: 代表不会读和写区块链状态
2. view: 代表会读区块链状态,但是不会改写区块链状态
3. nonpayable: 代表会改写区块链状态,如转账transfer和授权approve这连个ERC20标准的函数就是可以用来改写区块链
payable: 布尔类型,代表当前的函数function是否可以接收ETH Token,可以则为true,否则为false
inputs: 其类型是Json数组,代表当前项入参信息,内部会把每个参数的名称及其所对应的类型列出。一般来说,input会跟随type是function或者事件event而含有值。inputs中的Json变量除了name和type外,还含有如下变量:
1. Indexed,在Solidity代码事件event中,其入参有设置为Indexed关键字,此时Json中的这个变量对应的值为true,反之为false
2. components: 该变量的类型是Json数组,当参数的type是struct结构类型是,该变量就会出现
outputs: 和inputs的含义类似,其类型也是Json数组,代表的是当前项的返回值,内部表达是返回值的名称和类型。inputs和outputs如果没有值,便默认是[]。
anonymous: 布尔类型,它和"标准的事件(Event)"的Indexed的设置有关,当为true的时候,在event中的入参即使是属于Indexed关键字的形式也不会保存到Topic中,为false则会。
找一个ABI看看
[
{
"inputs":[
{
"internalType":"address",
"name":"_logic",
"type":"address"
},
{
"internalType":"bytes",
"name":"_data",
"type":"bytes"
}
],
"stateMutability":"payable",
"type":"constructor"
},
{
"anonymous":false,
"inputs":[
{
"indexed":false,
"internalType":"address",
"name":"previousAdmin",
"type":"address"
},
{
"indexed":false,
"internalType":"address",
"name":"newAdmin",
"type":"address"
}
],
"name":"AdminChanged",
"type":"event"
},
{
"anonymous":false,
"inputs":[
{
"indexed":true,
"internalType":"address",
"name":"beacon",
"type":"address"
}
],
"name":"BeaconUpgraded",
"type":"event"
},
{
"anonymous":false,
"inputs":[
{
"indexed":true,
"internalType":"address",
"name":"implementation",
"type":"address"
}
],
"name":"Upgraded",
"type":"event"
},
{
"stateMutability":"payable",
"type":"fallback"
},
{
"stateMutability":"payable",
"type":"receive"
}
]
合约标准
智能合约类型有很多,但是目前token合约标准主要是以 ERC20 和 ERC721 为标准。
ERC20标准
ERC20标准中包括了成员变量、函数和事件。
(1) 标准的成员变量
- string public name,这是token的名称,全称,Ethereum
- string public symbol,这是简称,如ETH
- uint8 decimals,精度,即小数点的位数
- uint256 totalSupply,总发行量
(2) 标准的函数和标准事件
interface IERC20 {
// 这是token的名称,全称,Ethereum
string public name;
// 这是简称,如ETH
string public symbol;
// 精度,即小数点的位数
uint8 decimals;
// 总发行量
uint256 totalSupply;
/*
标准的函数
*/
// 查询totalSupply函数
function totalSupply() external view returns (uint256);
// 查询某用户Token余额函数
function balanceOf(address account) external view returns (uint256);
// 转账函数
function transfer(address recipient, uint256 amount) external returns (bool);
// 根据授权关系查询授权数量函数
function allowance(address owner, address spender) external view returns (uint256);
// 授权函数
function approve(address spender, uint256 amount) external returns (bool);
// 转账函数
function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool);
/*
标准的事件
// ERC20标准中,规定了在编写转账、授权函数代码时,必须在成功转账后触发事件。
*/
// Transfer在transfer和transferFrom函数内触发
event Transfer(address indexed from, address indexed to, uint256 value);
// 在成功调用approve函数后对应的一个事件
event Approval(address indexed owner, address indexed spender, uint256 value );
}
以下是一个标准的ERC20合约
contract ERC20 {
// 这是token的名称,全称,Ethereum
string public name;
// 这是简称,如ETH
string public symbol;
// 精度,即小数点的位数
uint8 decimals;
// 总发行量
uint256 totalSupply;
/*
标准的函数
*/
// 查询totalSupply函数
function totalSupply() external view returns (uint256){};
// 查询某用户Token余额函数
function balanceOf(address account) external view returns (uint256){};
// 转账函数
function transfer(address recipient, uint256 amount) external returns (bool){};
// 根据授权关系查询授权数量函数
function allowance(address owner, address spender) external view returns (uint256){};
// 授权函数
function approve(address spender, uint256 amount) external returns (bool){};
// 转账函数
function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool){};
/*
标准的事件
// ERC20标准中,规定了在编写转账、授权函数代码时,必须在成功转账后触发事件。
*/
// Transfer在transfer和transferFrom函数内触发
event Transfer(address indexed from, address indexed to, uint256 value);
// 在成功调用approve函数后对应的一个事件
event Approval(address indexed owner, address indexed spender, uint256 value );
}
ERC721标准
ERC721标准中包括了成员变量、函数和事件。该合约主要提现一对一关系上。
(1) 成员变量
ERC721和ERC20成员变量基本一致,但是ERC721不需要decimal变量。
(2) 标准的函数和标准事件
/*
标准的函数
*/
// 查询totalSupply函数
function totalSupply() external view returns (uint256){};
// 查询某用户Token余额函数
function balanceOf(address account) external view returns (uint256){};
// 转账函数
function transfer(address recipient, uint256 amount) external returns (bool){};
// 所有权查询
function ownerOf(uint256 _tokenId) external view returns (uint256 balance){};
// 授权函数
function approve(address spender, uint256 amount) external returns (bool){};
// 转账函数
function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool){};
// 该标准主要的作用是用来检测当前智能合约实现了哪些接口,可以根据interfaceID来查询接口ID,存在返回true,否则返回false
// 该标准函数会消耗gas,至少消耗30000Gas
function supportsInterface(bytes4 _interfaceID) external view returns (bool){};
// 可选实现函数
function name() public view returns (string name);
function symbol() public view returns (string symbol);
function tokenOfowner(address _owner) external view returns(uin256 [] tokenIds);
function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl);
ERC721和ERC20相比,主要是多了以下函数
function ownerOf(uint256 _tokenId) external view returns (uint256 balance){};
这个函数的功能是根据tokenId查询该token的所有者。
function tokenOfowner(address _owner) external view returns(uin256 [] tokenIds){};
这个函数的功能是根据某地址,查询该地址所拥有的tokenId
function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl){};
这个函数内部是自定义的字符串,就是一些基本信息。比如,这里写的是url,可以理解为一个NFT存储地链接。
function supportsInterface(bytes4 _interfaceID) external view returns (bool){};
标准主要的作用是用来检测当前智能合约实现了哪些接口,可以根据interfaceID来查询接口ID,存在返回true,否则返回false。该标准函数会消耗gas,至少消耗30000Gas。
以下是ERC721智能合约
contract ERC721 {
// 这是token的名称,全称,Ethereum
string public name;
// 这是简称,如ETH
string public symbol;
// 精度,即小数点的位数
uint8 decimals;
// 总发行量
uint256 totalSupply;
/*
标准的函数
*/
// 查询totalSupply函数
function totalSupply() external view returns (uint256){};
// 查询某用户Token余额函数
function balanceOf(address account) external view returns (uint256){};
// 转账函数
function transfer(address recipient, uint256 amount) external returns (bool){};
// 所有权查询
function ownerOf(uint256 _tokenId) external view returns (uint256 balance){};
// 授权函数
function approve(address spender, uint256 amount) external returns (bool){};
// 转账函数
function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool){};
// 该标准主要的作用是用来检测当前智能合约实现了哪些接口,可以根据interfaceID来查询接口ID,存在返回true,否则返回false
// 该标准函数会消耗gas,至少消耗30000Gas
function supportsInterface(bytes4 _interfaceID) external view returns (bool){};
// 可选实现函数
function name() public view returns (string name);
function symbol() public view returns (string symbol);
function tokenOfowner(address _owner) external view returns(uin256 [] tokenIds);
function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl);
/*
标准的事件
// ERC721标准中,规定了在编写转账、授权函数代码时,必须在成功转账后触发事件。
*/
// Transfer在transfer和transferFrom函数内触发
event Transfer(address indexed from, address indexed to, uint256 value);
// 在成功调用approve函数后对应的一个事件
event Approval(address indexed owner, address indexed spender, uint256 value );
}