mirror of
https://github.com/Brotocol-xyz/xlink-bitcoin-public.git
synced 2026-01-12 22:25:09 +08:00
initial commit
This commit is contained in:
98
LICENSE
Normal file
98
LICENSE
Normal file
@@ -0,0 +1,98 @@
|
||||
Business Source License 1.1
|
||||
|
||||
License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
|
||||
"Business Source License" is a trademark of MariaDB Corporation Ab.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Parameters
|
||||
|
||||
Licensor: ALEXGO Pte. Ltd.
|
||||
|
||||
Licensed Work: bitcoin-bridge
|
||||
The Licensed Work is (c) 2024 ALEXGO Pte. Ltd.
|
||||
|
||||
Additional Use Grant: None
|
||||
|
||||
Change Date: 2028-01-01
|
||||
|
||||
Change License: MIT License
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Terms
|
||||
|
||||
The Licensor hereby grants you the right to copy, modify, create derivative
|
||||
works, redistribute, and make non-production use of the Licensed Work. The
|
||||
Licensor may make an Additional Use Grant, above, permitting limited
|
||||
production use.
|
||||
|
||||
Effective on the Change Date, or the fourth anniversary of the first publicly
|
||||
available distribution of a specific version of the Licensed Work under this
|
||||
License, whichever comes first, the Licensor hereby grants you rights under
|
||||
the terms of the Change License, and the rights granted in the paragraph
|
||||
above terminate.
|
||||
|
||||
If your use of the Licensed Work does not comply with the requirements
|
||||
currently in effect as described in this License, you must purchase a
|
||||
commercial license from the Licensor, its affiliated entities, or authorized
|
||||
resellers, or you must refrain from using the Licensed Work.
|
||||
|
||||
All copies of the original and modified Licensed Work, and derivative works
|
||||
of the Licensed Work, are subject to this License. This License applies
|
||||
separately for each version of the Licensed Work and the Change Date may vary
|
||||
for each version of the Licensed Work released by Licensor.
|
||||
|
||||
You must conspicuously display this License on each original or modified copy
|
||||
of the Licensed Work. If you receive the Licensed Work in original or
|
||||
modified form from a third party, the terms and conditions set forth in this
|
||||
License apply to your use of that work.
|
||||
|
||||
Any use of the Licensed Work in violation of this License will automatically
|
||||
terminate your rights under this License for the current and all other
|
||||
versions of the Licensed Work.
|
||||
|
||||
This License does not grant you any right in any trademark or logo of
|
||||
Licensor or its affiliates (provided that you may use a trademark or logo of
|
||||
Licensor as expressly required by this License).
|
||||
|
||||
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
||||
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
||||
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
||||
TITLE.
|
||||
|
||||
MariaDB hereby grants you permission to use this License’s text to license
|
||||
your works, and to refer to it using the trademark "Business Source License",
|
||||
as long as you comply with the Covenants of Licensor below.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Covenants of Licensor
|
||||
|
||||
In consideration of the right to use this License’s text and the "Business
|
||||
Source License" name and trademark, Licensor covenants to MariaDB, and to all
|
||||
other recipients of the licensed work to be provided by Licensor:
|
||||
|
||||
1. To specify as the Change License the GPL Version 2.0 or any later version,
|
||||
or a license that is compatible with GPL Version 2.0 or a later version,
|
||||
where "compatible" means that software provided under the Change License can
|
||||
be included in a program with software provided under GPL Version 2.0 or a
|
||||
later version. Licensor may specify additional Change Licenses without
|
||||
limitation.
|
||||
|
||||
2. To either: (a) specify an additional grant of rights to use that does not
|
||||
impose any additional restriction on the right granted in this License, as
|
||||
the Additional Use Grant; or (b) insert the text "None".
|
||||
|
||||
3. To specify a Change Date.
|
||||
|
||||
4. Not to modify this License in any other way.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Notice
|
||||
|
||||
The Business Source License (this document, or the "License") is not an Open
|
||||
Source license. However, the Licensed Work will eventually be made available
|
||||
under an Open Source License, as stated in this License.
|
||||
318
contracts/brc20-bridge-endpoint-v1-07.clar
Normal file
318
contracts/brc20-bridge-endpoint-v1-07.clar
Normal file
@@ -0,0 +1,318 @@
|
||||
(use-trait sip010-trait .trait-sip-010.sip-010-trait)
|
||||
|
||||
(define-constant err-unauthorised (err u1000))
|
||||
(define-constant err-paused (err u1001))
|
||||
(define-constant err-peg-in-address-not-found (err u1002))
|
||||
(define-constant err-invalid-amount (err u1003))
|
||||
(define-constant err-token-mismatch (err u1004))
|
||||
(define-constant err-invalid-tx (err u1005))
|
||||
(define-constant err-already-sent (err u1006))
|
||||
(define-constant err-address-mismatch (err u1007))
|
||||
(define-constant err-request-already-revoked (err u1008))
|
||||
(define-constant err-request-already-finalized (err u1009))
|
||||
(define-constant err-revoke-grace-period (err u1010))
|
||||
(define-constant err-request-already-claimed (err u1011))
|
||||
(define-constant err-invalid-input (err u1012))
|
||||
(define-constant err-tx-mined-before-request (err u1013))
|
||||
|
||||
(define-constant MAX_UINT u340282366920938463463374607431768211455)
|
||||
(define-constant ONE_8 u100000000)
|
||||
|
||||
(define-data-var contract-owner principal tx-sender)
|
||||
(define-data-var fee-address principal tx-sender)
|
||||
|
||||
;; governance functions
|
||||
|
||||
(define-public (set-contract-owner (new-contract-owner principal))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set contract-owner new-contract-owner))))
|
||||
|
||||
(define-public (set-fee-address (new-fee-address principal))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set fee-address new-fee-address))))
|
||||
|
||||
;; read-only functions
|
||||
|
||||
(define-read-only (get-request-revoke-grace-period)
|
||||
(contract-call? .brc20-bridge-registry-v1-02 get-request-revoke-grace-period))
|
||||
|
||||
(define-read-only (get-request-claim-grace-period)
|
||||
(contract-call? .brc20-bridge-registry-v1-02 get-request-claim-grace-period))
|
||||
|
||||
(define-read-only (is-peg-in-address-approved (address (buff 128)))
|
||||
(contract-call? .brc20-bridge-registry-v1-02 is-peg-in-address-approved address))
|
||||
|
||||
(define-read-only (get-token-to-tick-or-fail (token principal))
|
||||
(contract-call? .brc20-bridge-registry-v1-02 get-token-to-tick-or-fail token))
|
||||
|
||||
(define-read-only (get-token-details-or-fail (tick (string-utf8 4)))
|
||||
(contract-call? .brc20-bridge-registry-v1-02 get-token-details-or-fail tick))
|
||||
|
||||
(define-read-only (get-token-details-or-fail-by-address (token principal))
|
||||
(contract-call? .brc20-bridge-registry-v1-02 get-token-details-or-fail-by-address token))
|
||||
|
||||
(define-read-only (is-approved-token (tick (string-utf8 4)))
|
||||
(contract-call? .brc20-bridge-registry-v1-02 is-approved-token tick))
|
||||
|
||||
(define-read-only (get-request-or-fail (request-id uint))
|
||||
(contract-call? .brc20-bridge-registry-v1-02 get-request-or-fail request-id))
|
||||
|
||||
(define-read-only (create-order-or-fail (order { user: principal, dest: uint }))
|
||||
(ok (unwrap! (to-consensus-buff? order) err-invalid-input)))
|
||||
|
||||
(define-read-only (decode-order-or-fail (order-script (buff 128)))
|
||||
(ok (unwrap! (from-consensus-buff? { user: principal, dest: uint } (unwrap-panic (slice? order-script u2 (len order-script)))) err-invalid-input)))
|
||||
|
||||
(define-read-only (get-peg-in-sent-or-default (bitcoin-tx (buff 8192)) (output uint) (offset uint))
|
||||
(contract-call? .brc20-bridge-registry-v1-02 get-peg-in-sent-or-default bitcoin-tx output offset))
|
||||
|
||||
(define-read-only (get-fee-address)
|
||||
(var-get fee-address))
|
||||
|
||||
(define-read-only (extract-tx-ins-outs (tx (buff 8192)))
|
||||
(if (try! (contract-call? .clarity-bitcoin-v1-05 is-segwit-tx tx))
|
||||
(let
|
||||
(
|
||||
(parsed-tx (unwrap! (contract-call? .clarity-bitcoin-v1-05 parse-wtx tx) err-invalid-tx))
|
||||
)
|
||||
(ok { ins: (get ins parsed-tx), outs: (get outs parsed-tx) })
|
||||
)
|
||||
(let
|
||||
(
|
||||
(parsed-tx (unwrap! (contract-call? .clarity-bitcoin-v1-05 parse-tx tx) err-invalid-tx))
|
||||
)
|
||||
(ok { ins: (get ins parsed-tx), outs: (get outs parsed-tx) })
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; validate-tx
|
||||
;;
|
||||
;; given the inputs,
|
||||
;; (1) confirm the tx is indexed (by Bitcoin Oracle),
|
||||
;; (2) the tx has not yet been processed,
|
||||
;; (3) the peg-in address in the tx is one of the approved / correct addresses to receive BRC20 tokens
|
||||
(define-read-only (validate-tx (tx (buff 8192)) (output-idx uint) (offset-idx uint) (order-idx uint) (token principal))
|
||||
(let (
|
||||
(tx-idxed (try! (contract-call? .oracle-v1-06 get-bitcoin-tx-indexed-or-fail tx output-idx offset-idx)))
|
||||
(parsed-tx (try! (extract-tx-ins-outs tx)))
|
||||
(order-script (get scriptPubKey (unwrap-panic (element-at? (get outs parsed-tx) order-idx))))
|
||||
(order-details (try! (decode-order-or-fail order-script)))
|
||||
(token-details (try! (get-token-details-or-fail (get tick tx-idxed))))
|
||||
(amt-in-fixed (decimals-to-fixed (get amt tx-idxed) (contract-call? .oracle-v1-06 get-tick-decimals-or-default (get tick tx-idxed))))
|
||||
(fee (mul-down amt-in-fixed (get peg-in-fee token-details)))
|
||||
(amt-net (- amt-in-fixed fee)))
|
||||
(asserts! (is-eq token (get token token-details)) err-token-mismatch)
|
||||
(asserts! (not (get-peg-in-sent-or-default tx output-idx offset-idx)) err-already-sent)
|
||||
(asserts! (is-peg-in-address-approved (get to tx-idxed)) err-peg-in-address-not-found)
|
||||
|
||||
(ok { order-details: order-details, fee: fee, amt-net: amt-net, tx-idxed: tx-idxed, token-details: token-details })
|
||||
)
|
||||
)
|
||||
|
||||
;; public functions
|
||||
|
||||
;; pegs in `tick` of `amt` (net of fee) from Bitcoin to Stacks.
|
||||
;; the relevant tx must (1) have been indexed and (2) include OP_RETURN with Stacks address (see `create-order-or-fail`)
|
||||
;;
|
||||
;; tx => bitcoin tx hash of peg-in transfer
|
||||
;; order-idx => index of OP_RETURN
|
||||
;; token-trait => trait of pegged-in token
|
||||
|
||||
(define-public (finalize-peg-in-on-index
|
||||
(tx { bitcoin-tx: (buff 8192), output: uint, offset: uint, tick: (string-utf8 4), amt: uint, from: (buff 128), to: (buff 128), from-bal: uint, to-bal: uint, decimals: uint })
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(signature-packs (list 10 { signer: principal, tx-hash: (buff 32), signature: (buff 65) }))
|
||||
(order-idx uint) (token-trait <sip010-trait>))
|
||||
(begin
|
||||
(try! (index-tx tx block proof signature-packs))
|
||||
(finalize-peg-in (get bitcoin-tx tx) (get output tx) (get offset tx) order-idx token-trait)))
|
||||
|
||||
(define-public (finalize-peg-in (tx (buff 8192)) (output-idx uint) (offset-idx uint) (order-idx uint) (token-trait <sip010-trait>))
|
||||
(let (
|
||||
(token (contract-of token-trait))
|
||||
(validation-data (try! (validate-tx tx output-idx offset-idx order-idx token)))
|
||||
(tx-idxed (get tx-idxed validation-data))
|
||||
(order-details (get order-details validation-data))
|
||||
(order-address (get user order-details))
|
||||
(dest (get dest order-details))
|
||||
(token-details (get token-details validation-data))
|
||||
(fee (get fee validation-data))
|
||||
(amt-net (get amt-net validation-data)))
|
||||
(asserts! (not (get peg-in-paused token-details)) err-paused)
|
||||
|
||||
(as-contract (try! (contract-call? .brc20-bridge-registry-v1-02 set-peg-in-sent { tx: tx, output: output-idx, offset: offset-idx } true)))
|
||||
(and (> fee u0) (as-contract (try! (contract-call? token-trait mint-fixed fee (var-get fee-address)))))
|
||||
|
||||
;; map cannot hold traits, so the below have to be hard-coded.
|
||||
;; mint to order-address if either dest == 0 or order-address is not registered with b20, or token is not registered with b20
|
||||
(if (or (is-eq dest u0) (is-err (contract-call? .stxdx-registry get-user-id-or-fail order-address)) (is-none (contract-call? .stxdx-registry get-asset-id token)))
|
||||
(begin
|
||||
(and (> amt-net u0) (as-contract (try! (contract-call? token-trait mint-fixed amt-net order-address))))
|
||||
(print (merge tx-idxed { type: "peg-in", order-address: order-address, fee: fee, amt-net: amt-net, dest: u0, bitcoin-tx: tx, output-idx: output-idx, offset-idx: offset-idx, order-idx: order-idx }))
|
||||
)
|
||||
(begin
|
||||
(and (> amt-net u0) (as-contract (try! (contract-call? token-trait mint-fixed amt-net tx-sender))))
|
||||
(and (> amt-net u0) (as-contract (try! (contract-call? .stxdx-wallet-zero transfer-in
|
||||
amt-net
|
||||
(try! (contract-call? .stxdx-registry get-user-id-or-fail order-address)) ;; user-id
|
||||
(unwrap-panic (contract-call? .stxdx-registry get-asset-id token)) ;; asset-id
|
||||
token-trait))))
|
||||
(print (merge tx-idxed { type: "peg-in", order-address: order-address, fee: fee, amt-net: amt-net, dest: u1, bitcoin-tx: tx, output-idx: output-idx, offset-idx: offset-idx, order-idx: order-idx }))
|
||||
)
|
||||
)
|
||||
(ok true)))
|
||||
|
||||
;; request peg-out of `tick` of `amount` (net of fee) to `peg-out-address`
|
||||
;; request escrows the relevant pegged-in token and gas-fee token to the contract until the request is either finalized or revoked.
|
||||
;;
|
||||
;; token-trait => the trait of pegged-in token
|
||||
(define-public (request-peg-out (tick (string-utf8 4)) (amount uint) (peg-out-address (buff 128)) (token-trait <sip010-trait>))
|
||||
(let (
|
||||
(token (contract-of token-trait))
|
||||
(token-details (try! (get-token-details-or-fail tick)))
|
||||
(fee (mul-down amount (get peg-out-fee token-details)))
|
||||
(amount-net (- amount fee))
|
||||
(gas-fee (get peg-out-gas-fee token-details))
|
||||
(request-details { requested-by: tx-sender, peg-out-address: peg-out-address, tick: tick, amount-net: amount-net, fee: fee, gas-fee: gas-fee, claimed: u0, claimed-by: tx-sender, fulfilled-by: 0x, revoked: false, finalized: false, requested-at: block-height, requested-at-burn-height: burn-block-height })
|
||||
(request-id (as-contract (try! (contract-call? .brc20-bridge-registry-v1-02 set-request u0 request-details)))))
|
||||
(asserts! (not (get peg-out-paused token-details)) err-paused)
|
||||
(asserts! (is-eq token (get token token-details)) err-token-mismatch)
|
||||
(asserts! (> amount u0) err-invalid-amount)
|
||||
|
||||
(try! (contract-call? token-trait transfer-fixed amount tx-sender (as-contract tx-sender) none))
|
||||
(and (> gas-fee u0) (try! (contract-call? .token-susdt transfer-fixed gas-fee tx-sender (as-contract tx-sender) none)))
|
||||
|
||||
(print (merge request-details { type: "request-peg-out", request-id: request-id }))
|
||||
(ok true)))
|
||||
|
||||
;; claim peg-out request, so that the claimer can safely process the peg-out (within the grace period)
|
||||
;;
|
||||
(define-public (claim-peg-out (request-id uint) (fulfilled-by (buff 128)))
|
||||
(let (
|
||||
(claimer tx-sender)
|
||||
(request-details (try! (get-request-or-fail request-id)))
|
||||
(token-details (try! (get-token-details-or-fail (get tick request-details)))))
|
||||
(asserts! (not (get peg-out-paused token-details)) err-paused)
|
||||
(asserts! (< (get claimed request-details) block-height) err-request-already-claimed)
|
||||
(asserts! (not (get revoked request-details)) err-request-already-revoked)
|
||||
(asserts! (not (get finalized request-details)) err-request-already-finalized)
|
||||
|
||||
(as-contract (try! (contract-call? .brc20-bridge-registry-v1-02 set-request request-id (merge request-details { claimed: (+ block-height (get-request-claim-grace-period)), claimed-by: claimer, fulfilled-by: fulfilled-by }))))
|
||||
|
||||
(print (merge request-details { type: "claim-peg-out", request-id: request-id, claimed: (+ block-height (get-request-claim-grace-period)), claimed-by: claimer, fulfilled-by: fulfilled-by }))
|
||||
(ok true)
|
||||
)
|
||||
)
|
||||
|
||||
;; finalize peg-out request
|
||||
;; finalize `request-id` with `tx`
|
||||
;; pays the fee to `fee-address` and burn the relevant pegged-in tokens.
|
||||
;;
|
||||
;; peg-out finalization can be done by either a peg-in address or a non-peg-in (i.e. 3rd party) address
|
||||
;; if the latter, then the overall peg-in balance does not change.
|
||||
;; the claimer sends non-pegged-in BRC20 tokens to the peg-out requester and receives the pegged-in BRC20 tokens (along with gas-fee)
|
||||
;; if the former, then the overall peg-in balance decreases.
|
||||
;; the relevant BRC20 tokens are burnt (with fees paid to `fee-address`)
|
||||
(define-public (finalize-peg-out-on-index (request-id uint)
|
||||
(tx { bitcoin-tx: (buff 8192), output: uint, offset: uint, tick: (string-utf8 4), amt: uint, from: (buff 128), to: (buff 128), from-bal: uint, to-bal: uint, decimals: uint })
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(signature-packs (list 10 { signer: principal, tx-hash: (buff 32), signature: (buff 65) }))
|
||||
(token-trait <sip010-trait>))
|
||||
(begin
|
||||
(try! (index-tx tx block proof signature-packs))
|
||||
(finalize-peg-out request-id (get bitcoin-tx tx) (get output tx) (get offset tx) token-trait)))
|
||||
|
||||
(define-public (finalize-peg-out (request-id uint) (tx (buff 8192)) (output-idx uint) (offset-idx uint) (token-trait <sip010-trait>))
|
||||
(let (
|
||||
(token (contract-of token-trait))
|
||||
(request-details (try! (get-request-or-fail request-id)))
|
||||
(token-details (try! (get-token-details-or-fail (get tick request-details))))
|
||||
(tx-idxed (try! (contract-call? .oracle-v1-06 get-bitcoin-tx-indexed-or-fail tx output-idx offset-idx)))
|
||||
(tx-mined-height (try! (contract-call? .oracle-v1-06 get-bitcoin-tx-mined-or-fail tx)))
|
||||
(amount-in-fixed (decimals-to-fixed (get amt tx-idxed) (contract-call? .oracle-v1-06 get-tick-decimals-or-default (get tick tx-idxed))))
|
||||
(fulfilled-by (get from tx-idxed))
|
||||
(is-fulfilled-by-peg-in (is-peg-in-address-approved fulfilled-by))
|
||||
)
|
||||
(asserts! (not (get peg-out-paused token-details)) err-paused)
|
||||
(asserts! (is-eq token (get token token-details)) err-token-mismatch)
|
||||
(asserts! (is-eq (get tick request-details) (get tick tx-idxed)) err-token-mismatch)
|
||||
(asserts! (is-eq (get amount-net request-details) amount-in-fixed) err-invalid-amount)
|
||||
(asserts! (is-eq (get peg-out-address request-details) (get to tx-idxed)) err-address-mismatch)
|
||||
(asserts! (is-eq (get fulfilled-by request-details) fulfilled-by) err-address-mismatch)
|
||||
(asserts! (< (get requested-at-burn-height request-details) tx-mined-height) err-tx-mined-before-request)
|
||||
(asserts! (not (get-peg-in-sent-or-default tx output-idx offset-idx)) err-already-sent)
|
||||
(asserts! (not (get revoked request-details)) err-request-already-revoked)
|
||||
(asserts! (not (get finalized request-details)) err-request-already-finalized)
|
||||
|
||||
(as-contract (try! (contract-call? .brc20-bridge-registry-v1-02 set-peg-in-sent { tx: tx, output: output-idx, offset: offset-idx } true)))
|
||||
(as-contract (try! (contract-call? .brc20-bridge-registry-v1-02 set-request request-id (merge request-details { finalized: true }))))
|
||||
|
||||
(and (> (get fee request-details) u0) (as-contract (try! (contract-call? token-trait transfer-fixed (get fee request-details) tx-sender (var-get fee-address) none))))
|
||||
(and (> (get gas-fee request-details) u0) (as-contract (try! (contract-call? .token-susdt transfer-fixed (get gas-fee request-details) tx-sender (if is-fulfilled-by-peg-in (var-get fee-address) (get claimed-by request-details)) none))))
|
||||
|
||||
(if is-fulfilled-by-peg-in
|
||||
(as-contract (try! (contract-call? token-trait burn-fixed (get amount-net request-details) tx-sender)))
|
||||
(as-contract (try! (contract-call? token-trait transfer-fixed (get amount-net request-details) tx-sender (get claimed-by request-details) none)))
|
||||
)
|
||||
|
||||
(print { type: "finalize-peg-out", request-id: request-id, tx: tx })
|
||||
(ok true)))
|
||||
|
||||
;; revoke peg-out request
|
||||
;; only after `request-revoke-grace-period` passed
|
||||
;; returns fee and pegged-in tokens to the requester.
|
||||
(define-public (revoke-peg-out (request-id uint) (token-trait <sip010-trait>))
|
||||
(let (
|
||||
(token (contract-of token-trait))
|
||||
(request-details (try! (get-request-or-fail request-id)))
|
||||
(token-details (try! (get-token-details-or-fail (get tick request-details)))))
|
||||
(asserts! (is-eq token (get token token-details)) err-token-mismatch)
|
||||
(asserts! (> block-height (+ (get requested-at request-details) (get-request-revoke-grace-period))) err-revoke-grace-period)
|
||||
(asserts! (< (get claimed request-details) block-height) err-request-already-claimed)
|
||||
(asserts! (not (get revoked request-details)) err-request-already-revoked)
|
||||
(asserts! (not (get finalized request-details)) err-request-already-finalized)
|
||||
|
||||
(as-contract (try! (contract-call? .brc20-bridge-registry-v1-02 set-request request-id (merge request-details { revoked: true }))))
|
||||
|
||||
(and (> (get fee request-details) u0) (as-contract (try! (contract-call? token-trait transfer-fixed (get fee request-details) tx-sender (get requested-by request-details) none))))
|
||||
(and (> (get gas-fee request-details) u0) (as-contract (try! (contract-call? .token-susdt transfer-fixed (get gas-fee request-details) tx-sender (get requested-by request-details) none))))
|
||||
(as-contract (try! (contract-call? token-trait transfer-fixed (get amount-net request-details) tx-sender (get requested-by request-details) none)))
|
||||
|
||||
(print { type: "revoke-peg-out", request-id: request-id })
|
||||
(ok true)))
|
||||
|
||||
;; internal functions
|
||||
|
||||
(define-private (index-tx
|
||||
(tx { bitcoin-tx: (buff 8192), output: uint, offset: uint, tick: (string-utf8 4), amt: uint, from: (buff 128), to: (buff 128), from-bal: uint, to-bal: uint, decimals: uint })
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(signature-packs (list 10 { signer: principal, tx-hash: (buff 32), signature: (buff 65) })))
|
||||
(begin
|
||||
(and
|
||||
(not (is-ok (contract-call? .oracle-v1-06 get-bitcoin-tx-indexed-or-fail (get bitcoin-tx tx) (get output tx) (get offset tx))))
|
||||
(as-contract (try! (contract-call? .oracle-v1-06 index-tx-many (list { tx: tx, block: block, proof: proof, signature-packs: signature-packs })))))
|
||||
(print { type: "indexed-tx", tx: tx, block: block, proof: proof, signature-packs: signature-packs })
|
||||
(ok true)))
|
||||
|
||||
(define-private (is-contract-owner)
|
||||
(ok (asserts! (is-eq (var-get contract-owner) tx-sender) err-unauthorised)))
|
||||
|
||||
(define-private (min (a uint) (b uint))
|
||||
(if (< a b) a b))
|
||||
|
||||
(define-private (mul-down (a uint) (b uint))
|
||||
(/ (* a b) ONE_8))
|
||||
|
||||
(define-private (div-down (a uint) (b uint))
|
||||
(if (is-eq a u0)
|
||||
u0
|
||||
(/ (* a ONE_8) b)))
|
||||
|
||||
(define-private (decimals-to-fixed (amount uint) (decimals uint))
|
||||
(/ (* amount ONE_8) (pow u10 decimals)))
|
||||
129
contracts/brc20-bridge-registry-v1-02.clar
Normal file
129
contracts/brc20-bridge-registry-v1-02.clar
Normal file
@@ -0,0 +1,129 @@
|
||||
(use-trait sip010-trait .trait-sip-010.sip-010-trait)
|
||||
|
||||
(define-constant err-unauthorised (err u1000))
|
||||
(define-constant err-token-not-found (err u1001))
|
||||
(define-constant err-request-not-found (err u1002))
|
||||
|
||||
(define-data-var contract-owner principal tx-sender)
|
||||
|
||||
(define-map peg-in-sent { tx: (buff 8192), output: uint, offset: uint } bool)
|
||||
|
||||
;; governance functions
|
||||
|
||||
(define-public (set-contract-owner-legacy (new-owner principal))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 set-contract-owner new-owner))))
|
||||
|
||||
(define-public (approve-operator (operator principal) (approved bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 approve-operator operator approved))))
|
||||
|
||||
(define-public (set-request-revoke-grace-period (grace-period uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 set-request-revoke-grace-period grace-period))))
|
||||
|
||||
(define-public (set-request-claim-grace-period (grace-period uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 set-request-claim-grace-period grace-period))))
|
||||
|
||||
(define-public (pause-peg-in (tick (string-utf8 4)) (paused bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 pause-peg-in tick paused))))
|
||||
|
||||
(define-public (pause-peg-out (tick (string-utf8 4)) (paused bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 pause-peg-out tick paused))))
|
||||
|
||||
(define-public (set-peg-in-fee (tick (string-utf8 4)) (new-peg-in-fee uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 set-peg-in-fee tick new-peg-in-fee))))
|
||||
|
||||
(define-public (set-peg-out-fee (tick (string-utf8 4)) (new-peg-out-fee uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 set-peg-out-fee tick new-peg-out-fee))))
|
||||
|
||||
(define-public (set-peg-out-gas-fee (tick (string-utf8 4)) (new-peg-out-gas-fee uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 set-peg-out-gas-fee tick new-peg-out-gas-fee))))
|
||||
|
||||
(define-public (approve-token (tick (string-utf8 4)) (token principal) (approved bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 approve-token tick token approved))))
|
||||
|
||||
(define-public (approve-peg-in-address (address (buff 128)) (approved bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 approve-peg-in-address address approved))))
|
||||
|
||||
(define-public (set-contract-owner (new-contract-owner principal))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set contract-owner new-contract-owner))))
|
||||
|
||||
;; read-only functions
|
||||
|
||||
(define-read-only (get-request-revoke-grace-period)
|
||||
(contract-call? .brc20-bridge-registry-v1-01 get-request-revoke-grace-period))
|
||||
|
||||
(define-read-only (get-request-claim-grace-period)
|
||||
(contract-call? .brc20-bridge-registry-v1-01 get-request-claim-grace-period))
|
||||
|
||||
(define-read-only (is-peg-in-address-approved (address (buff 128)))
|
||||
(contract-call? .brc20-bridge-registry-v1-01 is-peg-in-address-approved address))
|
||||
|
||||
(define-read-only (get-token-to-tick-or-fail (token principal))
|
||||
(contract-call? .brc20-bridge-registry-v1-01 get-token-to-tick-or-fail token))
|
||||
|
||||
(define-read-only (get-token-details-or-fail (tick (string-utf8 4)))
|
||||
(contract-call? .brc20-bridge-registry-v1-01 get-token-details-or-fail tick))
|
||||
|
||||
(define-read-only (get-token-details-or-fail-by-address (token principal))
|
||||
(contract-call? .brc20-bridge-registry-v1-01 get-token-details-or-fail-by-address token))
|
||||
|
||||
(define-read-only (is-approved-token (tick (string-utf8 4)))
|
||||
(contract-call? .brc20-bridge-registry-v1-01 is-approved-token tick))
|
||||
|
||||
(define-read-only (get-request-or-fail (request-id uint))
|
||||
(contract-call? .brc20-bridge-registry-v1-01 get-request-or-fail request-id))
|
||||
|
||||
(define-read-only (get-approved-operator-or-default (operator principal))
|
||||
(contract-call? .brc20-bridge-registry-v1-01 get-approved-operator-or-default operator))
|
||||
|
||||
(define-read-only (get-peg-in-sent-or-default (bitcoin-tx (buff 8192)) (output uint) (offset uint))
|
||||
(match (as-max-len? bitcoin-tx u4096)
|
||||
some-value
|
||||
(or
|
||||
(contract-call? .brc20-bridge-registry-v1-01 get-peg-in-sent-or-default some-value output offset)
|
||||
(default-to false (map-get? peg-in-sent { tx: bitcoin-tx, output: output, offset: offset })))
|
||||
(default-to false (map-get? peg-in-sent { tx: bitcoin-tx, output: output, offset: offset }))))
|
||||
|
||||
(define-read-only (is-approved-operator)
|
||||
(contract-call? .brc20-bridge-registry-v1-01 is-approved-operator))
|
||||
|
||||
;; priviledged functions
|
||||
|
||||
(define-public (set-peg-in-sent (peg-in-tx { tx: (buff 8192), output: uint, offset: uint }) (sent bool))
|
||||
(begin
|
||||
(try! (is-approved-operator))
|
||||
(ok (map-set peg-in-sent peg-in-tx sent))))
|
||||
|
||||
(define-public (set-request (request-id uint) (details { requested-by: principal, peg-out-address: (buff 128), tick: (string-utf8 4), amount-net: uint, fee: uint, gas-fee: uint, claimed: uint, claimed-by: principal, fulfilled-by: (buff 128), revoked: bool, finalized: bool, requested-at: uint, requested-at-burn-height: uint}))
|
||||
(begin
|
||||
(try! (is-approved-operator))
|
||||
(as-contract (contract-call? .brc20-bridge-registry-v1-01 set-request request-id details))))
|
||||
|
||||
;; internal functions
|
||||
|
||||
(define-private (is-contract-owner)
|
||||
(ok (asserts! (is-eq (var-get contract-owner) tx-sender) err-unauthorised)))
|
||||
|
||||
619
contracts/btc-bridge-endpoint-v1-10.clar
Normal file
619
contracts/btc-bridge-endpoint-v1-10.clar
Normal file
@@ -0,0 +1,619 @@
|
||||
(use-trait sip010-trait .trait-sip-010.sip-010-trait)
|
||||
|
||||
(define-constant err-unauthorised (err u1000))
|
||||
(define-constant err-paused (err u1001))
|
||||
(define-constant err-peg-in-address-not-found (err u1002))
|
||||
(define-constant err-invalid-amount (err u1003))
|
||||
(define-constant err-invalid-tx (err u1004))
|
||||
(define-constant err-already-sent (err u1005))
|
||||
(define-constant err-address-mismatch (err u1006))
|
||||
(define-constant err-request-already-revoked (err u1007))
|
||||
(define-constant err-request-already-finalized (err u1008))
|
||||
(define-constant err-revoke-grace-period (err u1009))
|
||||
(define-constant err-request-already-claimed (err u1010))
|
||||
(define-constant err-bitcoin-tx-not-mined (err u1011))
|
||||
(define-constant err-invalid-input (err u1012))
|
||||
(define-constant err-tx-mined-before-request (err u1013))
|
||||
(define-constant err-dest-mismatch (err u1014))
|
||||
(define-constant err-token-mismatch (err u1015))
|
||||
(define-constant err-slippage (err u1016))
|
||||
(define-constant err-not-in-whitelist (err u1017))
|
||||
|
||||
(define-constant MAX_UINT u340282366920938463463374607431768211455)
|
||||
(define-constant ONE_8 u100000000)
|
||||
|
||||
(define-data-var contract-owner principal tx-sender)
|
||||
(define-data-var fee-address principal tx-sender)
|
||||
|
||||
(define-data-var peg-in-paused bool true)
|
||||
(define-data-var peg-out-paused bool true)
|
||||
(define-data-var peg-in-fee uint u0)
|
||||
(define-data-var peg-in-min-fee uint u0)
|
||||
(define-data-var peg-out-fee uint u0)
|
||||
(define-data-var peg-out-min-fee uint u0)
|
||||
|
||||
(define-map use-whitelist uint bool)
|
||||
(define-map whitelisted {launch-id: uint, owner: (buff 128)} bool)
|
||||
|
||||
;; governance functions
|
||||
|
||||
(define-public (set-use-whitelist (launch-id uint) (new-whitelisted bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (map-set use-whitelist launch-id new-whitelisted))))
|
||||
|
||||
(define-public (set-whitelisted (launch-id uint) (whitelisted-users (list 200 {owner: (buff 128), whitelisted: bool})))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(fold set-whitelisted-iter whitelisted-users launch-id)
|
||||
(ok true)))
|
||||
|
||||
(define-public (set-contract-owner (new-contract-owner principal))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set contract-owner new-contract-owner))))
|
||||
|
||||
(define-public (set-fee-address (new-fee-address principal))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set fee-address new-fee-address))))
|
||||
|
||||
(define-public (pause-peg-in (paused bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set peg-in-paused paused))))
|
||||
|
||||
(define-public (pause-peg-out (paused bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set peg-out-paused paused))))
|
||||
|
||||
(define-public (set-peg-in-fee (fee uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set peg-in-fee fee))))
|
||||
|
||||
(define-public (set-peg-in-min-fee (fee uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set peg-in-min-fee fee))))
|
||||
|
||||
(define-public (set-peg-out-fee (fee uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set peg-out-fee fee))))
|
||||
|
||||
(define-public (set-peg-out-min-fee (fee uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set peg-out-min-fee fee))))
|
||||
|
||||
;; read-only functions
|
||||
|
||||
(define-read-only (is-peg-in-paused)
|
||||
(var-get peg-in-paused))
|
||||
|
||||
(define-read-only (is-peg-out-paused)
|
||||
(var-get peg-out-paused))
|
||||
|
||||
(define-read-only (get-peg-in-fee)
|
||||
(var-get peg-in-fee))
|
||||
|
||||
(define-read-only (get-peg-in-min-fee)
|
||||
(var-get peg-in-min-fee))
|
||||
|
||||
(define-read-only (get-peg-out-fee)
|
||||
(var-get peg-out-fee))
|
||||
|
||||
(define-read-only (get-peg-out-min-fee)
|
||||
(var-get peg-out-min-fee))
|
||||
|
||||
(define-read-only (get-request-revoke-grace-period)
|
||||
(contract-call? .btc-bridge-registry-v1-03 get-request-revoke-grace-period))
|
||||
|
||||
(define-read-only (get-request-claim-grace-period)
|
||||
(contract-call? .btc-bridge-registry-v1-03 get-request-claim-grace-period))
|
||||
|
||||
(define-read-only (is-peg-in-address-approved (address (buff 128)))
|
||||
(contract-call? .btc-bridge-registry-v1-03 is-peg-in-address-approved address))
|
||||
|
||||
(define-read-only (get-request-or-fail (request-id uint))
|
||||
(contract-call? .btc-bridge-registry-v1-03 get-request-or-fail request-id))
|
||||
|
||||
(define-read-only (get-peg-in-sent-or-default (tx (buff 16384)) (output uint))
|
||||
(contract-call? .btc-bridge-registry-v1-03 get-peg-in-sent-or-default tx output))
|
||||
|
||||
(define-read-only (get-fee-address)
|
||||
(var-get fee-address))
|
||||
|
||||
(define-read-only (extract-tx-ins-outs (tx (buff 16384)))
|
||||
(if (try! (contract-call? .clarity-bitcoin-v1-06 is-segwit-tx tx))
|
||||
(let (
|
||||
(parsed-tx (unwrap! (contract-call? .clarity-bitcoin-v1-06 parse-wtx tx) err-invalid-tx)))
|
||||
(ok { ins: (get ins parsed-tx), outs: (get outs parsed-tx) }))
|
||||
(let (
|
||||
(parsed-tx (unwrap! (contract-call? .clarity-bitcoin-v1-06 parse-tx tx) err-invalid-tx)))
|
||||
(ok { ins: (get ins parsed-tx), outs: (get outs parsed-tx) }))
|
||||
))
|
||||
|
||||
(define-read-only (get-txid (tx (buff 16384)))
|
||||
(if (try! (contract-call? .clarity-bitcoin-v1-06 is-segwit-tx tx))
|
||||
(ok (contract-call? .clarity-bitcoin-v1-06 get-segwit-txid tx))
|
||||
(ok (contract-call? .clarity-bitcoin-v1-06 get-txid tx))
|
||||
))
|
||||
|
||||
(define-read-only (get-use-whitelist-or-default (launch-id uint))
|
||||
(default-to false (map-get? use-whitelist launch-id)))
|
||||
|
||||
(define-read-only (get-whitelisted-or-default (launch-id uint) (owner (buff 128)))
|
||||
(if (get-use-whitelist-or-default launch-id)
|
||||
(default-to false (map-get? whitelisted {launch-id: launch-id, owner: owner}))
|
||||
true))
|
||||
|
||||
;; verify-mined
|
||||
;;
|
||||
;; it takes Bitcoin tx and confirms if the tx is mined on Bitcoin L1
|
||||
(define-read-only (verify-mined (tx (buff 16384)) (block { header: (buff 80), height: uint }) (proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint }))
|
||||
(if (is-eq chain-id u1)
|
||||
(let (
|
||||
(response (if (try! (contract-call? .clarity-bitcoin-v1-06 is-segwit-tx tx))
|
||||
(contract-call? .clarity-bitcoin-v1-06 was-segwit-tx-mined? block tx proof)
|
||||
(contract-call? .clarity-bitcoin-v1-06 was-tx-mined? block tx proof))
|
||||
))
|
||||
(if (or (is-err response) (not (unwrap-panic response)))
|
||||
err-bitcoin-tx-not-mined
|
||||
(ok true)
|
||||
))
|
||||
(ok true))) ;; if not mainnet, assume verified
|
||||
|
||||
(define-read-only (create-order-0-or-fail (order principal))
|
||||
(ok (unwrap! (to-consensus-buff? order) err-invalid-input)))
|
||||
|
||||
(define-read-only (decode-order-0-or-fail (order-script (buff 128)))
|
||||
(let (
|
||||
(op-code (unwrap-panic (slice? order-script u1 u2))))
|
||||
(ok (unwrap! (from-consensus-buff? principal (unwrap-panic (slice? order-script (if (< op-code 0x4c) u2 u3) (len order-script)))) err-invalid-input))))
|
||||
|
||||
(define-read-only (validate-tx-0 (tx (buff 16384)) (output-idx uint) (order-idx uint))
|
||||
(let (
|
||||
(validation-data (try! (validate-tx-common tx output-idx order-idx))))
|
||||
(ok { order-details: (try! (decode-order-0-or-fail (get order-script validation-data))), fee: (get fee validation-data), amount-net: (get amount-net validation-data) })))
|
||||
|
||||
(define-read-only (create-order-1-or-fail (order { user: principal, pool-id: uint, min-dy: uint }))
|
||||
(ok (unwrap! (to-consensus-buff? { u: (get user order), p: (int-to-ascii (get pool-id order)), y: (int-to-ascii (get min-dy order)) }) err-invalid-input)))
|
||||
|
||||
(define-read-only (decode-order-1-or-fail (order-script (buff 128)))
|
||||
(let (
|
||||
(op-code (unwrap-panic (slice? order-script u1 u2)))
|
||||
(offset (if (< op-code 0x4c) u2 u3))
|
||||
(raw-order (unwrap! (from-consensus-buff? { u: principal, p: (string-ascii 40), y: (string-ascii 40) } (unwrap-panic (slice? order-script offset (len order-script)))) err-invalid-input))
|
||||
(pool-id (unwrap! (string-to-uint? (get p raw-order)) err-invalid-input))
|
||||
(min-dy (unwrap! (string-to-uint? (get y raw-order)) err-invalid-input)))
|
||||
(ok { user: (get u raw-order), pool-id: pool-id, min-dy: min-dy })))
|
||||
|
||||
(define-read-only (validate-tx-1 (tx (buff 16384)) (output-idx uint) (order-idx uint) (token principal))
|
||||
(validate-tx-1-extra (try! (validate-tx-1-base tx output-idx order-idx)) token))
|
||||
|
||||
(define-read-only (create-order-2-or-fail (order { user: principal, pool1-id: uint, pool2-id: uint, min-dz: uint }))
|
||||
(ok (unwrap! (to-consensus-buff? { u: (get user order), p1: (int-to-ascii (get pool1-id order)), p2: (int-to-ascii (get pool2-id order)), z: (int-to-ascii (get min-dz order)) }) err-invalid-input)))
|
||||
|
||||
(define-read-only (decode-order-2-or-fail (order-script (buff 128)))
|
||||
(let (
|
||||
(op-code (unwrap-panic (slice? order-script u1 u2)))
|
||||
(offset (if (< op-code 0x4c) u2 u3))
|
||||
(raw-order (unwrap! (from-consensus-buff? { u: principal, p1: (string-ascii 40), p2: (string-ascii 40), z: (string-ascii 40) } (unwrap-panic (slice? order-script offset (len order-script)))) err-invalid-input))
|
||||
(pool1-id (unwrap! (string-to-uint? (get p1 raw-order)) err-invalid-input))
|
||||
(pool2-id (unwrap! (string-to-uint? (get p2 raw-order)) err-invalid-input))
|
||||
(min-dz (unwrap! (string-to-uint? (get z raw-order)) err-invalid-input)))
|
||||
(ok { user: (get u raw-order), pool1-id: pool1-id, pool2-id: pool2-id, min-dz: min-dz })))
|
||||
|
||||
(define-read-only (validate-tx-2 (tx (buff 16384)) (output-idx uint) (order-idx uint) (token1 principal) (token2 principal))
|
||||
(validate-tx-2-extra (try! (validate-tx-2-base tx output-idx order-idx)) token1 token2))
|
||||
|
||||
(define-read-only (create-order-3-or-fail (order { user: principal, pool1-id: uint, pool2-id: uint, pool3-id: uint, min-dw: uint }))
|
||||
(ok (unwrap! (to-consensus-buff? { u: (get user order), p1: (int-to-ascii (get pool1-id order)), p2: (int-to-ascii (get pool2-id order)), p3: (int-to-ascii (get pool3-id order)), w: (int-to-ascii (get min-dw order)) }) err-invalid-input)))
|
||||
|
||||
(define-read-only (decode-order-3-or-fail (order-script (buff 128)))
|
||||
(let (
|
||||
(op-code (unwrap-panic (slice? order-script u1 u2)))
|
||||
(offset (if (< op-code 0x4c) u2 u3))
|
||||
(raw-order (unwrap! (from-consensus-buff? { u: principal, p1: (string-ascii 40), p2: (string-ascii 40), p3: (string-ascii 40), w: (string-ascii 40) } (unwrap-panic (slice? order-script offset (len order-script)))) err-invalid-input))
|
||||
(pool1-id (unwrap! (string-to-uint? (get p1 raw-order)) err-invalid-input))
|
||||
(pool2-id (unwrap! (string-to-uint? (get p2 raw-order)) err-invalid-input))
|
||||
(pool3-id (unwrap! (string-to-uint? (get p3 raw-order)) err-invalid-input))
|
||||
(min-dw (unwrap! (string-to-uint? (get w raw-order)) err-invalid-input)))
|
||||
(ok { user: (get u raw-order), pool1-id: pool1-id, pool2-id: pool2-id, pool3-id: pool3-id, min-dw: min-dw })))
|
||||
|
||||
(define-read-only (validate-tx-3 (tx (buff 16384)) (output-idx uint) (order-idx uint) (token1 principal) (token2 principal) (token3 principal))
|
||||
(validate-tx-3-extra (try! (validate-tx-3-base tx output-idx order-idx)) token1 token2 token3))
|
||||
|
||||
(define-read-only (create-order-launchpad-or-fail (order { user: principal, launch-id: uint }))
|
||||
(ok (unwrap! (to-consensus-buff? { u: (get user order), l: (int-to-ascii (get launch-id order)) }) err-invalid-input)))
|
||||
|
||||
(define-read-only (decode-order-launchpad-or-fail (order-script (buff 128)))
|
||||
(let (
|
||||
(op-code (unwrap-panic (slice? order-script u1 u2)))
|
||||
(offset (if (< op-code 0x4c) u2 u3))
|
||||
(raw-order (unwrap! (from-consensus-buff? { u: principal, l: (string-ascii 40) } (unwrap-panic (slice? order-script offset (len order-script)))) err-invalid-input))
|
||||
(launch-id (unwrap! (string-to-uint? (get l raw-order)) err-invalid-input)))
|
||||
(ok { user: (get u raw-order), launch-id: launch-id })))
|
||||
|
||||
(define-read-only (validate-tx-launchpad (tx (buff 16384)) (output-idx uint) (order-idx uint) (owner-idx uint))
|
||||
(validate-tx-launchpad-extra (try! (validate-tx-launchpad-base tx output-idx order-idx owner-idx))))
|
||||
|
||||
;; public functions
|
||||
|
||||
;; pegs in BTC (net of fee) from Bitcoin to Stacks.
|
||||
;; the relevant tx include OP_RETURN with Stacks address (see `create-order-or-fail`)
|
||||
;;
|
||||
;; tx => bitcoin tx hash of peg-in transfer
|
||||
;; order-idx => index of OP_RETURN
|
||||
|
||||
(define-public (finalize-peg-in-0
|
||||
(tx (buff 16384))
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(output-idx uint) (order-idx uint))
|
||||
(let (
|
||||
(common-check (try! (finalize-peg-in-common tx block proof output-idx order-idx)))
|
||||
(validation-data (try! (validate-tx-0 tx output-idx order-idx)))
|
||||
(order-details (get order-details validation-data))
|
||||
(amount-net (get amount-net validation-data))
|
||||
(fee (get fee validation-data)))
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-peg-in-sent tx output-idx true)))
|
||||
(and (> fee u0) (as-contract (try! (contract-call? .token-abtc mint-fixed fee (var-get fee-address)))))
|
||||
(as-contract (try! (contract-call? .token-abtc mint-fixed amount-net order-details)))
|
||||
(print { type: "peg-in", tx-id: (try! (get-txid tx)), output: output-idx, order-details: order-details, fee: fee, amount-net: amount-net })
|
||||
(ok true)))
|
||||
|
||||
(define-public (finalize-peg-in-1
|
||||
(tx (buff 16384))
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(output-idx uint) (order-idx uint)
|
||||
(token-trait <sip010-trait>))
|
||||
(let (
|
||||
(common-check (try! (finalize-peg-in-common tx block proof output-idx order-idx)))
|
||||
(validation-data (try! (validate-tx-1-base tx output-idx order-idx)))
|
||||
(order-details (get order-details validation-data))
|
||||
(amount-net (get amount-net validation-data))
|
||||
(fee (get fee validation-data))
|
||||
(minted (as-contract (try! (contract-call? .token-abtc mint-fixed amount-net tx-sender)))))
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-peg-in-sent tx output-idx true)))
|
||||
(and (> fee u0) (as-contract (try! (contract-call? .token-abtc mint-fixed fee (var-get fee-address)))))
|
||||
(print { type: "peg-in", tx-id: (try! (get-txid tx)), output: output-idx, order-details: order-details, fee: fee, amount-net: amount-net })
|
||||
(match (validate-tx-1-extra validation-data (contract-of token-trait))
|
||||
extra-details
|
||||
(let (
|
||||
(swapped (as-contract (try! (contract-call? .amm-swap-pool-v1-1 swap-helper .token-abtc token-trait (get factor extra-details) amount-net (some (get min-dy order-details)))))))
|
||||
(as-contract (try! (contract-call? token-trait transfer-fixed swapped tx-sender (get user order-details) none)))
|
||||
(ok true)
|
||||
)
|
||||
err-value
|
||||
(begin
|
||||
(as-contract (try! (contract-call? .token-abtc transfer-fixed amount-net tx-sender (get user order-details) none)))
|
||||
(ok false)
|
||||
)
|
||||
)))
|
||||
|
||||
(define-public (finalize-peg-in-2
|
||||
(tx (buff 16384))
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(output-idx uint) (order-idx uint)
|
||||
(token1-trait <sip010-trait>) (token2-trait <sip010-trait>))
|
||||
(let (
|
||||
(common-check (try! (finalize-peg-in-common tx block proof output-idx order-idx)))
|
||||
(validation-data (try! (validate-tx-2-base tx output-idx order-idx)))
|
||||
(order-details (get order-details validation-data))
|
||||
(amount-net (get amount-net validation-data))
|
||||
(fee (get fee validation-data))
|
||||
(minted (as-contract (try! (contract-call? .token-abtc mint-fixed amount-net tx-sender)))))
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-peg-in-sent tx output-idx true)))
|
||||
(and (> fee u0) (as-contract (try! (contract-call? .token-abtc mint-fixed fee (var-get fee-address)))))
|
||||
(print { type: "peg-in", tx-id: (try! (get-txid tx)), output: output-idx, order-details: order-details, fee: fee, amount-net: amount-net })
|
||||
(match (validate-tx-2-extra validation-data (contract-of token1-trait) (contract-of token2-trait))
|
||||
extra-details
|
||||
(let (
|
||||
(swapped (as-contract (try! (contract-call? .amm-swap-pool-v1-1 swap-helper-a .token-abtc token1-trait token2-trait (get factor1 extra-details) (get factor2 extra-details) amount-net (some (get min-dz order-details)))))))
|
||||
(as-contract (try! (contract-call? token2-trait transfer-fixed swapped tx-sender (get user order-details) none)))
|
||||
(ok true)
|
||||
)
|
||||
err-value
|
||||
(begin
|
||||
(as-contract (try! (contract-call? .token-abtc transfer-fixed amount-net tx-sender (get user order-details) none)))
|
||||
(ok false)
|
||||
)
|
||||
)))
|
||||
|
||||
(define-public (finalize-peg-in-3
|
||||
(tx (buff 16384))
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(output-idx uint) (order-idx uint)
|
||||
(token1-trait <sip010-trait>) (token2-trait <sip010-trait>) (token3-trait <sip010-trait>))
|
||||
(let (
|
||||
(common-check (try! (finalize-peg-in-common tx block proof output-idx order-idx)))
|
||||
(validation-data (try! (validate-tx-3-base tx output-idx order-idx)))
|
||||
(order-details (get order-details validation-data))
|
||||
(amount-net (get amount-net validation-data))
|
||||
(fee (get fee validation-data))
|
||||
(minted (as-contract (try! (contract-call? .token-abtc mint-fixed amount-net tx-sender)))))
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-peg-in-sent tx output-idx true)))
|
||||
(and (> fee u0) (as-contract (try! (contract-call? .token-abtc mint-fixed fee (var-get fee-address)))))
|
||||
(print { type: "peg-in", tx-id: (try! (get-txid tx)), output: output-idx, order-details: order-details, fee: fee, amount-net: amount-net })
|
||||
(match (validate-tx-3-extra validation-data (contract-of token1-trait) (contract-of token2-trait) (contract-of token3-trait))
|
||||
extra-details
|
||||
(let (
|
||||
(swapped (as-contract (try! (contract-call? .amm-swap-pool-v1-1 swap-helper-b .token-abtc token1-trait token2-trait token3-trait (get factor1 extra-details) (get factor2 extra-details) (get factor3 extra-details) amount-net (some (get min-dw order-details)))))))
|
||||
(as-contract (try! (contract-call? token3-trait transfer-fixed swapped tx-sender (get user order-details) none)))
|
||||
(ok true)
|
||||
)
|
||||
err-value
|
||||
(begin
|
||||
(as-contract (try! (contract-call? .token-abtc transfer-fixed amount-net tx-sender (get user order-details) none)))
|
||||
(ok false)
|
||||
)
|
||||
)))
|
||||
|
||||
(define-public (finalize-peg-in-launchpad
|
||||
(tx (buff 16384))
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(output-idx uint) (order-idx uint) (owner-idx uint))
|
||||
(let (
|
||||
(common-check (try! (finalize-peg-in-common tx block proof output-idx order-idx)))
|
||||
(validation-data (try! (validate-tx-launchpad-base tx output-idx order-idx owner-idx)))
|
||||
(order-details (get order-details validation-data))
|
||||
(amount-net (get amount-net validation-data))
|
||||
(fee (get fee validation-data)))
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-peg-in-sent tx output-idx true)))
|
||||
(and (> fee u0) (as-contract (try! (contract-call? .token-abtc mint-fixed fee (var-get fee-address)))))
|
||||
(as-contract (try! (contract-call? .token-abtc mint-fixed amount-net tx-sender)))
|
||||
(print { type: "peg-in", tx-id: (try! (get-txid tx)), output: output-idx, order-details: order-details, fee: fee, amount-net: amount-net })
|
||||
(if (is-ok (validate-tx-launchpad-extra validation-data))
|
||||
(let (
|
||||
(bounds (as-contract (try! (contract-call? .alex-launchpad-v1-7 register-on-behalf (get user order-details) (get launch-id order-details) amount-net .token-abtc)))))
|
||||
(map-set whitelisted { launch-id: (get launch-id order-details), owner: (get owner-script validation-data) } false)
|
||||
(ok bounds)
|
||||
)
|
||||
(begin
|
||||
(as-contract (try! (contract-call? .token-abtc transfer-fixed amount-net tx-sender (get user order-details) none)))
|
||||
(ok { start: u0, end: u0 })
|
||||
)
|
||||
)))
|
||||
|
||||
;; request peg-out of aBTC (net of fee) to `peg-out-address`
|
||||
;; request escrows the relevant aBTC and gas-fee token to the contract until the request is either finalized or revoked.
|
||||
;;
|
||||
(define-public (request-peg-out-0 (peg-out-address (buff 128)) (amount uint))
|
||||
(let (
|
||||
(gas-fee (var-get peg-out-min-fee))
|
||||
(fee (- (max (mul-down amount (var-get peg-out-fee)) gas-fee) gas-fee))
|
||||
(check-amount (asserts! (> amount (+ fee gas-fee)) err-invalid-amount))
|
||||
(amount-net (- amount fee gas-fee))
|
||||
(request-details { requested-by: tx-sender, peg-out-address: peg-out-address, amount-net: amount-net, fee: fee, gas-fee: gas-fee, claimed: u0, claimed-by: tx-sender, fulfilled-by: 0x, revoked: false, finalized: false, requested-at: block-height, requested-at-burn-height: burn-block-height })
|
||||
(request-id (as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-request u0 request-details)))))
|
||||
(asserts! (not (var-get peg-out-paused)) err-paused)
|
||||
|
||||
(try! (contract-call? .token-abtc transfer-fixed amount tx-sender (as-contract tx-sender) none))
|
||||
(print (merge request-details { type: "request-peg-out", request-id: request-id }))
|
||||
(ok request-id)))
|
||||
|
||||
(define-public (request-peg-out-1 (peg-out-address (buff 128)) (token-trait <sip010-trait>) (factor uint) (dx uint) (min-dy (optional uint)))
|
||||
(let (
|
||||
(swapped (try! (contract-call? .amm-swap-pool-v1-1 swap-helper token-trait .token-abtc factor dx min-dy))))
|
||||
(request-peg-out-0 peg-out-address swapped)))
|
||||
|
||||
(define-public (request-peg-out-2 (peg-out-address (buff 128)) (token1-trait <sip010-trait>) (token2-trait <sip010-trait>) (factor1 uint) (factor2 uint) (dx uint) (min-dz (optional uint)))
|
||||
(let (
|
||||
(swapped (try! (contract-call? .amm-swap-pool-v1-1 swap-helper-a token1-trait token2-trait .token-abtc factor1 factor2 dx min-dz))))
|
||||
(request-peg-out-0 peg-out-address swapped)))
|
||||
|
||||
(define-public (request-peg-out-3 (peg-out-address (buff 128)) (token1-trait <sip010-trait>) (token2-trait <sip010-trait>) (token3-trait <sip010-trait>) (factor1 uint) (factor2 uint) (factor3 uint) (dx uint) (min-dw (optional uint)))
|
||||
(let (
|
||||
(swapped (try! (contract-call? .amm-swap-pool-v1-1 swap-helper-b token1-trait token2-trait token3-trait .token-abtc factor1 factor2 factor3 dx min-dw))))
|
||||
(request-peg-out-0 peg-out-address swapped)))
|
||||
|
||||
(define-public (claim-peg-out (request-id uint) (fulfilled-by (buff 128)))
|
||||
(let (
|
||||
(claimer tx-sender)
|
||||
(request-details (try! (get-request-or-fail request-id))))
|
||||
(asserts! (not (var-get peg-out-paused)) err-paused)
|
||||
(asserts! (< (get claimed request-details) block-height) err-request-already-claimed)
|
||||
(asserts! (not (get revoked request-details)) err-request-already-revoked)
|
||||
(asserts! (not (get finalized request-details)) err-request-already-finalized)
|
||||
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-request request-id (merge request-details { claimed: (+ block-height (get-request-claim-grace-period)), claimed-by: claimer, fulfilled-by: fulfilled-by }))))
|
||||
(print (merge request-details { type: "claim-peg-out", request-id: request-id, claimed: (+ block-height (get-request-claim-grace-period)), claimed-by: claimer, fulfilled-by: fulfilled-by }))
|
||||
(ok true)
|
||||
)
|
||||
)
|
||||
|
||||
;; finalize peg-out request
|
||||
;; finalize `request-id` with `tx`
|
||||
;; pays the fee to `fee-address` and burn the relevant pegged-in tokens.
|
||||
;;
|
||||
(define-public (finalize-peg-out
|
||||
(request-id uint)
|
||||
(tx (buff 16384))
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(output-idx uint) (fulfilled-by-idx uint))
|
||||
(let (
|
||||
(request-details (try! (get-request-or-fail request-id)))
|
||||
(was-mined (try! (verify-mined tx block proof)))
|
||||
(parsed-tx (try! (extract-tx-ins-outs tx)))
|
||||
(output (unwrap! (element-at (get outs parsed-tx) output-idx) err-invalid-tx))
|
||||
(fulfilled-by (get scriptPubKey (unwrap! (element-at (get outs parsed-tx) fulfilled-by-idx) err-invalid-tx)))
|
||||
(amount (get value output))
|
||||
(peg-out-address (get scriptPubKey output))
|
||||
(is-fulfilled-by-peg-in (is-peg-in-address-approved fulfilled-by))
|
||||
)
|
||||
|
||||
(asserts! (not (var-get peg-out-paused)) err-paused)
|
||||
(asserts! (is-eq amount (get amount-net request-details)) err-invalid-amount)
|
||||
(asserts! (is-eq (get peg-out-address request-details) peg-out-address) err-address-mismatch)
|
||||
(asserts! (is-eq (get fulfilled-by request-details) fulfilled-by) err-address-mismatch)
|
||||
(asserts! (< (get requested-at-burn-height request-details) (get height block)) err-tx-mined-before-request)
|
||||
;; (asserts! (<= block-height (get claimed request-details)) err-request-claim-expired) ;; allow fulfilled if not claimed again
|
||||
(asserts! (not (get-peg-in-sent-or-default tx output-idx)) err-already-sent)
|
||||
(asserts! (not (get revoked request-details)) err-request-already-revoked)
|
||||
(asserts! (not (get finalized request-details)) err-request-already-finalized)
|
||||
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-peg-in-sent tx output-idx true)))
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-request request-id (merge request-details { finalized: true }))))
|
||||
|
||||
(and (> (get fee request-details) u0) (as-contract (try! (contract-call? .token-abtc transfer-fixed (get fee request-details) tx-sender (var-get fee-address) none))))
|
||||
(and (> (get gas-fee request-details) u0) (as-contract (try! (contract-call? .token-abtc transfer-fixed (get gas-fee request-details) tx-sender (if is-fulfilled-by-peg-in (var-get fee-address) (get claimed-by request-details)) none))))
|
||||
|
||||
(if is-fulfilled-by-peg-in
|
||||
(as-contract (try! (contract-call? .token-abtc burn-fixed (get amount-net request-details) tx-sender)))
|
||||
(as-contract (try! (contract-call? .token-abtc transfer-fixed (get amount-net request-details) tx-sender (get claimed-by request-details) none)))
|
||||
)
|
||||
|
||||
(print { type: "finalize-peg-out", request-id: request-id, tx: tx })
|
||||
(ok true)))
|
||||
|
||||
;; revoke peg-out request
|
||||
;; only after `request-revoke-grace-period` passed
|
||||
;; returns fee and pegged-in tokens to the requester.
|
||||
(define-public (revoke-peg-out (request-id uint))
|
||||
(let (
|
||||
(request-details (try! (get-request-or-fail request-id))))
|
||||
(asserts! (> block-height (+ (get requested-at request-details) (get-request-revoke-grace-period))) err-revoke-grace-period)
|
||||
(asserts! (< (get claimed request-details) block-height) err-request-already-claimed)
|
||||
(asserts! (not (get revoked request-details)) err-request-already-revoked)
|
||||
(asserts! (not (get finalized request-details)) err-request-already-finalized)
|
||||
|
||||
(as-contract (try! (contract-call? .btc-bridge-registry-v1-03 set-request request-id (merge request-details { revoked: true }))))
|
||||
|
||||
(and (> (get fee request-details) u0) (as-contract (try! (contract-call? .token-abtc transfer-fixed (get fee request-details) tx-sender (get requested-by request-details) none))))
|
||||
(and (> (get gas-fee request-details) u0) (as-contract (try! (contract-call? .token-abtc transfer-fixed (get gas-fee request-details) tx-sender (get requested-by request-details) none))))
|
||||
(as-contract (try! (contract-call? .token-abtc transfer-fixed (get amount-net request-details) tx-sender (get requested-by request-details) none)))
|
||||
|
||||
(print { type: "revoke-peg-out", request-id: request-id })
|
||||
(ok true)))
|
||||
|
||||
;; internal functions
|
||||
|
||||
(define-private (validate-tx-1-base (tx (buff 16384)) (output-idx uint) (order-idx uint))
|
||||
(let (
|
||||
(validation-data (try! (validate-tx-common tx output-idx order-idx))))
|
||||
(ok { order-details: (try! (decode-order-1-or-fail (get order-script validation-data))), fee: (get fee validation-data), amount-net: (get amount-net validation-data) })))
|
||||
|
||||
(define-private (validate-tx-1-extra (validation-data { order-details: { user: principal, pool-id: uint, min-dy: uint }, fee: uint, amount-net: uint }) (token principal))
|
||||
(let (
|
||||
(order-details (get order-details validation-data))
|
||||
(pool-details (try! (contract-call? .amm-swap-pool-v1-1 get-pool-details-by-id (get pool-id order-details))))
|
||||
(token-y (if (is-eq (get token-x pool-details) .token-abtc) (get token-y pool-details) (get token-x pool-details)))
|
||||
(factor (get factor pool-details))
|
||||
(dy (try! (contract-call? .amm-swap-pool-v1-1 get-helper .token-abtc token-y factor (get amount-net validation-data)))))
|
||||
(asserts! (>= dy (get min-dy order-details)) err-slippage)
|
||||
(asserts! (is-eq token-y token) err-token-mismatch)
|
||||
(ok { validation-data: validation-data, token-y: token-y, factor: factor })))
|
||||
|
||||
(define-private (validate-tx-2-base (tx (buff 16384)) (output-idx uint) (order-idx uint))
|
||||
(let (
|
||||
(validation-data (try! (validate-tx-common tx output-idx order-idx))))
|
||||
(ok { order-details: (try! (decode-order-2-or-fail (get order-script validation-data))), fee: (get fee validation-data), amount-net: (get amount-net validation-data) })))
|
||||
|
||||
(define-private (validate-tx-2-extra (validation-data { order-details: { user: principal, pool1-id: uint, pool2-id: uint, min-dz: uint }, fee: uint, amount-net: uint }) (token1 principal) (token2 principal))
|
||||
(let (
|
||||
(order-details (get order-details validation-data))
|
||||
(pool1-details (try! (contract-call? .amm-swap-pool-v1-1 get-pool-details-by-id (get pool1-id order-details))))
|
||||
(pool2-details (try! (contract-call? .amm-swap-pool-v1-1 get-pool-details-by-id (get pool2-id order-details))))
|
||||
(token1-y (if (is-eq (get token-x pool1-details) .token-abtc) (get token-y pool1-details) (get token-x pool1-details)))
|
||||
(token2-y (if (is-eq (get token-x pool2-details) token1-y) (get token-y pool2-details) (get token-x pool2-details)))
|
||||
(factor1 (get factor pool1-details))
|
||||
(factor2 (get factor pool2-details))
|
||||
(dz (try! (contract-call? .amm-swap-pool-v1-1 get-helper-a .token-abtc token1-y token2-y factor1 factor2 (get amount-net validation-data)))))
|
||||
(asserts! (is-eq token1-y token1) err-token-mismatch)
|
||||
(asserts! (is-eq token2-y token2) err-token-mismatch)
|
||||
(asserts! (>= dz (get min-dz order-details)) err-slippage)
|
||||
(ok { validation-data: validation-data, token1-y: token1-y, token2-y: token2-y, factor1: factor1, factor2: factor2 })))
|
||||
|
||||
(define-private (validate-tx-3-base (tx (buff 16384)) (output-idx uint) (order-idx uint))
|
||||
(let (
|
||||
(validation-data (try! (validate-tx-common tx output-idx order-idx))))
|
||||
(ok { order-details: (try! (decode-order-3-or-fail (get order-script validation-data))), fee: (get fee validation-data), amount-net: (get amount-net validation-data) })))
|
||||
|
||||
(define-private (validate-tx-3-extra (validation-data { order-details: { user: principal, pool1-id: uint, pool2-id: uint, pool3-id: uint, min-dw: uint }, fee: uint, amount-net: uint }) (token1 principal) (token2 principal) (token3 principal))
|
||||
(let (
|
||||
(order-details (get order-details validation-data))
|
||||
(pool1-details (try! (contract-call? .amm-swap-pool-v1-1 get-pool-details-by-id (get pool1-id order-details))))
|
||||
(pool2-details (try! (contract-call? .amm-swap-pool-v1-1 get-pool-details-by-id (get pool2-id order-details))))
|
||||
(pool3-details (try! (contract-call? .amm-swap-pool-v1-1 get-pool-details-by-id (get pool3-id order-details))))
|
||||
(token1-y (if (is-eq (get token-x pool1-details) .token-abtc) (get token-y pool1-details) (get token-x pool1-details)))
|
||||
(token2-y (if (is-eq (get token-x pool2-details) token1-y) (get token-y pool2-details) (get token-x pool2-details)))
|
||||
(token3-y (if (is-eq (get token-x pool3-details) token2-y) (get token-y pool3-details) (get token-x pool3-details)))
|
||||
(factor1 (get factor pool1-details))
|
||||
(factor2 (get factor pool2-details))
|
||||
(factor3 (get factor pool3-details))
|
||||
(dw (try! (contract-call? .amm-swap-pool-v1-1 get-helper-b .token-abtc token1-y token2-y token3-y factor1 factor2 factor3 (get amount-net validation-data)))))
|
||||
(asserts! (is-eq token1-y token1) err-token-mismatch)
|
||||
(asserts! (is-eq token2-y token2) err-token-mismatch)
|
||||
(asserts! (is-eq token3-y token3) err-token-mismatch)
|
||||
(asserts! (>= dw (get min-dw order-details)) err-slippage)
|
||||
(ok { validation-data: validation-data, token1-y: token1-y, token2-y: token2-y, token3-y: token3-y, factor1: factor1, factor2: factor2, factor3: factor3 })))
|
||||
|
||||
(define-private (validate-tx-launchpad-base (tx (buff 16384)) (output-idx uint) (order-idx uint) (owner-idx uint))
|
||||
(let (
|
||||
(validation-data (try! (validate-tx-common tx output-idx order-idx)))
|
||||
(owner-script (get scriptPubKey (unwrap-panic (element-at? (get outs (get parsed-tx validation-data)) owner-idx)))))
|
||||
(ok { owner-script: owner-script, order-details: (try! (decode-order-launchpad-or-fail (get order-script validation-data))), fee: (get fee validation-data), amount-net: (get amount-net validation-data) })))
|
||||
|
||||
(define-private (validate-tx-launchpad-extra (validation-data { owner-script: (buff 128), order-details: { user: principal, launch-id: uint }, fee: uint, amount-net: uint }))
|
||||
(let (
|
||||
(order-details (get order-details validation-data)))
|
||||
(asserts! (get-whitelisted-or-default (get launch-id order-details) (get owner-script validation-data)) err-not-in-whitelist)
|
||||
(try! (contract-call? .alex-launchpad-v1-7 validate-register (get user order-details) (get launch-id order-details) (get amount-net validation-data) .token-abtc))
|
||||
(ok validation-data)))
|
||||
|
||||
(define-private (validate-tx-common (tx (buff 16384)) (output-idx uint) (order-idx uint))
|
||||
(let (
|
||||
(parsed-tx (try! (extract-tx-ins-outs tx)))
|
||||
(output (unwrap! (element-at (get outs parsed-tx) output-idx) err-invalid-tx))
|
||||
(amount (get value output))
|
||||
(peg-in-address (get scriptPubKey output))
|
||||
(order-script (get scriptPubKey (unwrap-panic (element-at? (get outs parsed-tx) order-idx))))
|
||||
(fee (max (mul-down amount (var-get peg-in-fee)) (var-get peg-in-min-fee)))
|
||||
(amount-net (- amount fee)))
|
||||
(asserts! (not (get-peg-in-sent-or-default tx output-idx)) err-already-sent)
|
||||
(asserts! (is-peg-in-address-approved peg-in-address) err-peg-in-address-not-found)
|
||||
(asserts! (> amount-net u0) err-invalid-amount)
|
||||
|
||||
(ok { parsed-tx: parsed-tx, order-script: order-script, fee: fee, amount-net: amount-net })))
|
||||
|
||||
(define-private (finalize-peg-in-common
|
||||
(tx (buff 16384))
|
||||
(block { header: (buff 80), height: uint })
|
||||
(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint })
|
||||
(output-idx uint) (order-idx uint))
|
||||
(begin
|
||||
(asserts! (not (var-get peg-in-paused)) err-paused)
|
||||
(verify-mined tx block proof)))
|
||||
|
||||
(define-private (set-whitelisted-iter (e {owner: (buff 128), whitelisted: bool}) (launch-id uint))
|
||||
(begin
|
||||
(map-set whitelisted {launch-id: launch-id, owner: (get owner e)} (get whitelisted e))
|
||||
launch-id))
|
||||
|
||||
(define-private (is-contract-owner)
|
||||
(ok (asserts! (is-eq (var-get contract-owner) tx-sender) err-unauthorised)))
|
||||
|
||||
(define-private (max (a uint) (b uint))
|
||||
(if (< a b) b a)
|
||||
)
|
||||
|
||||
(define-private (min (a uint) (b uint))
|
||||
(if (< a b) a b))
|
||||
|
||||
(define-private (mul-down (a uint) (b uint))
|
||||
(/ (* a b) ONE_8))
|
||||
|
||||
(define-private (div-down (a uint) (b uint))
|
||||
(if (is-eq a u0)
|
||||
u0
|
||||
(/ (* a ONE_8) b)))
|
||||
|
||||
87
contracts/btc-bridge-registry-v1-03.clar
Normal file
87
contracts/btc-bridge-registry-v1-03.clar
Normal file
@@ -0,0 +1,87 @@
|
||||
(use-trait sip010-trait .trait-sip-010.sip-010-trait)
|
||||
|
||||
(define-constant err-unauthorised (err u1000))
|
||||
(define-constant err-request-not-found (err u1002))
|
||||
(define-constant err-invalid-input (err u1003))
|
||||
|
||||
(define-data-var contract-owner principal tx-sender)
|
||||
|
||||
(define-map peg-in-sent { tx: (buff 16384), output: uint } bool)
|
||||
|
||||
;; governance functions
|
||||
|
||||
(define-public (set-contract-owner (new-contract-owner principal))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(ok (var-set contract-owner new-contract-owner))))
|
||||
|
||||
(define-public (set-contract-owner-legacy (new-owner principal))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .btc-bridge-registry-v1-02 set-contract-owner new-owner))))
|
||||
|
||||
(define-public (approve-operator (operator principal) (approved bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .btc-bridge-registry-v1-02 approve-operator operator approved))))
|
||||
|
||||
(define-public (set-request-revoke-grace-period (grace-period uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .btc-bridge-registry-v1-02 set-request-revoke-grace-period grace-period))))
|
||||
|
||||
(define-public (set-request-claim-grace-period (grace-period uint))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .btc-bridge-registry-v1-02 set-request-claim-grace-period grace-period))))
|
||||
|
||||
(define-public (approve-peg-in-address (address (buff 128)) (approved bool))
|
||||
(begin
|
||||
(try! (is-contract-owner))
|
||||
(as-contract (contract-call? .btc-bridge-registry-v1-02 approve-peg-in-address address approved))))
|
||||
|
||||
;; read-only functions
|
||||
|
||||
(define-read-only (get-request-revoke-grace-period)
|
||||
(contract-call? .btc-bridge-registry-v1-02 get-request-revoke-grace-period))
|
||||
|
||||
(define-read-only (get-request-claim-grace-period)
|
||||
(contract-call? .btc-bridge-registry-v1-02 get-request-claim-grace-period))
|
||||
|
||||
(define-read-only (is-peg-in-address-approved (address (buff 128)))
|
||||
(contract-call? .btc-bridge-registry-v1-02 is-peg-in-address-approved address))
|
||||
|
||||
(define-read-only (get-request-or-fail (request-id uint))
|
||||
(contract-call? .btc-bridge-registry-v1-02 get-request-or-fail request-id))
|
||||
|
||||
(define-read-only (get-approved-operator-or-default (operator principal))
|
||||
(contract-call? .btc-bridge-registry-v1-02 get-approved-operator-or-default operator))
|
||||
|
||||
(define-read-only (is-approved-operator)
|
||||
(contract-call? .btc-bridge-registry-v1-02 is-approved-operator))
|
||||
|
||||
(define-read-only (get-peg-in-sent-or-default (tx (buff 16384)) (output uint))
|
||||
(match (as-max-len? tx u4096)
|
||||
some-value
|
||||
(or
|
||||
(contract-call? .btc-bridge-registry-v1-02 get-peg-in-sent-or-default some-value output)
|
||||
(default-to false (map-get? peg-in-sent { tx: tx, output: output })))
|
||||
(default-to false (map-get? peg-in-sent { tx: tx, output: output }))))
|
||||
|
||||
;; priviledged functions
|
||||
|
||||
(define-public (set-peg-in-sent (tx (buff 16384)) (output uint) (sent bool))
|
||||
(begin
|
||||
(try! (is-approved-operator))
|
||||
(ok (map-set peg-in-sent { tx: tx, output: output } sent))))
|
||||
|
||||
(define-public (set-request (request-id uint) (details { requested-by: principal, peg-out-address: (buff 128), amount-net: uint, fee: uint, gas-fee: uint, claimed: uint, claimed-by: principal, fulfilled-by: (buff 128), revoked: bool, finalized: bool, requested-at: uint, requested-at-burn-height: uint}))
|
||||
(begin
|
||||
(try! (is-approved-operator))
|
||||
(contract-call? .btc-bridge-registry-v1-02 set-request request-id details)))
|
||||
|
||||
;; internal functions
|
||||
|
||||
(define-private (is-contract-owner)
|
||||
(ok (asserts! (is-eq (var-get contract-owner) tx-sender) err-unauthorised)))
|
||||
|
||||
Reference in New Issue
Block a user