Skip to main content
Transfers USDCx from the calling address (tx-sender) into the Heirloom vault contract, increasing the vault’s usdcx-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-usdcx (amount uint)) -> (response bool uint))

Parameters

amount
uint
required
The amount of USDCx to deposit, denominated in micro-units (the smallest USDCx unit). USDCx has 6 decimal places.
Human amountMicro-unit value
$1.00 USDCu1000000
$10.00 USDCu10000000
$100.00 USDCu100000000
$1,000.00 USDCu1000000000
Amount must be greater than zero.

Return value

ok
bool
Returns (ok true) on success. The vault’s usdcx-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:
;; From heirloom-vault.clar
(try! (restrict-assets? tx-sender
  ((with-ft 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx "usdcx-token" amount))
  (try! (contract-call? 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx transfer amount tx-sender current-contract none))
))

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

JavaScript example

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

// Deposit $500.00 USDC (500,000,000 micro-units)
const amountMicro = 500 * 1_000_000; // = 500000000
await depositUsdcx(amountMicro, senderAddress);

// Deposit $1.50 USDC
await depositUsdcx(1.5 * 1_000_000, senderAddress);
postConditionMode: 'allow' is used for the same reason as in deposit-sbtc. The contract enforces the exact transfer amount internally via restrict-assets?, making external post-conditions redundant and potentially conflicting.
USDCx uses 6 decimal places, not 8. A common mistake is applying sBTC’s satoshi multiplier (× 10^8) to USDCx amounts. Use × 10^6 (1,000,000) for USDCx.

Build docs developers (and LLMs) love