Skip to content

ethers.js V6 带来了什么

Table of contents

Open Table of contents

Big Numbers

v6 中最大的变化之一是 BigNumber 类已被现代 JavaScript 环境提供的内置 ES2020 BigInt 取代。

可以在 MDN 这里查看 JavaScript ES2020 BigInt 的具体用法。

初始化 BigNumber

// BigNumber in v5
value = BigNumber.from("1000");

// Using BigInt in v6 (using literal notation).
// Notice the suffix n
value = 1000n;

// Using the BigInt function for strings
value = BigInt("1000");

简单计算

// Adding two values in v5
sum = value1.add(value2);

// Using BigInt in v6; keep in mind, both values
// must be a BigInt
sum = value1 + value2;

数字比较

// Checking equality in v5
isEqual = value1.eq(value2);

// Using BigInt in v6
isEqaul = value1 == value2;

Contracts

Contract 就是一个 ES6 的 Proxy, 这意味着它可以在运行时解析方法名称。

未知命名的函数

abi = ["function foo(address bar)", "function foo(uint160 bar)"];
contract = new Contract(address, abi, provider);

// In v5 it was necessary to specify the fully-qualified normalized
// signature to access the desired method. For example:
contract["foo(address)"](addr);

// These would fail, since there signature is not normalized:
contract["foo(address )"](addr);
contract["foo(address addr)"](addr);

// This would fail, since the method is ambiguous:
contract.foo(addr);
abi = ["function foo(address bar)", "function foo(uint160 bar)"];
contract = new Contract(address, abi, provider);

// Any of these work fine:
contract["foo(address)"](addr);
contract["foo(address )"](addr);
contract["foo(address addr)"](addr);

// This still fails, since there is no way to know which
// method was intended
contract.foo(addr);

// However, the Typed API makes things a bit easier, since it
// allows providing typing information to the Contract:
contract.foo(Typed.address(addr));

其他方法

// The default action chooses send or call base on method
// type (pure, view, constant, non-payable or payable)
contract.foo(addr);

// This would perform the default action, but return a Result
// object, instead of destructing the value
contract.functions.foo(addr);

// Forces using call
contract.staticCall.foo(addr);

// Estimate the gas
contract.estimateGas.foo(addr);

// Populate a transaction
contract.populateTransaction.foo(addr);
// Still behaves the same
contract.foo(addr);

// Perform a call, returning a Result object directly
contract.foo.staticCallResult(addr);

// Forces using call (even for payable and non-payable)
contract.foo.staticCall(addr);

// Forces sending a transaction (even for pure and view)
contract.foo.send(addr);

// Estimate the gas
contract.foo.estimateGas(addr);

// Populate a transaction
contract.foo.populateTransaction(addr);

Importing

v5 版本 ethers.js 使用 sub-package 方式管理 和 monorepo 比较相似

在 v6 版本所有 import 都可以在根 package 里面导入

v5 导入

// Many things (but not all) we available on the root package
import { ethers } from "ethers";

// But some packages were grouped behind an additional property
import { providers } from "ethers";
const { InfuraProvider } = providers;

// For granular control, importing from the sub-package
// was necessary
import { InfuraProvider } from "@ethersproject/providers";

v6 导入

// Many things (but not all) we available on the root package
import { ethers } from "ethers";

// But some packages were grouped behind an additional property
import { providers } from "ethers";
const { InfuraProvider } = providers;

// For granular control, importing from the sub-package
// was necessary
import { InfuraProvider } from "@ethersproject/providers";

Providers

之前所有 ethers.providers.* 转变成 ethers.*

// v5
provider = new ethers.providers.Web3Provider(window.ethereum);

// v6:
provider = new ethers.BrowserProvider(window.ethereum);

Signatures

v6 版本的 Signature 将是一个类,可以方便地进行解析和序列化操作。

// v5
splitSig = splitSignature(sigBytes);
sigBytes = joinSignature(splitSig);

// v6
splitSig = ethers.Signature.from(sigBytes);
sigBytes = ethers.Signature.from(splitSig).serialized;

Transactions

v5 版本中的 transaction 相关方法现在被封装到了 Transaction 类中,该类可以处理任何支持的交易格式以进一步进行处理。

// v5
tx = parseTransaction(txBytes);
txBytes = serializeTransaction(tx);
txBytes = serializeTransaction(tx, sig);

// v6
tx = Transaction.from(txBytes);

// v6 (the tx can optionally include the signature)
txBytes = Transaction.from(tx).serialized;

Utilities

Bytes32 string helpers

// In v5:
bytes32 = ethers.utils.formatBytes32String(text);
text = ethers.utils.parseBytes32String(bytes32);

// In v6:
bytes32 = ethers.encodeBytes32String(text);
text = ethers.decodeBytes32String(bytes32);

constants

// v5:
ethers.constants.AddressZero;
ethers.constants.HashZero;

// v6:
ethers.ZeroAddress;
ethers.ZeroHash;

data manipulation

// v5
slice = ethers.utils.hexDataSlice(value, start, end);
padded = ethers.utils.hexZeroPad(value, length);

// v5; converting numbers to hexstrings
hex = hexlify(35);

// v6
slice = ethers.dataSlice(value, start, end);
padded = ethers.zeroPadValue(value, length);

// v6; converting numbers to hexstrings
hex = toBeHex(35);

defaultAbiCoder

// In v5, it is a property of AbiCoder
coder = AbiCoder.defaultAbiCoder;

// In v6, it is a static function on AbiCoder, which uses
// a singleton pattern; the first time it is called, the
// AbiCoder is created and on subsequent calls that initial
// instance is returned.
coder = AbiCoder.defaultAbiCoder();

hex conversion

// v5
hex = ethers.utils.hexValue(value);
array = ethers.utils.arrayify(value);

// v6
hex = ethers.toQuantity(value);
array = ethers.getBytes(value);

solidity non-standard packed

// v5
ethers.utils.solidityPack(types, values);

// v6
ethers.solidityPacked(types, values);

property manipulation

// v5
ethers.utils.defineReadOnly(obj, "name", value);

// v6
ethers.defineProperties(obj, { name: value });

Share this post on:

Previous Post
Solidity 提款模式(withdrawal) 是什么?
Next Post
OpenZeppelin ERC20 源码解读