;; sBTC Deposit contract ;; constants ;; The required length of a txid (define-constant txid-length u32) (define-constant dust-limit u546) ;; protocol contract type (define-constant deposit-role 0x01) ;; error codes ;; TXID used in deposit is not the correct length (define-constant ERR_TXID_LEN (err u300)) ;; Deposit has already been completed (define-constant ERR_DEPOSIT_REPLAY (err u301)) (define-constant ERR_LOWER_THAN_DUST (err u302)) (define-constant ERR_DEPOSIT_INDEX_PREFIX (unwrap-err! ERR_DEPOSIT (err true))) (define-constant ERR_DEPOSIT (err u303)) (define-constant ERR_INVALID_CALLER (err u304)) (define-constant ERR_INVALID_BURN_HASH (err u305)) ;; public functions ;; Accept a new deposit request ;; Note that this function can only be called by the current ;; bootstrap signer set address - it cannot be called by users directly. ;; This function handles the validation & minting of sBTC, it then calls ;; into the sbtc-registry contract to update the state of the protocol (define-public (complete-deposit-wrapper (txid (buff 32)) (vout-index uint) (amount uint) (recipient principal) (burn-hash (buff 32)) (burn-height uint) (sweep-txid (buff 32))) (let ( (current-signer-data (contract-call? .sbtc-registry get-current-signer-data)) (replay-fetch (contract-call? .sbtc-registry get-deposit-status txid vout-index)) ) ;; Check that the caller is the current signer principal (asserts! (is-eq (get current-signer-principal current-signer-data) tx-sender) ERR_INVALID_CALLER) ;; Check that amount is greater than dust limit (asserts! (>= amount dust-limit) ERR_LOWER_THAN_DUST) ;; Check that txid is the correct length (asserts! (is-eq (len txid) txid-length) ERR_TXID_LEN) ;; Check that sweep txid is the correct length (asserts! (is-eq (len sweep-txid) txid-length) ERR_TXID_LEN) ;; Assert that the deposit has not already been completed (no replay) (asserts! (is-none replay-fetch) ERR_DEPOSIT_REPLAY) ;; Verify that Bitcoin hasn't forked by comparing the burn hash provided (asserts! (is-eq (some burn-hash) (get-burn-header burn-height)) ERR_INVALID_BURN_HASH) ;; Mint the sBTC to the recipient (try! (contract-call? .sbtc-token protocol-mint amount recipient deposit-role)) ;; Complete the deposit (contract-call? .sbtc-registry complete-deposit txid vout-index amount recipient burn-hash burn-height sweep-txid) ) ) ;; Return the bitcoin header hash of the bitcoin block at the given height. (define-read-only (get-burn-header (height uint)) (get-burn-block-info? header-hash height) ) ;; Accept multiple new deposit requests ;; Note that this function can only be called by the current ;; bootstrap signer set address - it cannot be called by users directly. ;; ;; This function handles the validation & minting of sBTC by handling multiple (up to 500) deposits at a time, ;; it then calls into the sbtc-registry contract to update the state of the protocol. (define-public (complete-deposits-wrapper (deposits (list 500 {txid: (buff 32), vout-index: uint, amount: uint, recipient: principal, burn-hash: (buff 32), burn-height: uint, sweep-txid: (buff 32)})) ) (begin ;; Check that the caller is the current signer principal (asserts! (is-eq (contract-call? .sbtc-registry get-current-signer-principal) tx-sender ) ERR_INVALID_CALLER) (fold complete-individual-deposits-helper deposits (ok u0)) ) ) ;; private functions (define-private (complete-individual-deposits-helper (deposit {txid: (buff 32), vout-index: uint, amount: uint, recipient: principal, burn-hash: (buff 32), burn-height: uint, sweep-txid: (buff 32)}) (helper-response (response uint uint))) (match helper-response index (begin (unwrap! (complete-deposit-wrapper (get txid deposit) (get vout-index deposit) (get amount deposit) (get recipient deposit) (get burn-hash deposit) (get burn-height deposit) (get sweep-txid deposit)) (err (+ ERR_DEPOSIT_INDEX_PREFIX (+ u10 index)))) (ok (+ index u1)) ) err-response (err err-response) ) )