Solidity-单位和全局变量(一)

发布于:2022-11-02 ⋅ 阅读:(629) ⋅ 点赞:(0)

前言


写本文的目的是记录自己对于区块链技术的学习,方便日后查漏补缺,solidity是一门智能合约语言,是静态类型语言,支持继承等特性。solidity中不存在 undefine和null的概念,每个新声明的变量都会根据其类型赋予默认值。


一、单位

单位之间的换算就是在数字后边加上weigweiether来实现的,如果后面没有单位,缺省为 wei。

  • 1 wei == 1
  • 1 gwei == 1e9 wei
  • 1 ether == 1e9 gwei

二、时间单位

 秒是缺省时间单位,在时间单位之间,数字后面带有secondsminuteshoursdays 和weeks的可以进行换算,基本换算关系如下:

  • 1 == 1 seconds
  • 1 minutes == 60 seconds
  • 1 hours == 60 minutes
  • 1 days == 24 hours
  • 1 weeks == 7 days

years已经在0.5.0版本去除了,因为闰年的原因。

三、区块和交易属性

  • blockhash(uint blockNumber) returns (bytes32):指定区块的区块哈希 —— 仅可用于最新的 256 个区块且不包括当前区块,否则返回 0 。
  • block.basefee (uint): 当前区块的基础费用
  • block.chainid (uint): 当前链 id
  • block.coinbase ( address ): 挖出当前区块的矿工地址
  • block.difficulty ( uint ): 当前区块难度
  • block.gaslimit ( uint ): 当前区块 gas 限额
  • block.number ( uint ): 当前区块号
  • block.timestamp ( uint): 自 unix epoch 起始当前区块以秒计的时间戳
  • gasleft() returns (uint256) :剩余的 gas
  • msg.data ( bytes ): 完整的 calldata
  • msg.sender ( address ): 消息发送者(当前调用)
  • msg.sig ( bytes4 ): calldata 的前 4 字节(也就是函数标识符)
  • msg.value ( uint ): 随消息发送的 wei 的数量
  • tx.gasprice (uint): 交易的 gas 价格
  • tx.origin ( address ): 交易发起者(完全的调用链)

对于每一个外部函数调用,包括 msg.sender 和 msg.value 在内所有 msg 成员的值都会变化。这里包括对库函数的调用。

基于可扩展因素,区块哈希不是对所有区块都有效。你仅仅可以访问最近 256 个区块的哈希,其余的哈希均为零。

 blockhash 函数之前是使用 block.blockhash, block.blockhash 在 0.4.22 开始不推荐使用,在 0.5.0 已经移除了。

gasleft 函数之前是使用 msg.gasmsg.gas 在 0.4.21 开始不推荐使用,在 0.5.0 已经移除了。

在 0.7.0, now ( block.timestamp 的别名) 被移除了。

 四、错误处理

 

  • assert(bool condition)如果不满足条件,则会导致Panic 错误,则撤销状态更改 - 用于检查内部错误。
  • require(bool condition)如果条件不满足则撤销状态更改 - 用于检查由输入或者外部组件引起的错误。
  • require(bool condition, string memory message如果条件不满足则撤销状态更改 - 用于检查由输入或者外部组件引起的错误,可以同时提供一个错误消息。
  • revert()终止运行并撤销状态更改。
  • revert(string memory reason)终止运行并撤销状态更改,可以同时提供一个解释性的字符串。

五、数学和密码学函数 

 addmod(uint x, uint y, uint k) returns (uint)

 计算 (x+y)%k,加法会在任意精度下执行,并且加法的结果即使超过 2**256 也不会被截取。从 0.5.0 版本的编译器开始会加入对 k!=0 的校验(assert)。

 mulmod(uint x, uint y, uint k) returns (uint)

 计算(x*y)%k,乘法会在任意精度下执行,并且乘法的结果即使超过 2**256 也不会被截取。从 0.5.0 版本的编译器开始会加入对 k!=0 的校验(assert)。

 keccak256((bytes memory) returns (bytes32)

 计算 Keccak-256 哈希,之前keccak256的别名函数sha3,在0.5.0中已经移除。

 sha256(bytes memory) returns (bytes32)

 计算参数的 SHA-256 哈希。

 ripemd160(bytes memory) returns (bytes20)

 计算参数的 RIPEMD-160 哈希。

 ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)

利用椭圆曲线签名恢复与公钥相关的地址,错误返回零值。

函数参数对应于 ECDSA签名的值:

  • r = 签名的前 32 字节
  • s = 签名的第2个32 字节
  • v = 签名的最后一个字节

ecrecover 返回一个address, 而不是address payable。

使用ecrecover,需要了解,在不需要知道相应的私钥下,签名也可以转换为另一个有效签名(可能是另外一个数据的签名)。在 Homestead 硬分叉,这个问题对于 _transaction_ 签名已经解决了(查阅 EIP-2)。 不过 ecrecover 没有更改。

除非需要签名是唯一的,否则这通常不是问题,或者是用它们来识别物品。 OpenZeppelin有一个 ECDSA助手库 ,可以将其用作 ecrecover 的”包装“,而不会出现此问题。

 六、地址成员

<address>.balance (uint256)  以 Wei 为单位的

<address>.code (bytes memory)

<address>.codehash (bytes32)

<address payable>.transfer(uint256 amount)  发送数量为 amount 的 Wei

<address payable>.send(uint256 amount) returns (bool) 发送数量为 amount 的 Wei,失败时返回 false

<address>.call(bytes memory) returns (bool, bytes memory)

<address>.delegatecall(bytes memory) returns (bool, bytes memory)

<address>.staticcall(bytes memory) returns (bool, bytes memory)

三个调用成员,都可设置gas,但是只有call可以带value

在执行另一个合约函数时,应该尽可能避免使用 .call() ,因为它绕过了类型检查,函数存在检查和参数打包。

 由于 EVM 会把对一个不存在的合约的调用作为是成功的。 Solidity 会在执行外部调用时使用 extcodesize 操作码进行额外检查。 这确保了即将被调用的合约要么实际存在(它包含代码)或者触发一个异常。

对地址而不是合约实例进行操作的低级调用call(),delegatecall()staticcall()send()transfer()时,不会进行extcodesize检查,在GAS方面更便宜,但也更不安全。

在版本0.5.0之前,Solidity允许通过合约实例来访问地址的成员,例如this.balance,不过现在禁止这样做,必须显式转换为地址后访问,如:address(this).balance

在 0.5.0 版本以前,call,delegatecallandstaticcall 仅仅返回成功状态,没有返回值。 

七、合约相关

  • this 指当前合约
  • selfdestruct(address payable recipient)   selfdestruct 具有从EVM继承的一些特性:接收合约的 receive 函数 不会执行。   - 合约仅在交易结束时才真正被销毁,并且 revert 可能会“撤消”销毁。

在 0.5.0 之前, 还有一个 suicide ,它和 selfdestruct 语义是一样的。 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到