299 lines
9.7 KiB
Plaintext
299 lines
9.7 KiB
Plaintext
_section: BigNumber @<BigNumber>
|
|
|
|
Many operations in Ethereum operation on numbers which are
|
|
[outside the range of safe values](BigNumber--notes-safenumbers) to use
|
|
in JavaScript.
|
|
|
|
A **BigNumber** is an object which safely allows mathematical operations
|
|
on numbers of any magnitude.
|
|
|
|
Most operations which need to return a value will return a **BigNumber**
|
|
and parameters which accept values will generally accept them.
|
|
|
|
|
|
_subsection: Types @<BigNumber--types>
|
|
|
|
_heading: BigNumberish @<BigNumberish>
|
|
|
|
Many functions and methods in this library take in values which
|
|
can be non-ambiguously and safely converted to a BigNumber. These
|
|
values can be specified as:
|
|
|
|
_definition: **//string//**
|
|
A [[HexString]] or a decimal string, either of which may
|
|
be negative.
|
|
|
|
_definition: **//BytesLike//**
|
|
A [[BytesLike]] Object, such as an Array or Uint8Array.
|
|
|
|
_definition: **//BigNumber//**
|
|
An existing [[BigNumber]] instance.
|
|
|
|
_definition: **//number//**
|
|
A number that is within the [safe range](link-js-maxsafe) for JavaScript numbers.
|
|
|
|
_definition: **//BigInt//**
|
|
A JavaScript [BigInt](link-js-bigint)
|
|
object, on environments that support BigInt.
|
|
|
|
|
|
_subsection: Creating Instances @<BigNumber--creating>
|
|
|
|
The constructor of BigNumber cannot be called directly. Instead, Use the static ``BigNumber.from``.
|
|
|
|
_property: ethers.BigNumber.from(aBigNumberish) => [[BigNumber]]
|
|
Returns an instance of a **BigNumber** for //aBigNumberish//.
|
|
|
|
_heading: Examples: @<>
|
|
|
|
_code: @lang<javascript>
|
|
|
|
// From a decimal string...
|
|
//_result:
|
|
BigNumber.from("42")
|
|
//_log:
|
|
|
|
// From a HexString...
|
|
//_result:
|
|
BigNumber.from("0x2a")
|
|
//_log:
|
|
|
|
// From a negative HexString...
|
|
//_result:
|
|
BigNumber.from("-0x2a")
|
|
//_log:
|
|
|
|
// From an Array (or Uint8Array)...
|
|
//_result:
|
|
BigNumber.from([ 42 ])
|
|
//_log:
|
|
|
|
// From an existing BigNumber...
|
|
let one1 = constants.One;
|
|
let one2 = BigNumber.from(one1)
|
|
|
|
//_result:
|
|
one2
|
|
//_log:
|
|
|
|
// ...which returns the same instance
|
|
//_result:
|
|
one1 === one2
|
|
//_log:
|
|
|
|
// From a (safe) number...
|
|
//_result:
|
|
BigNumber.from(42)
|
|
//_log:
|
|
|
|
// From a ES2015 BigInt... (only on platforms with BigInt support)
|
|
//_result:
|
|
BigNumber.from(42n)
|
|
//_log:
|
|
|
|
// Numbers outside the safe range fail:
|
|
//_throws:
|
|
BigNumber.from(Number.MAX_SAFE_INTEGER);
|
|
//_log:
|
|
|
|
|
|
_subsection: Methods @<BigNumber--methods>
|
|
|
|
The BigNumber class is immutable, so no operations can change the value
|
|
it represents.
|
|
|
|
|
|
_heading: Math Operations
|
|
|
|
_property: BigNumber.add(otherValue) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of //BigNumber// **+** //otherValue//.
|
|
|
|
_property: BigNumber.sub(otherValue) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of //BigNumber// **-** //otherValue//.
|
|
|
|
_property: BigNumber.mul(otherValue) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of //BigNumber// **×** //otherValue//.
|
|
|
|
_property: BigNumber.div(divisor) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of //BigNumber// **÷** //divisor//.
|
|
|
|
_property: BigNumber.mod(divisor) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of the **remainder** of //BigNumber// ÷ //divisor//.
|
|
|
|
_property: BigNumber.pow(exponent) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of //BigNumber// to the power of //exponent//.
|
|
|
|
_property: BigNumber.abs() => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the absolute value of //BigNumber//.
|
|
|
|
_property: BigNumber.mask(bitcount) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of //BigNumber// with bits beyond
|
|
the //bitcount// least significant bits set to zero.
|
|
|
|
|
|
_heading: Two's Complement
|
|
|
|
[Two's Complement](link-wiki-twoscomplement)
|
|
is an elegant method used to encode and decode fixed-width signed values
|
|
while efficiently preserving mathematical operations.
|
|
Most users will not need to interact with these.
|
|
|
|
_property: BigNumber.fromTwos(bitwidth) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of //BigNumber// converted from twos-complement with //bitwidth//.
|
|
|
|
_property: BigNumber.toTwos(bitwidth) => [[BigNumber]] @SRC<bignumber>
|
|
Returns a BigNumber with the value of //BigNumber// converted to twos-complement with //bitwidth//.
|
|
|
|
|
|
_heading: Comparison and Equivalence
|
|
|
|
_property: BigNumber.eq(otherValue) => boolean @SRC<bignumber>
|
|
Returns true if and only if the value of //BigNumber// is equal to //otherValue//.
|
|
|
|
_property: BigNumber.lt(otherValue) => boolean @SRC<bignumber>
|
|
Returns true if and only if the value of //BigNumber// **<** //otherValue//.
|
|
|
|
_property: BigNumber.lte(otherValue) => boolean @SRC<bignumber>
|
|
Returns true if and only if the value of //BigNumber// **≤** //otherValue//.
|
|
|
|
_property: BigNumber.gt(otherValue) => boolean @SRC<bignumber>
|
|
Returns true if and only if the value of //BigNumber// **>** //otherValue//.
|
|
|
|
_property: BigNumber.gte(otherValue) => boolean @SRC<bignumber>
|
|
Returns true if and only if the value of //BigNumber// **≥** //otherValue//.
|
|
|
|
_property: BigNumber.isZero() => boolean @SRC<bignumber:BigNumber.isZero>
|
|
Returns true if and only if the value of //BigNumber// is zero.
|
|
|
|
|
|
_heading: Conversion
|
|
|
|
_property: BigNumber.toNumber() => number @SRC<bignumber>
|
|
Returns the value of //BigNumber// as a JavaScript value.
|
|
|
|
This will **throw an error**
|
|
if the value is greater than or equal to //Number.MAX_SAFE_INTEGER// or less than or
|
|
equal to //Number.MIN_SAFE_INTEGER//.
|
|
|
|
_property: BigNumber.toString() => string @SRC<bignumber:BigNumber.toString>
|
|
Returns the value of //BigNumber// as a base-10 string.
|
|
|
|
_property: BigNumber.toHexString() => string<[[DataHexString]]> @SRC<bignumber:BigNumber.toHexString>
|
|
Returns the value of //BigNumber// as a base-16, ``0x``-prefixed [[DataHexString]].
|
|
|
|
|
|
_heading: Inspection
|
|
|
|
_property: ethers.BigNumber.isBigNumber(object) => boolean @SRC<bignumber>
|
|
Returns true if and only if the //object// is a BigNumber object.
|
|
|
|
|
|
_heading: Examples
|
|
|
|
_code: @lang<javascript>
|
|
|
|
let a = BigNumber.from(42);
|
|
let b = BigNumber.from("91");
|
|
|
|
//_result:
|
|
a.mul(b);
|
|
//_log:
|
|
|
|
|
|
_subsection: Notes @<BigNumber--notes>
|
|
|
|
This section is a for a couple of questions that come up frequently.
|
|
|
|
|
|
_heading: Why can't I just use numbers? @<BigNumber--notes-safenumbers>
|
|
|
|
The first problem many encounter when dealing with Ethereum is
|
|
the concept of numbers. Most common currencies are broken down
|
|
with very little granularity. For example, there are only 100
|
|
cents in a single dollar. However, there are 10^^18^^ **wei** in a
|
|
single **ether**.
|
|
|
|
JavaScript uses [IEEE 754 double-precision binary floating point](link-wiki-ieee754)
|
|
numbers to represent numeric values. As a result, there are //holes//
|
|
in the integer set after 9,007,199,254,740,991; which is
|
|
problematic for //Ethereum// because that is only around 0.009
|
|
ether (in wei), which means any value over that will begin to
|
|
experience rounding errors.
|
|
|
|
To demonstrate how this may be an issue in your code, consider:
|
|
|
|
_code: @lang<javascript>
|
|
|
|
//_result:
|
|
(Number.MAX_SAFE_INTEGER + 2 - 2) == (Number.MAX_SAFE_INTEGER)
|
|
//_log:
|
|
|
|
_null:
|
|
|
|
To remedy this, all numbers (which can be large) are stored
|
|
and manipulated as [Big Numbers](BigNumber).
|
|
|
|
The functions [parseEther( etherString )](utils-parseEther) and
|
|
[formatEther( wei )](utils-formatEther) can be used to convert
|
|
between string representations, which are displayed to or entered
|
|
by the user and Big Number representations which can have
|
|
mathematical operations handled safely.
|
|
|
|
|
|
_heading: Why not BigNumber.js, BN.js, BigDecimal, etc?
|
|
|
|
Everyone has their own favourite Big Number library, and once someone
|
|
has chosen one, it becomes part of their identity, like their editor,
|
|
vi vs emacs. There are over 100 Big Number libraries on [npm](link-npm-query-bignumber).
|
|
|
|
One of the biggest differences between the Ethers [[BigNumber]] object and
|
|
other libraries is that it is immutable, which is very important when
|
|
dealing with the asynchronous nature of the blockchain.
|
|
|
|
Capturing the value is not safe in async functions, so immutability
|
|
protects us from easy to make mistakes, which is not possible on the
|
|
low-level library's objects which supports myriad in-place operations.
|
|
|
|
Second, the Ethers [[BigNumber]] provides all the functionality required
|
|
internally and should generally be sufficient for most developers while
|
|
not exposing some of the more advanced and rare functionality. So it will
|
|
be easier to swap out the underlying library without impacting consumers.
|
|
|
|
For example, if [[link-npm-bnjs]] was exposed, someone may use the
|
|
greatest-common-denominator functions, which would then be functionality
|
|
the replacing library should also provide to ensure anyone depending on
|
|
that functionality is not broken.
|
|
|
|
|
|
_heading: Why BN.js??
|
|
|
|
The reason why [[link-npm-bnjs]] is used internally as the big
|
|
number is because that is the library used by [[link-npm-elliptic]].
|
|
|
|
Therefore it **must** be included regardless, so we leverage that
|
|
library rather than adding another Big Number library, which would
|
|
mean two different libraries offering the same functionality.
|
|
|
|
This has saved about 85kb (80% of this library size) of library size
|
|
over other libraries which include separate Big Number libraries for
|
|
various purposes.
|
|
|
|
|
|
_heading: Allow us to set a global Big Number library?
|
|
|
|
Another comment that comes up frequently is the desire to specify a
|
|
global user-defined Big Number library, which all functions would
|
|
return.
|
|
|
|
This becomes problematic since your code may live along side other
|
|
libraries or code that use Ethers. In fact, even Ethers uses a lot
|
|
of the public functions internally.
|
|
|
|
If you, for example, used a library that used ``a.plus(b)`` instead
|
|
of ``a.add(b)``, this would break Ethers when it tries to compute
|
|
fees internally, and other libraries likely have similar logic.
|
|
|
|
But, the [[BigNumber]] prototype is exposed, so you can always add a
|
|
``toMyCustomBigNumber()`` method to all [[BigNumber]]'s globally
|
|
which is safe.
|