Guides and Tutorials

Welcome to Corsa's guides and tutorials section. Here you'll find step-by-step instructions for common tasks and use cases. These guides will help you leverage the full power of Corsa's Ethereum Layer 2 solution with integrated Bitcoin functionality.

Table of Contents


How to Send a Bitcoin Transaction from an Ethereum Smart Contract

This guide will walk you through the process of sending a Bitcoin transaction using Corsa's custom precompiles from within an Ethereum smart contract.

Prerequisites

  • A Corsa node up and running

  • Basic knowledge of Solidity and Ethereum smart contracts

  • Some test BTC in your Bitcoin wallet (regtest)

Step 1: Create the Solidity Smart Contract

First, let's create a simple Ethereum smart contract that will interact with the Bitcoin network:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract BitcoinSender {
    address constant BITCOIN_PRECOMPILE = 0x0000000000000000000000000000000000000999;
    
    function sendBitcoinTransaction(bytes memory rawTransaction) public returns (bytes32) {
        (bool success, bytes memory result) = BITCOIN_PRECOMPILE.call(abi.encodePacked(bytes4(0x00000000), rawTransaction));
        require(success, "Bitcoin transaction failed");
        return abi.decode(result, (bytes32)); // bitcoin txid
    }
}

Step 2: Deploy the Smart Contract

Deploy this contract to your Corsa network using your preferred method (Foundry, Hardhat, Remix, etc...)

Step 3: Prepare the Bitcoin Transaction

Prepare your raw Bitcoin transaction off-chain. There are many ways to do this. For users users proficient with this cli, you can use btc-dev-utils for this purpose.

cd btc-dev-utils
just sign-tx <your-wallet-name> <recipient-btc-address>

Other options from preparing a raw signed transaction include the Electrum and Sparrow self custodial BTC wallets. Ensure your wallet is configured for the chain you want to use.

Step 4: Send the Bitcoin Transaction

Use web3.js, ethers.js, or Foundry's cast to interact with your deployed smart contract and send the Bitcoin transaction:

const { ethers } = require('ethers');

const provider = new ethers.providers.JsonRpcProvider('http://localhost:8545');
const signer = provider.getSigner();
const contractAddress = 'your_deployed_contract_address';
const abi = [/* Your contract ABI */];

const contract = new ethers.Contract(contractAddress, abi, signer);

async function sendBitcoinTx(rawTx) {
    const tx = await contract.sendBitcoinTransaction('0x' + rawTx);
    const receipt = await tx.wait();
    console.log('Bitcoin transaction sent:', receipt);
}

sendBitcoinTx(rawTransaction);

That's it! You've successfully sent a Bitcoin transaction from an Ethereum smart contract using OnCorsa.

Decoding a Bitcoin Transaction from an Ethereum Smart Contract

This guide will walk you through the process of decoding a Bitcoin raw transaction using Corsa's custom precompiles from within an Ethereum smart contract.

Prerequisites

  • An OnCorsa node up and running

  • Basic knowledge of Solidity and Ethereum smart contracts

  • A Bitcoin raw transaction to decode

Step 1: Create the Solidity Smart Contract

First, let's create a simple Ethereum smart contract that will decode a Bitcoin transaction:

contract BitcoinTxDecoder {
    address constant BITCOIN_PRECOMPILE = 0x0000000000000000000000000000000000000999;
  
    struct Output {
        string addr;
        uint256 value;
        bytes script;
    }

    struct Input {
        bytes32 prevTxHash;
        uint32 outputIndex;
        bytes scriptSig;
        bytes[] witness;
    }

    struct BitcoinTx {
        bytes32 txid;
        Output[] outputs;
        Input[] inputs;
        uint256 locktime;
    }
    
    function decodeBitcoinTransaction(bytes memory rawTransaction) public view returns (BitcoinTx memory) {
        (bool success, bytes memory returndata) = BITCOIN_PRECOMPILE.staticcall(
          abi.encodePacked(bytes4(00000002), rawTransaction)
        );
        require(success, "Bitcoin transaction decoding failed");
        return abi.decode(returndata, (BitcoinTx));
    }
}

Step 2: Deploy the Smart Contract

Deploy this contract to your Corsa network using your preferred method (Foundry, Hardhat, Remix, etc...)

Step 3: Prepare the Bitcoin Transaction

You'll need a raw Bitcoin transaction to decode. This is typically a hexadecimal string representing the serialized transaction. For example:

const rawTransaction = "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0503858a0100ffffffff0200f2052a01000000160014e8df018c7e326cc253faac7e46cdc51e68542c420000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000";

Step 4: Decode the Bitcoin Transaction

Use web3.js, ethers.js, or Foundry's cast to interact with your deployed smart contract and send the Bitcoin transaction:

const { ethers } = require('ethers');

const provider = new ethers.providers.JsonRpcProvider('http://localhost:8545');
const signer = provider.getSigner();
const contractAddress = 'your_deployed_contract_address';
const abi = [/* Your contract ABI */];

const contract = new ethers.Contract(contractAddress, abi, signer);

async function decodeBitcoinTx(rawTx) {
    const decodedTx = await contract.decodeBitcoinTransaction('0x' + rawTx);
    console.log('Decoded Bitcoin transaction:', decodedTx);
}

decodeBitcoinTx(rawTransaction);

Step 5: Interpret/ Verify the Results

The decodeBitcoinTransaction function will return a structured BitcoinTx object as defined in the BitcoinTxDecoder Solidity contract. The fields in this struct can be used to verify the tx recipient, tx amount, locktimes, input txid's, etc...

Verify a Contract on Corsascan

This guide will walk you through how to verify a contract you have deployed to the Corsa network.

Prerequisites

  • An RPC connection to Corsa

  • Basic knowledge of Solidity and Ethereum smart contracts

  • Foundry installed

Option 1: Call forge verify

forge verify-contract \
  --rpc-url http://rpc.oncorsa.com \
  --verifier blockscout \
  --verifier-url 'http://rpc.oncorsa.com/api/' --compiler-version 0.8.26 \
  <your-contract-address> \
  src/<your-contract-name>.sol:<your-contract-name>

Option 2: Verify with the Corsascan UI

Go to https://scan.oncorsa.com/contract-verification and follow the steps there to verify your contract.

Last updated