bn.ts 1.3 KB
Newer Older
1 2
import { BigNumber } from '@ethersproject/bignumber'
import { getAddress } from '@ethersproject/address'
3

4
import { remove0x, add0x } from './hex-strings'
5 6 7 8 9 10 11

/**
 * Converts an ethers BigNumber into an equivalent Ethereum address representation.
 *
 * @param bn BigNumber to convert to an address.
 * @return BigNumber converted to an address, represented as a hex string.
 */
12
export const bnToAddress = (bn: BigNumber | number): string => {
13
  // Coerce numbers into a BigNumber.
14
  bn = BigNumber.from(bn)
15 16 17 18 19

  // Negative numbers are converted to addresses by adding MAX_ADDRESS + 1.
  // TODO: Explain this in more detail, it's basically just matching the behavior of doing
  // addr(uint256(addr) - some_number) in Solidity where some_number > uint256(addr).
  if (bn.isNegative()) {
20
    bn = BigNumber.from('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF')
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
      .add(bn)
      .add(1)
  }

  // Convert to a hex string
  let addr = bn.toHexString()
  // Remove leading 0x so we can mutate the address a bit
  addr = remove0x(addr)
  // Make sure it's 40 characters (= 20 bytes)
  addr = addr.padStart(40, '0')
  // Only take the last 40 characters (= 20 bytes)
  addr = addr.slice(addr.length - 40, addr.length)
  // Add 0x again
  addr = add0x(addr)
  // Convert into a checksummed address
36
  addr = getAddress(addr)
37 38 39

  return addr
}