Skip to main content

Overview

This guide covers the complete deployment process for BTCVault smart contracts, from local development to mainnet deployment. The contracts are built using Scarb (Cairo’s package manager) and deployed to StarkNet using the starkli CLI tool.

Prerequisites

Before deploying contracts, ensure you have the following tools installed:
  • Scarb 2.14.0: Cairo package manager (installation guide)
  • Cairo 2.14.0: Automatically installed with Scarb
  • Starkli: StarkNet CLI tool for deployment (installation guide)
  • StarkNet wallet: ArgentX or Braavos browser extension
  • Funds: ETH on StarkNet for deployment gas fees

Environment Setup

1. Verify Installation

Confirm your development environment is configured correctly:
scarb --version  # Should show: scarb 2.14.0
cairo --version  # Should show: cairo 2.14.0
starkli --version

2. Configure StarkNet Account

Export your StarkNet account credentials:
export STARKNET_ACCOUNT=~/.starkli-wallets/deployer/account.json
export STARKNET_KEYSTORE=~/.starkli-wallets/deployer/keystore.json
export STARKNET_RPC="https://starknet-mainnet.public.blastapi.io"
If you haven’t created a StarkNet account yet, follow the Starkli account setup guide.

3. Project Structure

The contract source files are organized as follows:
contracts/
├── Scarb.toml           # Package configuration
├── src/
│   ├── lib.cairo        # Module exports
│   ├── interfaces.cairo # External protocol interfaces
│   ├── btcvault.cairo   # Main BTC vault
│   ├── stablecoin_vault.cairo
│   ├── sentinel.cairo
│   ├── delta_neutral.cairo
│   ├── apex.cairo
│   ├── trident.cairo
│   ├── citadel.cairo
│   ├── dca.cairo
│   ├── cdp.cairo
│   ├── shielded_pool*.cairo
│   └── strategy.cairo   # Helper utilities
└── target/              # Build artifacts (generated)

Building Contracts

1

Navigate to Contract Directory

Change to the contracts directory:
cd ~/workspace/source/contracts
2

Clean Previous Builds

Remove old build artifacts to ensure a fresh compilation:
scarb clean
3

Build Contracts

Compile all contracts to Sierra and CASM bytecode:
scarb build
This generates two files per contract:
  • Sierra JSON (target/dev/btcvault_BTCVault.contract_class.json): High-level intermediate representation
  • CASM JSON (target/dev/btcvault_BTCVault.compiled_contract_class.json): Low-level Cairo Assembly
4

Verify Build Artifacts

Confirm the build succeeded by checking for generated files:
ls -lh target/dev/*.contract_class.json
You should see contract class files for all modules defined in lib.cairo.
The Scarb.toml file specifies allowed-libfuncs-list.name = "experimental". This is required for certain Cairo 2.14.0 features but may not be allowed on all StarkNet networks. For mainnet deployment, verify the current allowed libfuncs list.

Deployment Process

Deploying a contract to StarkNet is a two-step process:
  1. Declare: Upload the contract class to the network (one-time per class)
  2. Deploy: Instantiate the contract class with constructor arguments
1

Declare Contract Class

Upload the contract class to StarkNet and obtain a class hash:
starkli declare \
  target/dev/btcvault_BTCVault.contract_class.json \
  --compiler-version 2.14.0
Save the class hash—you’ll need it for deployment and upgrades.
If the contract class has already been declared, Starkli will return the existing class hash without submitting a new transaction.
2

Prepare Constructor Arguments

BTCVault contracts require several constructor parameters. Prepare them as hex-encoded StarkNet addresses:
WBTC_ADDRESS="0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac"
OWNER_ADDRESS="0x..."  # Your curator wallet address
VESU_SINGLETON="0x000d8d6dfec4d33bfb6895de9f3852143a17c6f92fd2a21da3d6924d34870160"
VESU_POOL_ID="0x03a8416bf20d036df5b1cf3447630a2e1cb04685f6b0c3a70ed7fb1473548ecf"
AVNU_EXCHANGE="0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f"
USDC_ADDRESS="0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"
PRAGMA_ORACLE="0x02a85bd616f912537c50a49a4076db02c00b29b2cdc8a197ce92ed1837fa875b"
See src/strategy.cairo for additional mainnet addresses.
3

Deploy Contract Instance

Deploy the contract using the class hash and constructor arguments:
starkli deploy \
  0x1234...abcd \
  $WBTC_ADDRESS \
  $OWNER_ADDRESS \
  $VESU_SINGLETON \
  $VESU_POOL_ID \
  $AVNU_EXCHANGE \
  $USDC_ADDRESS \
  $PRAGMA_ORACLE
Save the contract address—this is your deployed vault instance.
4

Verify Deployment

Confirm the contract was deployed successfully:
starkli call \
  0xabcd...1234 \
  get_owner
This should return your owner address, confirming the constructor executed correctly.

Contract Upgrades

BTCVault contracts are upgradeable using StarkNet’s replace_class_syscall mechanism. This allows the curator to update contract logic without migrating user funds.
1

Build New Contract Version

Make code changes and rebuild:
scarb build
2

Declare New Class

Upload the new contract class:
starkli declare \
  target/dev/btcvault_BTCVault.contract_class.json \
  --compiler-version 2.14.0
Note the new class hash (e.g., 0x9999...aaaa).
3

Execute Upgrade

Call the upgrade function on the deployed contract:
starkli invoke \
  0xabcd...1234 \
  upgrade \
  0x9999...aaaa
Only the contract owner can call upgrade. Ensure you’re using the owner account configured in step 2.
4

Verify Upgrade

Confirm the contract is using the new class hash:
starkli class-hash-at 0xabcd...1234
This should return the new class hash (0x9999...aaaa).
Storage Compatibility: When upgrading contracts, ensure the new version maintains storage layout compatibility. Adding new storage variables at the end is safe, but reordering or removing variables will corrupt state.

Testing on Mainnet

Before deploying user funds, test vault operations on mainnet with small amounts:
1

Approve WBTC

Approve the vault to spend your WBTC:
starkli invoke \
  $WBTC_ADDRESS \
  approve \
  0xabcd...1234 \
  1000000  # 0.01 WBTC (8 decimals)
2

Deposit Assets

Deposit WBTC into the vault:
starkli invoke \
  0xabcd...1234 \
  deposit \
  1000000 \
  $YOUR_ADDRESS
This mints yvBTC vault shares to your address.
3

Deploy to Strategy

As curator, deploy idle assets to Vesu:
starkli invoke \
  0xabcd...1234 \
  deploy_to_vesu \
  1000000
4

Harvest Yield

Update vault accounting to reflect accrued interest:
starkli invoke \
  0xabcd...1234 \
  harvest
5

Withdraw Assets

Redeem vault shares for underlying WBTC:
starkli invoke \
  0xabcd...1234 \
  redeem \
  1000000 \
  $YOUR_ADDRESS \
  $YOUR_ADDRESS
The vault will automatically unwind Vesu positions if needed using flash loans.

Deployment Checklist

Before mainnet deployment, verify:
  • All contract addresses are correct for mainnet (not testnet)
  • Curator wallet has sufficient ETH for gas fees
  • Contract has been audited by a reputable security firm
  • Emergency pause mechanism is functional
  • Upgrade mechanism is tested on testnet
  • Oracle feeds (Pragma) are active and returning valid prices
  • Integration protocols (Vesu, AVNU) are operational
  • Minimum deposit thresholds meet Vesu dust requirements
  • Flash loan callback security is verified (sender == self)
  • Constructor parameters are documented for reproducibility

Common Issues

This occurs when the deposit amount is too small or the vault’s share calculation rounds to zero. Increase the deposit amount or check that total_assets_managed is not zero.
Vesu enforces minimum position values (dust thresholds). The minimum is calculated as (floor * scale) / price + 1. For WBTC, this is typically ~$10-20 worth. Ensure deposits exceed this threshold.
The flash loan callback is reverting due to security checks. Verify:
  • sender in on_flash_loan equals the vault contract address
  • get_caller_address() in callback equals the Vesu pool address
  • Pool ID is correctly configured in vault storage
The vault needs approval to spend tokens. Ensure:
  • WBTC approval is granted before depositing
  • USDC approval is sufficient for debt repayment (with buffer for rounding)
  • Vesu pool and singleton addresses are both approved for debt operations
Only the current owner can upgrade contracts. Verify:
  • You’re using the correct account (matches get_owner() return value)
  • Ownership transfer completed if recently transferred
  • Account JSON and keystore are correctly configured in environment variables

Next Steps

Smart Contracts Overview

Learn about contract architecture and design patterns

API Reference

Explore detailed contract interfaces and functions

Build docs developers (and LLMs) love