目录
1. 内置的全局变量
2. 错误处理
3. 访问函数
4. 创建合约
5. 合约继承
6. 修饰器modifier
最后
补充知识:
转账的话是与部署者无关,与交易者有关!
gas是以太坊网络中的一个计量单位,是为了对算力消耗进行量化而设计的指标,也就是说有了gas这个计算单位,我们可以方便的计算出用户完成一笔交易需要支出多少gas费用,矿工完成一个区块的打包确认能收到多少gas报酬。
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
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{…}
原来要返回一个变量,得写个函数返回
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(); // 这里必须加括号,是个访问函数
}
}
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 {}
}
使用is关键字,多个父合约用逗号隔开
contract 合约名 is 父合约1,父合约2,… {}
constract Cat is Animail,Lactation{} // Lactation:哺乳动物
如果两个父合约中有相同的函数,则遵循最远继承原则(继承顺序,Animail最近,Lactation最远,所以是Lactation中的)
在函数执行前检查是否满足前置条件,满足条件才执行函数
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;
}
}
小生凡一,期待你的关注。