编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Solidity中继承、创建合约和外部调用、合约事件event

wxchong 2024-09-25 23:21:29 开源技术 10 ℃ 0 评论

solidity高级语法

全局函数/变量

- 最重要的两个全局变量

  • msg.sender
  • 每一次和以太坊交互时都会产生一笔交易,这笔交易的执行人就是msg.sender。简而言之:谁调用的,msg.sender就是谁,每笔交易的msg.sender都可以不同。举例:
  • 部署合约的时候,msg.sender就是部署的账户。
  • 调用setMessage时,msg.sender就是调用账户。
  • 调用getMessage时,msg.sender就是调用账户。
  • msg.value
  • 我们在介绍payable关键字的时候说,如果函数修饰为payable,那么这个函数可以接收转账,这笔钱通过remix的value输入框传递进来。
  • 在转账操作中,这笔钱是通过我们调用一个函数从而产生一笔交易而转入合约的,换句话说,是这笔交易附带了一笔钱。在合约中,每次转入的value是可以通过msg.value来获取到的。注意,
  • 单位是wei
  • 有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)交易的发送者(完整的调用链)

两个常用单位

- 货币单位

  • 一个字面量的数字,可以使用后缀wei,finney,szabo或ether来在不同面额中转换。
  • 不含任何后缀的默认单位是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,则会删除与该键相关的值



Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表