ox
Version:
170 lines (156 loc) • 4.99 kB
text/typescript
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
}