2020年07月12日12:04:35
2019年09月26日10:01:43
pragma
版本标识指令,用来启动编译器检查。
使用规范:
pragma solidity ^0.5.2;
这样的话,源文件不允许低于0.5.2版本的编译器编译,也不允许高于0.6.0版本的编译器编译。(第二个条件因使用^被添加)
每个合约可以包括状态变量,函数,事件Event,结构体,枚举类型,合约可以从其他合约继承。
指永久地存储在合约中的值。
合约内——方法外
pragma solidity >=0.4.0 <0.7.0;
contract TinyStorage {
uint storedXlbData; // 状态变量
// ...
}
函数是合约中代码的可执行单元。
pragma solidity >=0.4.0 <0.7.0;
contract TinyAuction {
function Mybid() public payable { // 定义函数
// ...
}
}
函数接受参数和返回值。
修饰符可以用来以声明的方式来修改函数语义。
pragma solidity >=0.4.22 <0.7.0;
contract MyPurchase {
address public seller;
modifier onlySeller() { // 修饰器
require(
msg.sender == seller,
"Only seller can call this."
);
_;
}
function abort() public onlySeller { // 修饰器用法
// ...
}
}
事件是能方便地调用以太坊虚拟机日志功能的接口。
pragma solidity >=0.4.21 <0.7.0;
contract TinyAuction {
event HighestBidIncreased(address bidder, uint amount); // 事件
function bid() public payable {
// ...
emit HighestBidIncreased(msg.sender, msg.value); // 触发事件
}
}
事件编写:
pragma solidity >=0.4.21 <0.7.0;
contract ClientReceipt {
event Deposit(
address indexed _from,
bytes32 indexed _id,
uint _value
);
function deposit(bytes32 _id) public payable {
// 事件使用 emit 触发事件。
// 我们可以过滤对 `Deposit` 的调用,从而用 Javascript API 来查明对这个函数的任何调用(甚至是深度嵌套调用)。
emit Deposit(msg.sender, _id, msg.value);
}
}
使用 JavaScript API 调用事件的用法如下:
var abi = /* abi 由编译器产生 */;
var ClientReceipt = web3.eth.contract(abi);
var clientReceipt = ClientReceipt.at("0x1234...xlb67" /* 地址 */);
var event = clientReceipt.Deposit();
// 监听变化
event.watch(function(error, result) {
// 结果包含 非索引参数 以及 主题 topic
if (!error)
console.log(result);
});
// 或者通过传入回调函数,立即开始听监
var event = clientReceipt.Deposit(function(error, result) {
if (!error)
console.log(result);
});
上面的输出如下所示(有删减):
{
"returnValues": {
"_from": "0x1111…FFFFCCCC",
"_id": "0x50…sd5adb20",
"_value": "0x420042"
},
"raw": {
"data": "0x7f…91385",
"topics": ["0xfd4…b4ead7", "0x7f…1a91385"]
}
}
结构体是可以将几个变量分组的自定义类型。
pragma solidity >=0.4.0 <0.7.0;
contract TinyBallot {
struct Voter { // 结构体
uint weight;
bool voted;
address delegate;
uint vote;
}
}
枚举可用来创建一定数量的“常量值”构成的自定义类型。
pragma solidity >=0.4.0 <0.7.0;
contract Upchain {
enum State { Created, Locked, InValid } // 枚举
}
“undefined”或“null”值的概念在Solidity中不存在,但是新声明的变量总是有一个默认值,具体的默认值跟类型相关。
bool
:true或者falseint
/ uint
:分别表示有符号和无符号的不同位数的整型变量。 支持关键字 uint8
到 uint256
(无符号,从 8 位到 256 位)以及 int8
到 int256
,以 8
位为步长递增。uint
和 int
分别是 uint256
和 int256
的别名。
地址类型有两种形式,他们大致相同:
address
:保存一个20字节的值(以太坊地址的大小)。ddress payable
:可支付地址,与address
相同,不过有成员函数transfer
和send
。
这种区别背后的思想是 address payable
可以接受以太币的地址,而一个普通的 address
则不能。
类型转换:
允许从 address payable
到 address
的隐式转换,而从 address
到 address payable
的转换是不可以的( 执行这种转换的唯一方法是使用中间类型,先转换为 uint160
)
大部分情况下你不需要关心
address
与address payable
之间的区别,并且到处都使用address
。 例如,如果你在使用取款模式, 你可以(也应该)保存地址为address
类型, 因为可以在msg.sender
对象上调用transfer
函数, 因为msg.sender
是address payable
。
address
和address payable
的区别是在 0.5.0 版本引入的,同样从这个版本开始,合约类型不再继承自地址类型,不过如果合约有可支付的回退( payable fallback )函数,合约类型仍然可以显示转换为address
或address payable
。
可以使用 balance
属性来查询一个地址的余额, 也可以使用 transfer
函数向一个可支付地址(payable address)发送 Ether (以 wei 为单位)
address x = 0x123;
address myAddress = this;
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);
如果当前合约的余额不够多,则 transfer
函数会执行失败,或者如果以太转移被接收帐户拒绝, transfer
函数同样会失败而进行回退。
send
是 transfer
的低级版本。如果执行失败,当前的合约不会因为异常而终止,但 send
会返回 false
。
call
, delegatecall
和 staticcall
为了与不符合应用二进制接口Application Binary Interface(ABI) 的合约交互,或者要更直接地控制编码,提供了函数 call
,delegatecall
和 staticcall
。 它们都带有一个bytes memory
参数和返回执行成功状态(bool
)和数据(bytes memory
)。
所有三个函数
call
,delegatecall
和staticcall
都是非常低级的函数,应该只把它们当作 最后一招 来使用,因为它们破坏了 Solidity 的类型安全性。
每一个contract定义都有他自己的类型。
您可以隐式地将合约转换为从他们继承的合约。 合约可以显式转换为 address
类型。
只有当合约具有可支付回退函数时,才能显式和 address payable
类型相互转换 转换仍然使用 address(x)
执行,而不是使用 address payable(x)
。
在版本0.5.0之前,合约直接从地址类型派生的, 并且
address
和address payable
之间没有区别。
字符串字面常量是指由双引号或单引号引起来的字符串("foo"
或者 ‘bar‘
)。 不像在 C 语言中那样带有结束符;"foo"
相当于 3 个字节而不是 4 个。 和整数字面常量一样,字符串字面常量的类型也可以发生改变,但它们可以隐式地转换成 bytes1
,……,bytes32
,如果合适的话,还可以转换成 bytes
以及 string
。
映射类型在声明时的形式为 mapping(_KeyType => _ValueType)
。 其中 _KeyType
可以是任何基本类型,即可以是任何的内建类型加上bytes
and string
。 而用户定义的类型或复杂的类型如:合约类型、枚举、映射、结构体、即除bytes
and string
之外的数组类型 是不可以作为 _KeyType
的类型的。
_ValueType
可以是包括映射类型在内的任何类型。
映射可以视作 哈希表 ,它们在实际的初始化过程中创建每个可能的 key, 并将其映射到字节形式全是零的值:一个类型的 默认值。然而下面是映射与哈希表不同的地方: 在映射中,实际上并不存储 key,而是存储它的 keccak256
哈希值,从而便于查询实际的值。
正因为如此,映射是没有长度的,也没有 key 的集合或 value 的集合的概念。
pragma solidity >=0.4.0 <0.7.0;
contract MappingExample {
mapping(address => uint) public balances;
function update(uint newBalance) public {
balances[msg.sender] = newBalance;
}
}
contract MappingLBC {
function f() public returns (uint) {
MappingExample m = new MappingExample();
m.update(100);
return m.balances(this);
}
}
60、solidity编程语言了解、实践-1——2020年07月12日12:01:12
原文:https://www.cnblogs.com/oneapple/p/13287916.html