Contract Address

Similar to wallet addresses, contract addresses in the EVM are also stored in a 20-byte hex format. Even if it doesn't need to be sliced by the Solidity address data type itself, address slicing issues can also arise during cross-contract calls. To maintain consistency with EVM behavior, the Veda application needs to directly input the pre-calculated Contract Address when constructing the execute instruction. The rule for calculating the Contract Address is to hash the deployer's hex address combined with the transaction nonce using keccak256.

Example

import * as bitcoin from 'bitcoinjs-lib'
import { keccak256 } from 'web3-utils'
import RLP from 'rlp'

const publicKeyToAddress = (publicKeyHex: string, networkType: 'mainnet' | 'testnet' = 'mainnet') => {
  const publicKeyBuffer = Buffer.from(publicKeyHex, 'hex')
  const network = networkType === 'mainnet' ? bitcoin.networks.bitcoin : bitcoin.networks.testnet

  // p2tr
  const toXOnly = (pubKey: Buffer) => (pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33))
  const tapInternalKey = toXOnly(publicKeyBuffer)

  return {
    p2tr: bitcoin.payments.p2tr({ internalPubkey: tapInternalKey, network }).address!,
    p2pkh: bitcoin.payments.p2pkh({ pubkey: publicKeyBuffer, network }).address!,
    p2sh: bitcoin.payments.p2sh({
      redeem: bitcoin.payments.p2wpkh({ pubkey: publicKeyBuffer, network }),
    }).address!,
    p2wpkh: bitcoin.payments.p2wpkh({ pubkey: publicKeyBuffer, network }).address!,
  }
}
const toHexAddress = (address: string) => {
  const hash = keccak256(address)

  return '0x' + hash.slice(26)
}
const generateContractAddress = (walletAddress: string, nonce: number) => {
  const input = RLP.encode([walletAddress, nonce])
  const hash = keccak256(input)

  return '0x' + hash.slice(26)
}

// Example
const sampleInstruction: DeploySerialInstruction = {
  p: 'veda',
  publicKey: 'YOUR PUBLIC KEY HERE',
  addressType: 'p2wpkh',
  action: 'deploy',
  bytecodeLocation: 'BYTECODE ORDINALS ID HERE'
  nonce: 0,
  data: 'DATA HERE',
}
const ownerAddress = toHexAddress(
  publicKeyToAddress(sampleInstruction.publicKey)[sampleInstruction.addressType as 'p2pkh' | 'p2wpkh' | 'p2sh' | 'p2tr'],
)
const contractAddress = generateContractAddress(ownerAddress, sampleInstruction.nonce)

Last updated