UNPKG

ox

Version:

Ethereum Standard Library

170 lines (156 loc) 4.99 kB
import * as Address from './Address.js' import * as Bytes from './Bytes.js' import type * as Errors from './Errors.js' import * as Hash from './Hash.js' import * as Hex from './Hex.js' import type { OneOf } from './internal/types.js' import * as Rlp from './Rlp.js' /** * Computes Contract Address generated by the [CREATE](https://ethereum.stackexchange.com/questions/68943/create-opcode-what-does-it-really-do/68945#68945) or [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode. * * @example * ### CREATE * * Computes via the [CREATE](https://ethereum.stackexchange.com/questions/68943/create-opcode-what-does-it-really-do/68945#68945) opcode. Shorthand for {@link ox#ContractAddress.(fromCreate:function)}. * * ```ts twoslash * import { ContractAddress } from 'ox' * ContractAddress.from({ * from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6', * nonce: 0n, * }) * // @log: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2' * ``` * * @example * ### CREATE2 * * Computes via the [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode. Shorthand for {@link ox#ContractAddress.(fromCreate2:function)}. * * ```ts twoslash * import { ContractAddress, Hex } from 'ox' * ContractAddress.from({ * from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6', * bytecode: '0x6394198df16000526103ff60206004601c335afa6040516060f3', * salt: Hex.fromString('hello world'), * }) * // @log: '0x59fbB593ABe27Cb193b6ee5C5DC7bbde312290aB' * ``` * * @param options - Options. * @returns Contract Address. */ export function from(options: from.Options): Address.Address { if (options.salt) return fromCreate2(options) return fromCreate(options) } export declare namespace from { export type Options = OneOf<fromCreate.Options | fromCreate2.Options> type ErrorType = | fromCreate.ErrorType | fromCreate2.ErrorType | Errors.GlobalErrorType } /** * Computes contract address via [CREATE](https://ethereum.stackexchange.com/questions/68943/create-opcode-what-does-it-really-do/68945#68945) opcode. * * @example * ```ts twoslash * import { ContractAddress } from 'ox' * * ContractAddress.fromCreate({ * from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6', * nonce: 0n, * }) * // @log: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2' * ``` * * @param options - Options for retrieving address. * @returns Contract Address. */ export function fromCreate(options: fromCreate.Options): Address.Address { const from = Bytes.fromHex(Address.from(options.from)) let nonce = Bytes.fromNumber(options.nonce) if (nonce[0] === 0) nonce = new Uint8Array([]) return Address.from( `0x${Hash.keccak256(Rlp.fromBytes([from, nonce], { as: 'Hex' })).slice(26)}` as Address.Address, ) } export declare namespace fromCreate { type Options = { /** The address the contract was deployed from. */ from: Address.Address /** The nonce of the transaction which deployed the contract. */ nonce: bigint } type ErrorType = | Hash.keccak256.ErrorType | Address.from.ErrorType | Bytes.fromHex.ErrorType | Bytes.fromNumber.ErrorType | Rlp.fromBytes.ErrorType | Errors.GlobalErrorType } /** * Computes contract address via [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode. * * @example * ```ts twoslash * import { ContractAddress, Hex } from 'ox' * * ContractAddress.fromCreate2({ * from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6', * bytecode: '0x6394198df16000526103ff60206004601c335afa6040516060f3', * salt: Hex.fromString('hello world'), * }) * // @log: '0x59fbB593ABe27Cb193b6ee5C5DC7bbde312290aB' * ``` * * @param options - Options for retrieving address. * @returns Contract Address. */ export function fromCreate2(options: fromCreate2.Options): Address.Address { const from = Bytes.fromHex(Address.from(options.from)) const salt = Bytes.padLeft( Bytes.validate(options.salt) ? options.salt : Bytes.fromHex(options.salt), 32, ) const bytecodeHash = (() => { if ('bytecodeHash' in options) { if (Bytes.validate(options.bytecodeHash)) return options.bytecodeHash return Bytes.fromHex(options.bytecodeHash) } return Hash.keccak256(options.bytecode, { as: 'Bytes' }) })() return Address.from( Hex.slice( Hash.keccak256( Bytes.concat(Bytes.fromHex('0xff'), from, salt, bytecodeHash), { as: 'Hex' }, ), 12, ), ) } export declare namespace fromCreate2 { type Options = | { bytecode: Bytes.Bytes | Hex.Hex from: Address.Address salt: Bytes.Bytes | Hex.Hex } | { bytecodeHash: Bytes.Bytes | Hex.Hex from: Address.Address salt: Bytes.Bytes | Hex.Hex } type ErrorType = | Address.from.ErrorType | Bytes.concat.ErrorType | Bytes.validate.ErrorType | Bytes.padLeft.ErrorType | Hash.keccak256.ErrorType | Hex.slice.ErrorType | Bytes.fromHex.ErrorType | Errors.GlobalErrorType }