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关键字

- 区块和交易的属性

函数

两个常用单位

- 货币单位

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

- 时间单位

seconds,minutes,hours,days,weeks,years均可做为后缀,默认是seconds为单位。1 = 1 seconds1 minutes = 60 seconds1 hours = 60 minutes1 days = 24 hours1 weeks = 7 days1 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(); } }

合约

- 创建合约和外部调用

new关键字,返回值是一个address,需要显示转化类型后才能使用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(); } }

继承

is关键字, 可以同时继承多个父合约。当父合约存在同名函数时,==默认为最远继承原则==可以指定某个父合约,调用它的方法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无法返回自定义的数据结构,所以若想返回一个自定义结构的数据,需要在函数中一次返回多个值,即元组。元组是一个数据集合,类似于字典但是无法修改数据,使用圆括号包括多种数据类型。

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

- 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,则会删除与该键相关的值