Win10下开发部署Dapp(4):solidity快速入门(基础篇)

基础篇

Solidity是一门静态类型的脚本语言,我们可以对照C++的语法进行快速记忆。
###1.基本保留字与基本类型

  • contract:类似于class,定义一个合约,具有构造函数,仅在创建合约时被调用。
  • function:定义一个函数。
  • event:定义一个事件,外部Dapp可以监控这些事件,以获知合约内的变化。
  • var:声明变量,类似于C++11的auto,可以在初始化时进行自动类型推导,之后不能更改类型。
  • bool: 布尔类型,有true跟false两种值。
  • uint8、uint16、。。。uint256:无符号整型,uint是uint256的别名。
  • nint8、int16、。。。int256:有符号整形,int是int256的别名。
  • ufixedMxN:无符号定点小数,M表示整个类型占用的bit数,N表示小数位数。ufixed64x7:7位小数,剩下的是整数部分
  • fixedMxN:定点小数。
  • address:地址类型,表示账户地址或者合约地址。20Byte。
    addr.balance:返回uint256类型的值,表示addr账户的余额(Wei)。
    addr.send(uint256 N):转给addr地址N Wei数量的以太币,失败是返回false。
    addr.transfer(uint256 N):包装了send方法,失败时直接抛出异常,会导致整个交易回退。
    addr.call、addr.callcode、addr.delegatecall:调用addr合约的指定的方法,区别稍后详述。

###2.基本操作符

  • 逻辑操作符:!(逻辑非)、&&(逻辑与)、||(逻辑或)。跟C++完全一致,并且&&与||同样存在短路求值。
  • 比较操作符:<、<=、>、>=、==、!=,跟C++完全一致。
  • 算术操作符:+(正号)、-(负号)、 +、-、*、/、%(取余)、<<(左移)、>>(右移)、**(幂)。除了幂,其余的都跟C++一致。
  • 位操作符:&(与)、|(或)、~(非)、^(异或)。

###3.数组、字符串、结构体、枚举类型、mapping

  • 数组
  • 定长数组:编译期长度就固定下来的数组是定长数组,这样定义一个定常数组:T[k](例如 uint8[ 5 ] arr)。bytes1、bytes2, bytes3, …, bytes32,这些也是定长数组。bytes1可以简写成byte。定长数组是值类型(value-type),可以进行比较操作、位操作、索引操作。
  • 动态数组:编译期长度不固定,类似于C++中的vector,这样定义一个动态数组:T[] (例如 int256[] arr)。
    string是特殊的动态数组。普通的定长数组、动态数组都可以进行取长度操作:arr.length,以及下标索引操作,但是string暂时不支持这两种操作。bytes也是动态数组,相当于byte[],但是比byte[]要更、廉价一些,应该尽量使用bytes。另外,动态数组、bytes还可以调用push方法,在数组末尾添加数据,返回最新的长度。
  • 字符串
    string本质上是经过UTF8编码的byte数组。当前版本的solidity对string的实现十分不完整,无法支持串联、比较、下标索引等操作,甚至连取长度都不支持。当前的string仅可以用来做mapping的key。
  • 结构体
    跟C++很像,这样定义一个结构体:
struct MyStruct{
bool flag;
string name;

}
MyStruct a;

	结构体、数组里未被初始化的元素,都是0。
  • 枚举
  • mapping
    solidity里使用频率比较高的类型。mapping (address => uint256) balanceOf; 定义了一个map,使用地址做索引,值位uint256.

###4.全局可用的单位、函数、对象

  • 以太币单位
    1 Ether = 1000 Finny
    1 Finny = 1000 Szabo
    1 Szabo = 1000 Gwei
    1 Gwei = 1000 Mwei
    1 Mwei = 1000 Kwei
    1 Kwei = 1000 wei
    1 Ether = 10^18 wei
  • 时间单位
    1 == 1 seconds
    1 minutes == 60 seconds
    1 hours == 60 minutes
    1 days == 24 hours
    1 weeks == 7 days
    1 years == 365 days
  • block对象
    block.blockhash(uint blockNumber) returns (bytes32):返回指定高度的块的hash值,仅限最近256块。
    block.coinbase (address):当前块的矿工
    block.difficulty (uint):当前块的难度
    block.gaslimit (uint):当前块的gaslimit
    block.number (uint):当前块高度
    block.timestamp (uint): 当前块时间戳
  • msg对象
    msg.data (bytes):当前调用完整的原始数据
    msg.gas (uint): 剩余的gas,0.4.21版本之后弃用,替换为gasleft。
    msg.sender (address): 当前调用的发起者。
    msg.sig (bytes4):调用数据的头四字节
    msg.value (uint):当前消息携带的以太币,单位wei。
  • tx对象
    tx.gasprice (uint):当前交易的gas price
    tx.origin (address): 当前交易的发起者。
  • 数学函数、hash函数
    addmod(uint x, uint y, uint k) returns (uint):
    mulmod(uint x, uint y, uint k) returns (uint):
    keccak256(…) returns (bytes32):
    sha256(…) returns (bytes32):
    sha3(…) returns (bytes32):
    ripemd160(…) returns (bytes20):
    ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):
  • 异常处理函数
    assert(bool condition):
    require(bool condition):
    revert():
  • 其他
    gasleft() returns (uint256)
    now (uint):
    this
    suicide

###5.contract(合约)
contract类似于class,他有:

  • 构造函数。跟contract名称相同的function即为构造函数,在合约创建时被调用,可以有参数,无返回值。
  • 自杀函数。selfdestruct(address)销毁合约,并把合约账户里的ether转移到指定的地址,花费比调用transfer小。suicide是selfdestruct的别名。
  • this。在合约内,this可以转化成address。在合约内部调用自己的external函数也需要用到this。
  • 成员变量。
  • 成员函数。
  • 继承、被继承。一个合约可以继承其他合约。
    ###6.可见性:external、public、internal、private
    合约内的成员变量、成员函数需要使用可见性来修饰,不修饰默认为public(跟C++刚好相反)。
  • external:只能用来修饰成员函数,这样的函数只能被外部合约调用,合约内部想要调用该函数,需要使用this.func();
  • public:修饰变量,则编译器会自动生成一个同名的getter。修饰函数,则外部可以调用该函数。
  • internal:类似于protect,可被合约内部以及子类合约访问。
  • private:私有的,仅合约内部可以访问,子类不可访问。
    ###7.函数及其修饰词
    函数可以有多个返回值:
    直接通过一个稍微复杂点的例子来看下solidity的函数是啥样子的。
uint16 uCount; //合约内的成员变量

function add(uint8 a, uint8 b) public pure returns(uint8){
	return a + b; //先忽略溢出。
}

function GetCount() public view returns(uint16){
	return uCount;
}

function setCount(uint16 count) public {
	uCount = count;
}

modifier validAddress(address addr){
	assert(addr != address(0));
	_;
}
modifier validAmount(uint256 amount){
	reqire(amount > 0);
	_;
}

function myTransferFunc(address to, uint256 amount) public validAddress(to) validAmount(amount){
	//无需再检查参数的合法性,如果不合法,会在modifier中抛出异常,进不到函数体中。
	//........
	//........
}

function deposit(uint256 amount) public payable returns(bool, string){ 
	//........
	return (true, "successfull");
}

function () public payable{
	//.......
}

  从上往下依次看,add方法很简单,实现了两个数相加,但是pure是啥意思?GetCount方法的view又是啥意思?SetCount为啥没有这两个东西?pure:不改变合约状态,也不读取合约状态的函数,开发者应当主动使用pure修饰;读取合约状态但是不修改合约状态的函数,使用view修饰;SetCount改变了合约状态,不能被这两个中的任何一个修饰。(老版本的solidity没有view与pure,只有一个constant,凡是不改变状态的函数需要被constant修饰,后来细化成两部分view + pure)。
  接下来的modifier,业界普遍翻译成函数修改器,我觉得应该叫 函数卫词,它就像是一个卫语句,在函数运行之前过滤参数的合法性。不合法直接抛出异常,退出函数体,整个交易都不会被执行。
  再往下,一个新关键词:payable。被这个修饰的函数,才能够被转账,否则只能是普通调用。
  最后,一个没有名字的函数,叫回退函数(fallback function)。当且仅当一个合约的回退函数被实现了且被payable修饰了,才能向这个合约地址直接转账。
###8.事件
  事件是另一个新东西,可以让外部dapp监控合约内的变化。这里先简单介绍下事件的定义以及触发,事件的监听后面补上。

event OnTrasnsfer(address from, address to, uint value);
function myTransferFunc(address to, uint256 amount) public validAddress(to) validAmount(amount){
	//转账
	。。。
	//新版本的solidity触发事件需要使用emit关键字,之前的版本不用,但是看起来像是个函数调用。
	emit OnTrasnsfer(address(this), to, amount);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章