【solidity三】Solidity中继承、创建合约和外部调用、合约事件event、solidity中元祖的使用、new、delete关键字的使用、solisity创建合约和外部调用

高级语法

全局函数/变量

- 最重要的两个全局变量

  • msg.sender

    每一次和以太坊交互时都会产生一笔交易,这笔交易的执行人就是msg.sender。简而言之:谁调用的,msg.sender就是谁,每笔交易的msg.sender都可以不同。举例:

    1. 部署合约的时候,msg.sender就是部署的账户。
    2. 调用setMessage时,msg.sender就是调用账户。
    3. 调用getMessage时,msg.sender就是调用账户。
  • msg.value

    我们在介绍payable关键字的时候说,如果函数修饰为payable,那么这个函数可以接收转账,这笔钱通过remix的value输入框传递进来。

    在转账操作中,这笔钱是通过我们调用一个函数从而产生一笔交易而转入合约的,换句话说,是这笔交易附带了一笔钱。在合约中,每次转入的value是可以通过msg.value来获取到的。注意,

    1. 单位是wei
    2. 有msg.value,就必须有payable关键字

- 区块和交易的属性

函数含义
blockhash(uint blockNumber)哈希值(byte32)
block.coinbase(address) 当前块矿工的地址。
block.difficulty(uint)当前块的难度
block.gaslimit(uint)当前块的gaslimit
block.number(uint)当前区块的块号
block.timestamp(uint)当前块的时间戳
msg.data(bytes)完整的调用数据(calldata)
gasleft()(uint)当前还剩的gas
msg.sender(address)当前调用发起人的地址
msg.sig(bytes4)调用数据的前四个字节(函数标识符)
msg.value(uint)这个消息所附带的货币量,单位为wei
now (uint)当前块的时间戳等同于block.timestamp
tx.gasprice(uint) 交易的gas价格
tx.origin(address)交易的发送者(完整的调用链)

两个常用单位

- 货币单位

  • 一个字面量的数字,可以使用后缀weifinneyszaboether来在不同面额中转换。
  • 不含任何后缀的默认单位是wei。如1 ether == 1000 finney的结果是true

- 时间单位

  • seconds,minutes,hours,days,weeks,years均可做为后缀,默认是seconds为单位。
  • 1 = 1 seconds
  • 1 minutes = 60 seconds
  • 1 hours = 60 minutes
  • 1 days = 24 hours
  • 1 weeks = 7 days
  • 1 years = 365 days

事件(Event)

相当于打印log,但是需要在调用端才能看到,web3调用时演示

pragma solidity ^0.4.0;

contract ClientReceipt {
    //定义,注意,需要加分号,相当于一句语句,与struct和enum不同。
    //类似于定义函数原型
    event Deposit(
        address indexed _from,
        uint indexed _id,
        uint _value
    );

    function deposit(uint _id) {
        //使用
        Deposit(msg.sender, _id, msg.value);

        //TODO
    }
}

访问函数(Getter Functions)

编译器为自动为所有的public的状态变量创建访问函数。下面的合约例子中,编译器会生成一个名叫data的无参,返回值是uint的类型的值data。状态变量的初始化可以在定义时完成。

pragma solidity ^0.4.24;

contract  Test {

    // 加了public 的转态变量,solidity会自动的生成一个同名个访问函数。
    // 在合约内部使用这个状态变量的时候,直接当初变量使用即可, 不能直接当成方法使用
    // 如果在合约外面向访问这个public变量(data),就需要使用xx.data()形式
    uint256 public data = 200;

    function getData() public view returns(uint256) {
        return data;
    }

    //This代表合约本身,如果在合约内部使用this自己的方法的话,相当于外部调用
    function getData1() public view returns(uint256) {
        //return this.data;   //不能使用.data形式
        return this.data();
    }
}

contract Test1 {
    function getValue() public view returns(uint256) {
        Test t1 = new Test();
        return t1.data();
    }
}

合约

- 创建合约和外部调用

  1. new关键字,返回值是一个address,需要显示转化类型后才能使用
  2. C c1形式,此时c1是空的,需要赋值地址才能使用,否则报错
pragma solidity ^0.4.24;

contract  C1 {

    uint256 public value ;

    constructor(uint256 input) public {
        value = input;
    }

    function getValue() public view returns(uint256) {
        return value;
    }
}

contract C2 {
    C1 public c1;  //0x0000000000000
    C1 public c11;  //0x0000000000000
    C1 public c13;

    function getValue1() public returns(uint256) {

        //创建一个合约,返回地址
        address addr1 = new C1(10);  //balance , transfer方法
        //return addr1.getValue();

        //需要显示的转换为特定类型,才可以正常使用
        c1 = C1(addr1);

        return c1.getValue();
    }


    function getValue2() public returns(uint256) {

        //定义合约的时候,同时完成类型转换
        c11 = new C1(20);
        return c11.getValue();
    }


    function getValue3(address addr) public returns(uint256) {
        //传进来的地址必须是同类型的,如果是不是C1类型的,转换时报错
        c13 = C1(addr);
        return c13.getValue();
    }
}

继承

  1. is关键字, 可以同时继承多个父合约。
  2. 当父合约存在同名函数时,默认为最远继承原则
  3. 可以指定某个父合约,调用它的方法
pragma solidity ^0.4.24;


contract baseA {

    function getData() public pure returns(uint256) {
        return 1;
    }
} 


contract baseB {

    function getData() public pure returns(uint256) {
        return 2;
    }
} 


contract sonA is baseA, baseB {

    function getSonData() public pure returns(uint256){
        return 3;
    }

    function getData3() public pure returns(uint256) {
        return baseA.getData();
    }
}

合约间如何转钱

如何使用一个合约向另一个合约转账。

pragma solidity ^0.4.24;


contract TestA {

    string public message;

    function invest(string _input) payable public {
        message = _input;    
    }

    function getBalanceA() public view returns(uint256) {
        return address(this).balance;
    }
} 



contract TestB {

    TestA public a1;

    function setFeed(address addr)public{
        a1 = TestA(addr);
    }

    function() public payable {

    }
    function Test() payable public{}

    function pay() public {
        //TestB调用TestA的invest方法时,如何转账给TestA?
        //把TestB的钱转给TestA, 并不是调用pay函数人的钱
        a1.invest.value(5 ether).gas(21000)("hangtou!");
    }

    function getBalanceB() public view returns(uint256) {
        return address(this).balance;
    }

}

internal和external

访问函数有外部(external)可见性。如果通过内部(internal)的方式访问,比如直接访问,你可以直接把它当一个变量进行使用,但如果使用外部(external)的方式来访问,如通过this.,那么它必须通过函数的方式来调用。

private ,           intenal ,            external,            public
合约本身可以调用,  合约及子类可以调用, 只能在合约外部调用, 可以被任意的合约调用

元组(tuple)

return(a, b, c)

solidity无法返回自定义的数据结构,所以若想返回一个自定义结构的数据,需要在函数中一次返回多个值,即元组。元组是一个数据集合,类似于字典但是无法修改数据,使用圆括号包括多种数据类型。

  1. 可以包含多个数据
  2. 类型可以不同
  3. 不可以修改
  4. 使用圆括号包裹

- new

创建对象,合约等

- delete

  • delete操作符可以用于任何变量(map除外),将其设置成默认值
  • 如果对动态数组使用delete,则删除所有元素,其长度变为0: uint[ ] array0 ; arry0 = new uint
  • 如果对静态数组使用delete,则重置所有索引的值: uint[10] array1 = [1,2,3,4,5,6];
  • 如果对map类型使用delete,什么都不会发生
  • 但如果对map类型中的一个键使用delete,则会删除与该键相关的值
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yida&yueda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值