Skip to main content
Transfers sBTC from the calling address (tx-sender) into the Heirloom vault contract, increasing the vault’s sbtc-balance. The vault must exist and must not be distributed. The calling address must be the vault owner because only the owner’s vault entry is looked up via tx-sender.

Function signature

(define-public (deposit-sbtc (amount uint)) -> (response bool uint))

Parameters

amount
uint
required
The amount of sBTC to deposit, denominated in satoshis (the smallest sBTC unit). sBTC has 8 decimal places.
Human amountSatoshi value
0.001 BTCu100000
0.01 BTCu1000000
0.1 BTCu10000000
1 BTCu100000000
Amount must be greater than zero.

Return value

ok
bool
Returns (ok true) on success. The vault’s sbtc-balance is incremented by amount.
err
uint
Returns (err uint) on failure. See error codes below.

Error codes

CodeConstantWhen returned
u103ERR-VAULT-NOT-FOUNDThe calling address has no vault
u110ERR-VAULT-DISTRIBUTEDThe vault has been distributed or cancelled
u113ERR-NO-BALANCEamount is zero

How the transfer works

The function uses Clarity 4’s restrict-assets? with with-ft to enforce the exact transfer amount as a post-condition within the contract itself. This prevents callers from submitting transactions that transfer a different amount than the deposit function expects:
;; From heirloom-vault.clar
(try! (restrict-assets? tx-sender
  ((with-ft 'ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token "sbtc-token" amount))
  (try! (contract-call? 'ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token transfer amount tx-sender current-contract none))
))

;; Update balance
(map-set vaults tx-sender
  (merge vault { sbtc-balance: (+ (get sbtc-balance vault) amount) })
)
The sBTC contract is ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token. Tokens are transferred to current-contract — the vault contract’s own principal.

JavaScript example

import { depositSbtc } from './lib/contracts';

// Deposit 0.001 BTC (100,000 satoshis)
const amountSats = 0.001 * 100_000_000; // = 100000
await depositSbtc(amountSats, senderAddress);

// Deposit 0.5 BTC (50,000,000 satoshis)
await depositSbtc(0.5 * 100_000_000, senderAddress);
postConditionMode: 'allow' is used to avoid post-condition conflicts. Because the contract enforces the exact transfer amount internally via restrict-assets?, external post-conditions are redundant. Using allow mode prevents wallet-level post-condition failures if the transaction errors before reaching restrict-assets? (for example, when ERR-VAULT-NOT-FOUND is returned).
Always pass amounts as integers (satoshis). Never use floating-point arithmetic to compute satoshi values — use integer multiplication only. For example, 0.1 * 100_000_000 in JavaScript may produce 10000000.000000002 due to floating-point precision. Use Math.round() or a bigint library for production code.

Build docs developers (and LLMs) love