Try it Live Run Address examples in the interactive playground
This page is a placeholder. All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.
Auto-injected API
Factory API
import { Address } from '@tevm/voltaire'
const deployer = Address ( "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e" )
const salt = Bytes32 () // 32-byte salt
const initCode = Bytecode ([ 0x60 , 0x80 ]) // Contract bytecode
const contractAddr = Address . calculateCreate2Address ( deployer , salt , initCode )
console . log ( contractAddr . toHex ())
import { CalculateCreate2Address } from '@tevm/voltaire/Address'
import { hash as keccak256 } from '@tevm/voltaire/Keccak256'
import * as Address from '@tevm/voltaire/Address'
// Create function with injected dependencies
const calculateCreate2Address = CalculateCreate2Address ({ keccak256 })
const deployer = Address ( "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e" )
const salt = Bytes32 () // 32-byte salt
const initCode = Bytecode ([ 0x60 , 0x80 ]) // Contract bytecode
const contractAddr = calculateCreate2Address ( deployer , salt , initCode )
console . log ( contractAddr . toHex ())
Tree-shakeable - only bundles keccak256 hash function
Algorithm
Hash init code: initCodeHash = keccak256(initCode)
Concatenate data: data = 0xff ++ sender (20 bytes) ++ salt (32 bytes) ++ initCodeHash (32 bytes)
Hash and extract: address = keccak256(data)[12:32]
Pseudocode:
init_code_hash = keccak256(init_code)
data = [0xff] + sender_address + salt + init_code_hash
hash = keccak256(data)
contract_address = hash[12:32]
Total data size: 1 + 20 + 32 + 32 = 85 bytes
Bigint salt: Converted to 32-byte big-endian:
const salt = 42 n
// Becomes: [0, 0, ..., 0, 42] (32 bytes)
Uint8Array salt: Must be exactly 32 bytes:
const salt = Bytes32 ()
salt [ 0 ] = 0x12
salt [ 31 ] = 0x34
Hex salt: Convert from hex string:
import * as Hex from '@tevm/voltaire/Hex'
const salt = Hex . toBytes ( "0x0000000000000000000000000000000000000000000000000000000000000001" )
Complete Example
import { Address } from '@tevm/voltaire'
import * as Hex from '@tevm/voltaire/Hex'
// Deployer (could be factory contract)
const factory = Address ( "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e" )
// Contract bytecode (initialization code)
const initCode = Hex . toBytes (
"0x608060405234801561001057600080fd5b5060405161012..." // Full bytecode
)
// Deploy with different salts
function predictAddress ( salt : bigint ) : Address {
return factory . calculateCreate2Address ( salt , initCode )
}
// Predict addresses
const addr1 = predictAddress ( 0 n )
const addr2 = predictAddress ( 1 n )
const addr3 = predictAddress ( 42 n )
console . log ( 'Salt 0:' , addr1 . toHex ())
console . log ( 'Salt 1:' , addr2 . toHex ())
console . log ( 'Salt 42:' , addr3 . toHex ())
// Deploy to predicted address
async function deployWithSalt ( salt : bigint ) {
const predicted = predictAddress ( salt )
// Deploy using CREATE2
const tx = await factory . create2Deploy ( salt , initCode )
await tx . wait ()
console . log ( `Deployed to ${ tx . contractAddress } ` )
console . log ( `Predicted: ${ predicted . toHex () } ` )
console . log ( `Match: ${ tx . contractAddress === predicted . toHex () } ` )
}
Use Cases
Deterministic Deployments
Deploy to same address across different chains:
import { Address } from '@tevm/voltaire'
const factory = Address ( "0x..." )
const salt = 42 n
const initCode = // ... bytecode
// Same address on all chains with same factory, salt, and code
const predictedAddress = factory . calculateCreate2Address ( salt , initCode )
// Deploy on mainnet
await deployOnChain ( 'mainnet' , factory , salt , initCode )
// Deploy on testnet (same address)
await deployOnChain ( 'goerli' , factory , salt , initCode )
Counterfactual Addresses
Interact with contract before deployment:
import { Address } from '@tevm/voltaire'
// Predict address
const contractAddress = factory . calculateCreate2Address ( salt , initCode )
// Send funds before deployment
await sendEth ( contractAddress , amount )
// Deploy later
await factory . create2Deploy ( salt , initCode )
// Contract now has funds
Vanity Addresses
Generate addresses with specific patterns:
import { Address } from '@tevm/voltaire'
function findVanitySalt (
factory : Address ,
initCode : Uint8Array ,
prefix : string
) : bigint {
for ( let salt = 0 n ; salt < 1000000 n ; salt ++ ) {
const addr = factory . calculateCreate2Address ( salt , initCode )
if ( addr . toHex (). startsWith ( prefix )) {
return salt
}
}
throw new Error ( 'Salt not found' )
}
// Find salt that produces address starting with "0x0000"
const salt = findVanitySalt ( factory , initCode , "0x0000" )
const vanityAddress = factory . calculateCreate2Address ( salt , initCode )
Upgradeable Proxies
Deploy proxies to deterministic addresses:
import { Address } from '@tevm/voltaire'
class ProxyFactory {
constructor (
private factory : Address ,
private proxyBytecode : Uint8Array
) {}
predictProxy ( owner : Address , salt : bigint ) : Address {
// Include owner in salt for uniqueness
const fullSalt = this . encodeSalt ( owner , salt )
return this . factory . calculateCreate2Address ( fullSalt , this . proxyBytecode )
}
private encodeSalt ( owner : Address , salt : bigint ) : Uint8Array {
const saltBytes = Bytes32 ()
// First 20 bytes: owner
saltBytes . set ( owner , 0 )
// Last 12 bytes: salt
for ( let i = 0 ; i < 12 ; i ++ ) {
saltBytes [ 31 - i ] = Number (( salt >> BigInt ( i * 8 )) & 0xff n )
}
return saltBytes
}
}
EIP-1014
CREATE2 was introduced in EIP-1014 to enable:
Deterministic addresses independent of nonce
Counterfactual interactions (interact before deployment)
State channels with guaranteed addresses
Cross-chain consistency (same address on different chains)
CREATE vs CREATE2
Feature CREATE CREATE2 Formula keccak256(rlp([addr, nonce]))[12:]keccak256(0xff ++ addr ++ salt ++ keccak256(code))[12:]Parameters Deployer, nonce Deployer, salt, init code Determinism Sequential (nonce-based) Arbitrary (salt-based) Redeployment Different address Same address if inputs identical Cross-chain Different addresses Same address possible
Cryptographic operations:
Two keccak256 hashes (init code + final data)
No RLP encoding required
Bundle size impact: Adds keccak256 (~5-10 KB)
Error Handling
import { Address } from '@tevm/voltaire'
const deployer = Address ( "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e" )
const initCode = Bytecode ([ 0x60 , 0x80 ])
// Valid salts
const addr1 = deployer . calculateCreate2Address ( 42 n , initCode ) // ✓
const addr2 = deployer . calculateCreate2Address ( Bytes32 (), initCode ) // ✓
// Invalid: negative salt
try {
deployer . calculateCreate2Address ( - 1 n , initCode )
} catch ( e ) {
console . error ( e ) // InvalidValueError: Salt cannot be negative
}
// Invalid: wrong salt length
try {
deployer . calculateCreate2Address ( Bytes16 (), initCode )
} catch ( e ) {
console . error ( e ) // Error: Salt must be 32 bytes
}
See Also