Loading...

智能合约语言 Solidity 教程 – Solidity API

Smart Contracts语言 Solidity 教程 – Solidity API

电报联系方式

Solidity API 主要表现为Solidity 内置的特殊的变量及函数,他们存在于全局命名空间里,主要分为以下几类:

  1. 有关区块和Trading的属性
  2. ABI编码函数
  3. 有关错误处理
  4. 有关数学及加密功能
  5. 地址相关
  6. 合约相关

区块和交易的属性

  • blockhash(uint blockNumber) returns (bytes32):返回给定区块号的哈希值,只支持最近256个区块,且不包含当前区块。
  • block.coinbase (address): 当前块矿工的地址。
  • block.difficulty (uint):当前块的难度。
  • block.gaslimit (uint):当前块的gaslimit。
  • block.number (uint):当前区块的块号。
  • block.timestamp (uint): 当前块的Unix时间戳(从1970/1/1 00:00:00 UTC开始所经过的秒数)
  • gasleft() (uint256): 获取剩余gas。
  • msg.data (bytes): 完整的调用数据(calldata)。
  • msg.gas (uint): 当前还剩的gas(弃用)。
  • msg.sender (address): 当前调用发起人的地址。
  • msg.sig (bytes4):调用数据(calldata)的前四个字节(例如为:函数标识符)。
  • msg.value (uint): 这个消息所附带的以太币,单位为wei。
  • now (uint): 当前块的时间戳(block.timestamp的别名)
  • tx.gasprice (uint) : 交易的gas价格。
  • tx.origin (address): 交易的发送者(全调用链)

在每次外部函数调用或库函数调用中,msg.sender.msg.valueetc.msg对象的成员值都可以根据调用的上下文而发生变化,因为msg是一个全局变量,它的值取决于当前的函数调用。

Usingblock.timestamp, ,now.block.blockhash来生成随机数应该谨慎,因为这些值在一定程度上受到矿工的影响。例如,在赌博合约中,不诚实的矿工可能会尝试选择对他们有利的哈希值。

此外,对于同一条区块链上的连续区块,当前区块的时间戳(timestamp)通常会大于前一个区块的时间戳。

出于可扩展性的考虑,你只能查询最近的256个区块的这些值,而对于其他区块,这些查询将返回0。这是因为区块链的设计限制了对历史区块的某些操作。

ABI编码函数

Solidity 提供了一下函数,用来直接得到ABI编码信息,这些函数有:
* abi.encode(…) returns (bytes):计算参数的ABI编码。
* abi.encodePacked(…) returns (bytes):计算参数的紧密打包编码
* abi. encodeWithSelector(bytes4 selector, …) returns (bytes): 计算函数选择器和参数的ABI编码
* abi.encodeWithSignature(string signature, …) returns (bytes): 等价于* abi.encodeWithSelector(bytes4(keccak256(signature), …)

通过ABI编码函数可以在不用调用函数的情况下,获得ABI编码值,下面通过一段代码来看看这些方式的使用:

pragma solidity ^0.4.24;

contract testABI {
function abiEncode() public constant returns (bytes) {
abi.encode(1); // 计算 1 的ABI编码
return abi.encodeWithSignature(“set(uint256)”, 1); //计算函数set(uint256) 及参数1 的ABI 编码
}
}

错误处理

  1. assert(bool condition):用于判断内部错误,如果条件不满足,会抛出异常。这是一种在代码中明确指示发生严重问题的方式,通常用于检查合约内部的逻辑错误。
  2. require(bool condition):用于判断输入或外部组件错误。如果条件不满足,会抛出异常。这通常用于检查函数输入参数或与外部合约的交互是否有效。
  3. require(bool condition, string message):与上述相同,但提供了一个自定义的错误信息,以便更好地理解问题的性质。
  4. revert():用于终止执行并还原改变的状态。它通常用于回滚不合法操作,不消耗所有的剩余Gas,这是一种优化的方式。
  5. revert(string reason):与上述相同,但提供了一个自定义错误信息,有助于更清晰地传达发生的问题。

以前的错误处理方式中使用throw,但这种方式会消耗掉所有剩余的Gas,并且已经被弃用。新的方式提供了更好的可读性和更精细的错误处理机制。

数学及加密功能

以下是一些以太坊智能合约中常见的数学和加密函数的功能和作用:

  1. addmod(uint x, uint y, uint k) returns (uint):计算 (x + y) % k,这个操作支持任意精度,而且不会在达到 2^256 时溢出。从 Solidity 0.5.0 版本开始,必须断言 k != 0.
  2. mulmod(uint x, uint y, uint k) returns (uint):计算 (x * y) % k,这个操作也支持任意精度,不会在达到 2^256 时溢出。同样,从 Solidity 0.5.0 版本开始,必须断言 k != 0.
  3. keccak256(...):使用以太坊的 Keccak-256 算法计算哈希值,通常用于紧密打包参数并生成唯一标识。它返回一个 256 位的字节数组,通常存储在 bytes32 类型的变量中。
  4. sha256(...):使用 SHA-256 算法计算哈希值,同样用于紧密打包参数,通常返回一个 256 位的字节数组。
  5. sha3(...): Thesha3keccak256 的别名,用于计算哈希值。
  6. ripemd160(...):使用 RIPEMD-160 算法计算哈希值,通常用于紧密打包参数,返回一个 160 位的字节数组。
  7. ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):通过椭圆曲线签名来恢复与公钥关联的地址,或者在签名错误时返回零地址。这个函数通常用于验证数据的签名,如果返回的地址与签名者的公钥地址匹配,则说明数据是正确签名的。

这些函数在以太坊智能合约中用于执行数学运算和数据加密,以保证合约的正确性和安全性。

ecrecover函数需要四个参数,需要被签名数据的哈希结果值,r,s,v分别来自签名结果串。
r = signature[0:64]
s = signature[64:128]
v = signature[128:130]
其中v取出来的值或者是00或01。要使用时,我们先要将其转为整型,再加上27,所以我们将得到27或28。在调用函数时v将填入27或28。

用javascript表达如下:

var msg = ‘0x8CbaC5e4d803bE2A3A5cd3DbE7174504c6DD0c1C’

var hash = web3.sha3(msg)
var sig = web3.eth.sign(address, h).slice(2)
var r = `0x${sig.slice(0, 64)}`
var s = `0x${sig.slice(64, 128)}`
var v = web3.toDecimal(sig.slice(128, 130)) + 27

紧密打包参数(tightly packed)意思是说参数不会补位,是直接连接在一起的,下面几个是相等的。

keccak256(“ab”, “c”)
keccak256(“abc”)

keccak256(0x616263) // hex
keccak256(6382179)
keccak256(97, 98, 99) //ascii

在以太坊私链(private blockchain)上运行 sha256, ,ripemd160 or ecrecover 这些函数可能会导致 Out-Of-Gas 错误。这是因为私链实现了一种预编译合约机制,这些合约需要在收到第一个消息后才真正存在(尽管它们的合约代码已经硬编码到以太坊客户端中)。因此,尝试向一个尚未初始化的合约发送消息会导致 Out-Of-Gas 问题。

为了解决这个问题,一种解决办法是在实际使用这些函数之前,向这些合约发送一小笔 ETH(例如 1 wei)以完成初始化。在官方以太坊主网和测试链上,通常不会出现这个问题,因为这些合约在启动时已经初始化。但在私链中,这个初始化步骤可能是必需的。

地址相关

  • .balance (uint256):

Address的余额,以wei为单位。

  • .transfer(uint256 amount):

发送给定数量的ether到某个地址,以wei为单位。失败时抛出异常。

  • .send(uint256 amount) returns (bool):

发送给定数量的ether到某个地址,以wei为单位, 失败时返回false。

  • .call(…) returns (bool):

发起底层的call调用。失败时返回false。

  • .callcode(…) returns (bool):

发起底层的callcode调用,失败时返回false。
不鼓励使用,未来可能会移除。

  • .delegatecall(…) returns (bool):

发起底层的delegatecall调用,失败时返回false

合约相关

  • this(当前合约的类型):
    表示当前合约,可以显式的转换为Address
  • selfdestruct(address recipient):
    销毁当前合约,并把它所有资金发送到给定的地址。
  • suicide(address recipient):
    selfdestruct的别名

开发联系:DEXDAO

 

© 版权声明

Related posts

No comments

No comments...