原文链接 http://www.liankuai.tech/public/technology/80.html
区块链技术教程——智能合约,本文主要讲解了区块链开发技术——以太坊智能合约语言Solidity 函数的种类。
十一、 函数的输入参数与输出参数
Solidity函数的输入参数的数量是可选的,也可以有任意数量的返回参数。
入参(Input Parameter)与变量的定义方式一致,稍微不同的是,不会用到的参数可以省略变量名称。一种可接受两个整型参数的函数如下:
pragma solidity ^0.4.0;contract Simple { function taker(uint _a, uint) { // do something with _a. }}出参(Output Paramets)在returns关键字后定义,语法类似变量的定义方式。返回结果的数量需要与定义的一致。如果给定了参数名,则函数可以不适用return关键字返回,如果没有给定参数名则需要函数体重使用return关键字按照顺序返回。
pragma solidity ^0.4.24;contract Simple { //return sum and product function arithmetics(uint _a, uint _b) returns (uint o_sum, uint o_product) { o_sum = _a + _b; o_product = _a * _b; }}pragma solidity ^0.4.24;contract Simple { //return sum and product function arithmetics(uint _a, uint _b) pure returns (uint , uint ) { return(_a + _b,_a * _b); }}十二、访问函数
编译器为自动为所有的public的状态变量创建访问函数。下面的合约例子中,编译器会生成一个名叫data的无参,返回值是uint的类型的值data。状态变量的初始化可以在定义时完成。
pragma solidity ^0.4.0;contract C{ uint public c = 10;}contract D{ C c = new C(); function getDataUsingAccessor() returns (uint){ return c.c(); }}访问函数有外部(external)可见性。如果通过内部(internal)的方式访问,比如直接访问,你可以直接把它当一个变量进行使用,但如果使用外部(external)的方式来访问,如通过this.,那么它必须通过函数的方式来调用。
pragma solidity ^0.4.0;contract C{ uint public c = 10; function accessInternal() returns (uint){ return c; } function accessExternal() returns (uint){ return this.c(); }}十三、抽象函数
是没有函数体的的函数。如下:
pragma solidity ^0.4.0;contract Feline { function utterance() returns (bytes32);}这样的合约不能通过编译,即使合约内也包含一些正常的函数。但它们可以做为基合约被继承。
pragma solidity ^0.4.0;contract Feline { function utterance() returns (bytes32); function getContractName() returns (string){ return "Feline"; }}contract Cat is Feline { function utterance() returns (bytes32) { return "miaow"; }}如果一个合约从一个抽象合约里继承,但却没实现所有函数,那么它也是一个抽象合约。
十四、数学和加密函数
以下函数式solidity自带的函数
asser(bool condition):
如果条件不满足,抛出异常。
addmod(uint x, uint y, uint k) returns (uint):
计算(x + y) % k。加法支持任意的精度。但不超过(wrap around?)2**256。
mulmod(uint x, uint y, uint k) returns (uint):
计算(x * y) % k。乘法支持任意精度,但不超过(wrap around?)2**256。
keccak256(...) returns (bytes32):
使用以太坊的(Keccak-256)计算HASH值。紧密打包。
sha3(...) returns (bytes32):
等同于keccak256()。紧密打包。
sha256(...) returns (bytes32):
使用SHA-256计算HASH值。紧密打包。
ripemd160(...) returns (bytes20):
使用RIPEMD-160计算HASH值。紧密打包。
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):
通过签名信息恢复非对称加密算法公匙地址。如果出错会返回0,例如:
function verify(bytes32 hash, uint8 v, bytes32 r, bytes32 s) constant returns(bool) { bytes memory prefix = "\\x19Ethereum Signed Message:\n32"; bytes32 prefixedHash = keccak256(prefix, hash); return ecrecover(prefixedHash, v, r, s) == (Your Address);}revert():
取消执行,并回撤状态变化。
需要注意的是参数是“紧密打包(tightly packed)”的,意思是说参数不会补位,就直接连接在一起的。下面来看一个例子:
keccak256("ab", "c")keccak256("abc")//hexkeccak256(0x616263)keccak256(6382179)//asciikeccak256(97, 98, 99)上述例子中,三种表达方式都是一致的。
如果需要补位,需要明确的类型转换,如keccak256("\\x00\\x12")等同于keccak256(uint16(0x12))
需要注意的是字面量会用,尽可能小的空间来存储它们。比如,keccak256(0) == keccak256(uint8(0)),keccak256(0x12345678) == keccak256(uint32(0x12345678))
注意:
在私链(private blockchain)上运行sha256,ripemd160或ecrecover可能会出现Out-Of-Gas报错。因为它们实现了一种预编译的机制,但合约要在收到第一个消息后才会存在。向一个不存在的合约发送消息,非常昂贵,所以才会导致Out-Of-Gas的问题。一种解决办法是每个在你真正使用它们前,先发送1 wei到这些合约上来完成初始化。在官方和测试链上没有这个问题。
-END-

附上链块学院网课学习平台链接:http://wk.liankuai.tech/
助教卫星:lkxy007
添加新手交流群:币种分析、每日早晚盘分析
添加助理微信,一对一亲自指导:YoYo8abc