Contract Code

Overview

Every deployed contract on OP_NET stores its compiled WASM bytecode on-chain. The provider exposes a method to retrieve this bytecode, enabling use cases such as verifying that a deployed contract matches expected source code, analyzing contract size and structure, and debugging deployment issues.

Using getCode()

The provider's getCode() method retrieves deployed contract data from the network.
It supports two retrieval modes:

  • A lightweight mode that returns only the raw bytecode.
  • A full mode that includes the bytecode along with contract metadata.

Use the lightweight mode when you only need the bytecode itself, as it reduces response size and parsing overhead.

typescript
getCode() Method Signature
async getCode(
    address: string | Address,
    onlyBytecode?: boolean
): Promise<ContractData | Buffer>

The following table describes each parameter accepted by this method.

Parameter Type Required Description
address string | Address Yes The contract address to fetch code from.
onlyBytecode boolean No Specifies the response format. true for raw WASM bytecode only, false for the complete ContractData object.

ContractData Class

The ContractData class encapsulates the contract's compiled WASM bytecode alongside its on-chain metadata, providing a complete representation of a deployed contract as stored on the network.

typescript
ContractData Interface Definition
interface ContractData {
    bytecode: Uint8Array;       // Contract WASM bytecode
    contractAddress: Address;   // Contract address
}

Usage

Fetch Full Contract Data

To retrieve the bytecode along with all associated metadata, set onlyBytecode to false.

typescript
Fetch Full Contract Data
const address = Address.fromString('0x...');
const contractData = await provider.getCode(address, false);

console.log('Contract address:', contractData.contractAddress.toHex());
console.log('Bytecode size:', contractData.bytecode.length, 'bytes');

Fetch Bytecode Only

When only the bytecode is needed, set onlyBytecode to true to reduce response size and improve performance.

typescript
Fetch Bytecode Only
import { toHex } from '@btc-vision/bitcoin';

const contractData = await provider.getCode(contractAddress, true);

const bytecode = contractData.bytecode;
console.log('Bytecode:', toHex(bytecode).slice(0, 100), '...');

Use Cases

Verify Contract Deployment

Check whether a contract has been deployed at a specific address.

typescript
Verify Contract Deployment
async function isContractDeployed(
    provider: AbstractRpcProvider,
    address: string | Address
): Promise<boolean> {
    try {
        const code = await provider.getCode(address, true);
        return code.bytecode.length > 0;
    } catch {
        return false;
    }
}

// Usage
const deployed = await isContractDeployed(provider, contractAddress);
console.log('Contract deployed:', deployed);

Compare Contract Code

Determine whether two contracts have identical bytecode.

typescript
Compare Contract Code
import { toHex } from '@btc-vision/bitcoin';

async function compareContracts(
    provider: AbstractRpcProvider,
    address1: Address,
    address2: Address
): Promise<boolean> {
    const [code1, code2] = await Promise.all([
        provider.getCode(address1, true),
        provider.getCode(address2, true),
    ]);

    return toHex(code1.bytecode) === toHex(code2.bytecode);
}

// Check if two contracts have the same code
const sameCode = await compareContracts(provider, addr1, addr2);
console.log('Same bytecode:', sameCode);

Calculate Code Hash

Generate a unique identifier for contract code using a cryptographic hash.

typescript
Calculate Code Hash
import { toHex } from '@btc-vision/bitcoin';
import { sha256 } from '@noble/hashes/sha256';

async function getCodeHash(
    provider: AbstractRpcProvider,
    address: Address
): Promise<string> {
    const contractData = await provider.getCode(address, true);
    const hash = sha256(contractData.bytecode);
    return toHex(hash);
}

// Get unique identifier for contract code
const codeHash = await getCodeHash(provider, contractAddress);
console.log('Code hash:', codeHash);

Contract Verification

Verify that a deployed contract matches the expected bytecode.

typescript
Contract Verification
import { toHex } from '@btc-vision/bitcoin';

async function verifyContract(
    provider: AbstractRpcProvider,
    address: Address,
    expectedBytecode: Uint8Array
): Promise<boolean> {
    const contractData = await provider.getCode(address, true);
    return toHex(contractData.bytecode) === toHex(expectedBytecode);
}

Security Analysis

Analyze contract size and bytecode characteristics.

typescript
Security Analysis
import { toHex } from '@btc-vision/bitcoin';

async function analyzeContract(
    provider: AbstractRpcProvider,
    address: Address
) {
    const contractData = await provider.getCode(address, false);

    console.log('Contract Analysis:');
    console.log('  Address:', contractData.contractAddress.toHex());
    console.log('  Bytecode size:', contractData.bytecode.length, 'bytes');

    return {
        address: contractData.contractAddress.toHex(),
        size: contractData.bytecode.length,
    };
}

Contract Discovery

Identify contracts matching a specific code hash.

typescript
Contract Discovery
async function findContractsWithCode(
    provider: AbstractRpcProvider,
    addresses: Address[],
    targetCodeHash: string
): Promise<Address[]> {
    const matches: Address[] = [];

    for (const address of addresses) {
        try {
            const codeHash = await getCodeHash(provider, address);
            if (codeHash === targetCodeHash) {
                matches.push(address);
            }
        } catch {
            // Contract doesn't exist or error occurred
        }
    }

    return matches;
}