You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.9 KiB
170 lines
4.9 KiB
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
|
|
}
|