2020-02-25 14:57:11 -05:00
|
|
|
_section: Migration: From Ethers v4 @<migration-v4>
|
2020-02-17 17:56:13 -05:00
|
|
|
|
2020-07-07 23:20:32 -04:00
|
|
|
This document only covers the features present in v4 which have changed
|
|
|
|
in some important way in v5.
|
|
|
|
|
2020-10-03 13:30:15 -03:00
|
|
|
It does not cover all the new additional features that have been added and
|
2020-07-07 23:20:32 -04:00
|
|
|
mainly aims to help those updating their older scripts and applications to
|
|
|
|
retain functional parity.
|
|
|
|
|
|
|
|
If you encounter any missing changes, please let me know and I'll update this
|
|
|
|
guide.
|
|
|
|
|
|
|
|
|
2020-02-17 17:56:13 -05:00
|
|
|
_subsection: BigNumber
|
|
|
|
|
|
|
|
_heading: Namespace
|
2020-05-08 03:24:40 -04:00
|
|
|
Since [[BigNumber]] is used quite frequently, it has been moved to
|
2020-02-17 17:56:13 -05:00
|
|
|
the top level of the umbrella package.
|
2020-04-19 02:18:20 -04:00
|
|
|
|
|
|
|
_code: @lang<script>
|
|
|
|
|
|
|
|
// v4
|
|
|
|
ethers.utils.BigNumber
|
|
|
|
ethers.utils.BigNumberish
|
|
|
|
|
|
|
|
// v5
|
|
|
|
ethers.BigNumber
|
|
|
|
ethers.BigNumberish
|
|
|
|
|
2020-02-17 17:56:13 -05:00
|
|
|
|
|
|
|
_heading: Creating Instances
|
2020-07-07 23:20:32 -04:00
|
|
|
|
2020-02-17 17:56:13 -05:00
|
|
|
The ``bigNumberify`` method was always preferred over the constructor
|
2020-05-08 03:24:40 -04:00
|
|
|
since it could short-circuit an object instantiation for [[BigNumber]
|
2020-02-17 17:56:13 -05:00
|
|
|
objects (since they are immutable). This has been moved to a static
|
|
|
|
``from`` class method.
|
2020-04-19 02:18:20 -04:00
|
|
|
|
|
|
|
_code: @lang<script>
|
|
|
|
|
|
|
|
// v4
|
|
|
|
new ethers.utils.BigNumber(someValue)
|
|
|
|
ethers.utils.bigNumberify(someValue);
|
|
|
|
|
|
|
|
// v5
|
|
|
|
// - Constructor is private
|
|
|
|
// - Removed `bigNumberify`
|
|
|
|
ethers.BigNumber.from(someValue)
|
2020-02-17 17:56:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
_subsection: Contracts
|
2020-04-19 02:18:20 -04:00
|
|
|
|
2020-07-07 23:20:32 -04:00
|
|
|
_heading: ENS Name Resolution
|
|
|
|
|
|
|
|
The name of the resolved address has changed. If the address passed into the
|
2020-10-03 13:30:15 -03:00
|
|
|
constructor was an ENS name, the address will be resolved before any calls
|
2020-07-07 23:20:32 -04:00
|
|
|
are made to the contract.
|
|
|
|
|
|
|
|
The name of the property where the resolved address has changed from ``addressPromise``
|
|
|
|
to ``resolvedAddress``.
|
|
|
|
|
|
|
|
_code: Resolved ENS Names @lang<script>
|
|
|
|
|
|
|
|
// v4
|
|
|
|
contract.addressPromise
|
|
|
|
|
|
|
|
// v5
|
|
|
|
contract.resolvedAddress
|
|
|
|
|
|
|
|
|
|
|
|
_heading: Gas Estimation
|
|
|
|
|
|
|
|
The only difference in gas estimation is that the bucket has changed
|
|
|
|
its name from ``estimate`` to ``estimateGas``.
|
|
|
|
|
|
|
|
_code: Gas Estimation @lang<script>
|
|
|
|
|
|
|
|
// v4
|
|
|
|
contract.estimate.transfer(toAddress, amount)
|
|
|
|
|
|
|
|
// v5
|
|
|
|
contract.estimateGas.transfer(toAddress, amount)
|
|
|
|
|
|
|
|
_heading: Functions
|
|
|
|
|
|
|
|
In a contract in ethers, there is a ``functions`` bucket, which exposes
|
|
|
|
all the methods of a contract.
|
2020-04-19 02:18:20 -04:00
|
|
|
|
2020-07-07 23:20:32 -04:00
|
|
|
All these functions are available on the root contract itself as well
|
|
|
|
and historically there was no difference between ``contact.foo`` and
|
|
|
|
``contract.functions.foo``. The original reason for the ``functions`` bucket
|
|
|
|
was to help when there were method names that collided with other buckets,
|
|
|
|
which is rare.
|
|
|
|
|
|
|
|
In v5, the ``functions`` bucket is now intended to help with frameworks and
|
|
|
|
for the new error recovery API, so most users should use the methods on the
|
|
|
|
root contract.
|
|
|
|
|
|
|
|
The main difference will occur when a contract method only returns a single
|
|
|
|
item. The root method will dereference this automatically while the ``functions``
|
|
|
|
bucket will preserve it as an [[Result]].
|
|
|
|
|
|
|
|
If a method returns multiple items, there is no difference.
|
|
|
|
|
|
|
|
This helps when creating a framework, since the result will always be known to
|
|
|
|
have the same number of components as the [[Fragment]] outputs, without having
|
|
|
|
to handle the special case of a single return value.
|
|
|
|
|
|
|
|
_code: Functions Bucket @lang<script>
|
|
|
|
|
|
|
|
const abi = [
|
|
|
|
|
|
|
|
// Returns a single value
|
|
|
|
"function single() view returns (uint8)",
|
|
|
|
|
|
|
|
// Returns two values
|
|
|
|
"function double() view returns (uint8, uint8)",
|
|
|
|
];
|
|
|
|
|
|
|
|
// v4
|
|
|
|
await contract.single()
|
|
|
|
// 123
|
|
|
|
await contract.functions.single()
|
|
|
|
// 123
|
|
|
|
|
|
|
|
|
|
|
|
// v5 (notice the change in the .function variant)
|
|
|
|
await contract.single()
|
|
|
|
// 123
|
|
|
|
await contract.functions.single()
|
|
|
|
// [ 123 ]
|
|
|
|
|
|
|
|
|
|
|
|
// v4
|
|
|
|
await contract.double()
|
|
|
|
// [ 123, 5 ]
|
|
|
|
await contract.functions.double()
|
|
|
|
// [ 123, 5 ]
|
|
|
|
|
|
|
|
|
|
|
|
// v5 (no difference from v4)
|
|
|
|
await contract.double()
|
|
|
|
// [ 123, 5 ]
|
|
|
|
await contract.functions.double()
|
|
|
|
// [ 123, 5 ]
|
2020-04-19 02:18:20 -04:00
|
|
|
|
2020-02-17 17:56:13 -05:00
|
|
|
|
|
|
|
_subsection: Errors
|
|
|
|
|
|
|
|
_heading: Namespace
|
2020-05-08 03:24:40 -04:00
|
|
|
All errors now belong to the [[Logger]] class and the related functions
|
|
|
|
have been moved to [[Logger]] instances, which can include a per-package
|
2020-02-17 17:56:13 -05:00
|
|
|
version string.
|
|
|
|
|
2020-11-22 23:03:50 -05:00
|
|
|
Global error functions have been moved to [[Logger]] class methods.
|
2020-04-19 02:18:20 -04:00
|
|
|
|
|
|
|
_code: @lang<script>
|
|
|
|
|
|
|
|
// v4
|
|
|
|
ethers.errors.UNKNOWN_ERROR
|
|
|
|
ethers.errors.*
|
|
|
|
|
|
|
|
errors.setCensorship(censorship, permanent)
|
|
|
|
errors.setLogLevel(logLevel)
|
|
|
|
|
|
|
|
errors.checkArgumentCount(count, expectedCount, suffix)
|
|
|
|
errors.checkNew(self, kind)
|
|
|
|
errors.checkNormalize()
|
|
|
|
errors.throwError(message, code, params)
|
|
|
|
errors.warn(...)
|
|
|
|
errors.info(...)
|
|
|
|
|
|
|
|
// v5
|
|
|
|
ethers.utils.Logger.errors.UNKNOWN_ERROR
|
|
|
|
ethers.utils.Logger.errors.*
|
|
|
|
|
|
|
|
Logger.setCensorship(censorship, permanent)
|
|
|
|
Logger.setLogLevel(logLevel)
|
|
|
|
|
|
|
|
const logger = new ethers.utils.Logger(version);
|
|
|
|
logger.checkArgumentCount(count, expectedCount, suffix)
|
|
|
|
logger.checkNew(self, kind)
|
|
|
|
logger.checkNormalize()
|
|
|
|
logger.throwError(message, code, params)
|
|
|
|
logger.warn(...)
|
|
|
|
logger.info(...)
|
2020-02-17 17:56:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
_subsection: Interface
|
2020-07-07 23:20:32 -04:00
|
|
|
|
2020-05-08 03:24:40 -04:00
|
|
|
The [[Interface]] object has undergone the most dramatic changes.
|
2020-02-17 17:56:13 -05:00
|
|
|
|
|
|
|
It is no longer a meta-class and now has methods that simplify handling
|
|
|
|
contract interface operations without the need for object inspection and
|
|
|
|
special edge cases.
|
|
|
|
|
|
|
|
_heading: Functions
|
2020-04-19 02:18:20 -04:00
|
|
|
|
|
|
|
_code: @lang<script>
|
|
|
|
|
|
|
|
// v4 (example: "transfer(address to, uint amount)")
|
|
|
|
interface.functions.transfer.encode(to, amount)
|
|
|
|
interface.functions.transfer.decode(callData)
|
|
|
|
|
|
|
|
// v5
|
2020-07-03 01:44:17 -04:00
|
|
|
interface.encodeFunctionData("transfer", [ to, amount ])
|
|
|
|
interface.decodeFunctionResult("transfer", data)
|
2020-04-19 02:18:20 -04:00
|
|
|
|
|
|
|
// Or you can use any compatible signature or Fragment objects.
|
|
|
|
// Notice that signature normalization is performed for you,
|
|
|
|
// e.g. "uint" and "uint256" will be automatically converted
|
2020-07-03 01:44:17 -04:00
|
|
|
interface.encodeFunctionData("transfer(address,uint)", [ to, amount ])
|
|
|
|
interface.decodeFunctionResult("transfer(address to, uint256 amount)", data)
|
2020-04-19 02:18:20 -04:00
|
|
|
|
2020-02-17 17:56:13 -05:00
|
|
|
|
|
|
|
_heading: Events
|
2020-04-19 02:18:20 -04:00
|
|
|
|
|
|
|
_code: @lang<script>
|
|
|
|
|
|
|
|
// v4 (example: Transfer(address indexed, address indexed, uint256)
|
|
|
|
interface.events.Transfer.encodeTopics(values)
|
|
|
|
interface.events.Transfer.decode(data, topics)
|
|
|
|
|
|
|
|
// v5
|
|
|
|
interface.encodeFilterTopics("Transfer", values)
|
2020-07-04 21:29:18 -04:00
|
|
|
interface.decodeEventLog("Transfer", data, topics)
|
2020-04-19 02:18:20 -04:00
|
|
|
|
2020-02-17 17:56:13 -05:00
|
|
|
|
|
|
|
_heading: Inspection
|
|
|
|
Interrogating properties about a function or event can now (mostly) be
|
2020-05-08 03:24:40 -04:00
|
|
|
done directly on the [[Fragment]] object.
|
2020-04-19 02:18:20 -04:00
|
|
|
|
|
|
|
_code:
|
|
|
|
|
|
|
|
// v4
|
|
|
|
interface.functions.transfer.name
|
|
|
|
interface.functions.transfer.inputs
|
|
|
|
interface.functions.transfer.outputs
|
|
|
|
interface.functions.transfer.payable
|
|
|
|
interface.functions.transfer.gas
|
|
|
|
|
|
|
|
// v5
|
|
|
|
const functionFragment = interface.getFunction("transfer")
|
|
|
|
functionFragment.name
|
|
|
|
functionFragment.inputs
|
|
|
|
functionFragment.outputs
|
|
|
|
functionFragment.payable
|
|
|
|
functionFragment.gas
|
|
|
|
|
|
|
|
|
|
|
|
// v4; type is "call" or "transaction"
|
|
|
|
interface.functions.transfer.type
|
|
|
|
|
|
|
|
// v5; constant is true (i.e. "call") or false (i.e. "transaction")
|
|
|
|
functionFragment.constant
|
|
|
|
|
|
|
|
|
|
|
|
// v4
|
|
|
|
interface.events.Transfer.anonymous
|
|
|
|
interface.events.Transfer.inputs
|
|
|
|
interface.events.Transfer.name
|
|
|
|
|
|
|
|
// v5
|
|
|
|
const eventFragment = interface.getEvent("Transfer");
|
|
|
|
eventFragment.anonymous
|
|
|
|
eventFragment.inputs
|
|
|
|
eventFragment.name
|
|
|
|
|
|
|
|
|
|
|
|
// v4
|
|
|
|
const functionSig = interface.functions.transfer.signature
|
|
|
|
const sighash = interface.functions.transfer.sighash
|
|
|
|
|
|
|
|
const eventSig = interface.events.Transfer.signature
|
|
|
|
const topic = interface.events.Transfer.topic
|
|
|
|
|
|
|
|
// v5
|
|
|
|
const functionSig = functionFragment.format()
|
|
|
|
const sighash = interface.getSighash(functionFragment)
|
|
|
|
|
|
|
|
const eventSig = eventFragment.format()
|
|
|
|
const topic = interface.getTopic(eventFragment)
|
2020-02-17 17:56:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
_subsection: Wallet
|
|
|
|
|
|
|
|
_heading: Mnemonic Phrases
|
|
|
|
The **mnemonic** phrase and related properties have been merged into
|
|
|
|
a single ``mnemonic`` object, which also now includes the ``locale``.
|
2020-04-19 02:18:20 -04:00
|
|
|
|
|
|
|
_code: @lang<script>
|
|
|
|
|
|
|
|
// v4
|
|
|
|
wallet.mnemonic
|
|
|
|
wallet.path
|
|
|
|
|
|
|
|
// v5
|
|
|
|
// - Mnemonic phrase and path are a Mnemonic object
|
|
|
|
// - Note: wallet.mnemonic is null if there is no mnemonic
|
|
|
|
wallet.mnemonic.phrase
|
|
|
|
wallet.mnemonic.path
|
|
|
|
|