Solidity 进阶编程 | 注意一下合约中的细节
【摘要】
目录
1. 内置的全局变量2. 错误处理3. 访问函数4. 创建合约5. 合约继承6. 修饰器modifier最后
补充知识:
转账的话是与部署者无关,与交易者有关!gas是以太坊网络中的...
补充知识:
- 转账的话是与部署者无关,与交易者有关!
- gas是以太坊网络中的一个计量单位,是为了对算力消耗进行量化而设计的指标,也就是说有了gas这个计算单位,我们可以方便的计算出用户完成一笔交易需要支出多少gas费用,矿工完成一个区块的打包确认能收到多少gas报酬。
1. 内置的全局变量
- msg.sender:
获取调用者地址,下面的例子是部署者调用了,所以是部署者的地址,
比如a账户
部署,但是是使用b账户
调用下getOwner
的话,那么这个时候的owner
就是b账户
的地址了。
pragma solidity 0.4.22;
contract Owner {
address public owner;
function getOwner() public {
owner = msg.sender; // 获取调用者的地址
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- msg.value:
可以接收payable修饰的转账金额,单位:wei,必须要有payable
可以用接收的value
进行判断限制,比如转账金额必须在某个范围,balance
做不到
pragma solidity 0.4.22;
contract Value {
uint256 public money;
function getValue() public payable {
money = msg.value;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
如果加if
判断:
pragma solidity 0.4.22;
contract Value {
uint256 public money;
function getValue() public payable {
if( msg.value == 666) { // 转钱金额为666wei才赋值
money = msg.value;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
注意:需要转钱,注意单位默认是wei
内置的全局变量 | 简称 | 类型 |
---|---|---|
blockhash | 哈希值 | byte32 |
block.coinbase | 当前块矿工的地址 | address |
block.difficulty | 当前块的难度 | uint |
block.gaslimi | 当前块的gaslimit | uint |
block.number | 当前块的块号 | uint |
block.timestamp | 当前块的时间戳 | uint |
gasleft() | 剩余的gas | uint |
msg.sender | 调用者的地址 | address |
msg.value | 转账的金额(单位:wei) | uint |
msg.data | 完整的调用数据 | calldata bytes |
now | 当前块的时间戳 | uint(和block.timestamp相同) |
tx.gasprice | 交易的gas价格 | uint |
tx.origin | 交易的发送者 | address |
2. 错误处理
- require:
require 式的异常不会消耗任何 gas,官方推荐使用require,相当于if {throw},没有else的
最终底层触发的也是assert式的错误
require(msg.value == 666); // 如果不满足则报错,否则继续往下执行
- 1
类似于下面的:注意条件正好是相反的
if (msg.value <= 6 * 10 ** 18) {
// todo 涉及到错误处理
throw;
}
- 1
- 2
- 3
- 4
- assert:
即使有错误,也会执行并扣除gas
assert(msg.value == 666 ); // 如果不满足则报错,否则继续往下执行
- 1
- revert():处理更复杂逻辑的场景,比如
if/else
if (msg.value <= 6 * 10 ** 18){
revert();
} else {
b = 666;
}
- 1
- 2
- 3
- 4
- 5
- require(条件); 如果满足条件则继续往下执行,如果不满足则报错,不扣除gas,推荐使用
- assert(条件); assert扣除gas,不推荐使用
- revert(): 负责逻辑中使用,if(条件){revert();}else{…}
3. 访问函数
原来要返回一个变量,得写个函数返回
pragma solidity 0.4.22;
contract Hello {
string name = "hallen";
function get_name() public view returns(string){
return name;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
如果用public修饰了变量,会生成一个同名的访问函数,可以直接访问
pragma solidity 0.4.22;
contract Fan {
string public name = "fanone";
function getName() public view returns(string){
return name;
// return this.data(); 合约内部使用this也是要调用访问函数的
}
}
contract One {
function getHelloName() public view returns (string){
Fan h = new Fan(); // 地址直接强转合约类型
return h.name(); // 这里必须加括号,是个访问函数
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
4. 创建合约
- new : 返回的是地址,需要转合约类型
初始化合约的时候用到这种方式
Fan h = new Fan(); // 把地址直接强转为合约类型
- 1
和java有点像
合约变量(Fan public h),此时是空的,需要赋值地址才能使用,否则报错
合约类型作为参数的场景用到这种方式
Fan public h;
// 函数中赋值
address addr = new Fan();
h = Fan(addr); // 赋值地址
- 1
- 2
- 3
- 4
转账语法:
h.get_money.value(20).gas(800)();
h必须是赋值地址后的合约对象
pragma solidity 0.4.24;
contract Test1{
// 获取转账钱
function contractGetMoney() public payable{
}
// 查看余额
function getBalance() public view returns(uint256){
return address(this).balance;
}
}
contract Test2 {
// 查看余额
function getBalance() public view returns(uint256){
return address(this).balance;
}
// 获取转账钱
function contractGetMoney()public payable{
}
// transfer:谁调用就给谁转钱
Test1 public t1;
function getAddr(address addr) public{
t1 = Test1(addr);
}
// 转钱给Test1合约
function payToT1() public{
t1.contract_get_money.value(5 * 10 **18).gas(200)();
}
// 付钱得用payable修饰,使用匿名函数
function () public payable {}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
5. 合约继承
- 使用
is
关键字,多个父合约用逗号隔开
contract 合约名 is 父合约1,父合约2,… {}
constract Cat is Animail,Lactation{} // Lactation:哺乳动物
如果两个父合约中有相同的函数,则遵循最远继承原则(继承顺序,Animail最近,Lactation最远,所以是Lactation中的)
6. 修饰器modifier
在函数执行前检查是否满足前置条件,满足条件才执行函数
pragma solidity 0.4.22;
contract Value {
uint256 public money;
modifier check_money(){
require(msg.value == 10);
_; // 修饰的代码,指进入函数后的所有代码
}
function get_value() public payable check_money{ // check_money就是前面定义的修饰器
money = msg.value;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
可以结合构造函数,判断是不是管理员(部署者),只有是管理员才可以访问的函数可以加修饰器
pragma solidity 0.4.22;
contract Value {
address public owner;
uint256 public money;
constructor() public{
owner = msg.sender;
}
modifier check_owner(){
require(msg.sender == owner);
_; // 修饰的代码,指进入函数后的所有代码
}
function get_value() public payable check_money{
money = msg.value;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
最后
小生凡一,期待你的关注。
文章来源: blog.csdn.net,作者:小生凡一,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_45304503/article/details/118979085
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)