contract-address.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { keccak256 } from "../crypto/index.js";
  2. import {
  3. concat, dataSlice, getBigInt, getBytes, encodeRlp, assertArgument
  4. } from "../utils/index.js";
  5. import { getAddress } from "./address.js";
  6. import type { BigNumberish, BytesLike } from "../utils/index.js";
  7. // http://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed
  8. /**
  9. * Returns the address that would result from a ``CREATE`` for %%tx%%.
  10. *
  11. * This can be used to compute the address a contract will be
  12. * deployed to by an EOA when sending a deployment transaction (i.e.
  13. * when the ``to`` address is ``null``).
  14. *
  15. * This can also be used to compute the address a contract will be
  16. * deployed to by a contract, by using the contract's address as the
  17. * ``to`` and the contract's nonce.
  18. *
  19. * @example
  20. * from = "0x8ba1f109551bD432803012645Ac136ddd64DBA72";
  21. * nonce = 5;
  22. *
  23. * getCreateAddress({ from, nonce });
  24. * //_result:
  25. */
  26. export function getCreateAddress(tx: { from: string, nonce: BigNumberish }): string {
  27. const from = getAddress(tx.from);
  28. const nonce = getBigInt(tx.nonce, "tx.nonce");
  29. let nonceHex = nonce.toString(16);
  30. if (nonceHex === "0") {
  31. nonceHex = "0x";
  32. } else if (nonceHex.length % 2) {
  33. nonceHex = "0x0" + nonceHex;
  34. } else {
  35. nonceHex = "0x" + nonceHex;
  36. }
  37. return getAddress(dataSlice(keccak256(encodeRlp([ from, nonceHex ])), 12));
  38. }
  39. /**
  40. * Returns the address that would result from a ``CREATE2`` operation
  41. * with the given %%from%%, %%salt%% and %%initCodeHash%%.
  42. *
  43. * To compute the %%initCodeHash%% from a contract's init code, use
  44. * the [[keccak256]] function.
  45. *
  46. * For a quick overview and example of ``CREATE2``, see [[link-ricmoo-wisps]].
  47. *
  48. * @example
  49. * // The address of the contract
  50. * from = "0x8ba1f109551bD432803012645Ac136ddd64DBA72"
  51. *
  52. * // The salt
  53. * salt = id("HelloWorld")
  54. *
  55. * // The hash of the initCode
  56. * initCode = "0x6394198df16000526103ff60206004601c335afa6040516060f3";
  57. * initCodeHash = keccak256(initCode)
  58. *
  59. * getCreate2Address(from, salt, initCodeHash)
  60. * //_result:
  61. */
  62. export function getCreate2Address(_from: string, _salt: BytesLike, _initCodeHash: BytesLike): string {
  63. const from = getAddress(_from);
  64. const salt = getBytes(_salt, "salt");
  65. const initCodeHash = getBytes(_initCodeHash, "initCodeHash");
  66. assertArgument(salt.length === 32, "salt must be 32 bytes", "salt", _salt);
  67. assertArgument(initCodeHash.length === 32, "initCodeHash must be 32 bytes", "initCodeHash", _initCodeHash);
  68. return getAddress(dataSlice(keccak256(concat([ "0xff", from, salt, initCodeHash ])), 12))
  69. }