目录
1. 内置的全局变量
2. 错误处理
3. 访问函数
4. 创建合约
5. 合约继承
6. 修饰器modifier
最后
补充知识:
转账的话是与部署者无关,与交易者有关!
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; // 获取调用者的地址 } }
msg.value:
可以接收payable修饰的转账金额,单位:wei,必须要有payable
可以用接收的value进行判断限制,比如转账金额必须在某个范围,balance做不到
pragma solidity 0.4.22; contract Value { uint256 public money; function getValue() public payable { money = msg.value; } }
如果加if判断:
pragma solidity 0.4.22; contract Value { uint256 public money; function getValue() public payable { if( msg.value == 666) { // 转钱金额为666wei才赋值 money = msg.value; } } }
注意:需要转钱,注意单位默认是wei
2. 错误处理
require:
require 式的异常不会消耗任何 gas,官方推荐使用require,相当于if {throw},没有else的
最终底层触发的也是assert式的错误
require(msg.value == 666); // 如果不满足则报错,否则继续往下执行
类似于下面的:注意条件正好是相反的
if (msg.value <= 6 * 10 ** 18) { // todo 涉及到错误处理 throw; }
assert:
即使有错误,也会执行并扣除gas
assert(msg.value == 666 ); // 如果不满足则报错,否则继续往下执行
revert():处理更复杂逻辑的场景,比如if/else
if (msg.value <= 6 * 10 ** 18){ revert(); } else { b = 666; }
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; } }
如果用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(); // 这里必须加括号,是个访问函数 } }
4. 创建合约
new : 返回的是地址,需要转合约类型
初始化合约的时候用到这种方式
Fan h = new Fan(); // 把地址直接强转为合约类型
和java有点像
合约变量(Fan public h),此时是空的,需要赋值地址才能使用,否则报错
合约类型作为参数的场景用到这种方式
Fan public h; // 函数中赋值 address addr = new Fan(); h = Fan(addr); // 赋值地址
转账语法:
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 {} }
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; } }
可以结合构造函数,判断是不是管理员(部署者),只有是管理员才可以访问的函数可以加修饰器
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; } }
最后
小生凡一,期待你的关注。