From 9364df5c5ba63d9adbefd6ceceb90b2b269d903e Mon Sep 17 00:00:00 2001 From: fiftyeightandeight Date: Thu, 18 Jan 2024 17:25:42 +0800 Subject: [PATCH] endpoint::burn; clarinet_manager --- .gitignore | 1 + Clarinet.json | 10 +++ Clarinet.toml | 8 +- contracts/lqstx-mint-endpoint.clar | 35 ++++++--- contracts/lqstx-mint-registry.clar | 6 +- contracts/token-wlqstx.clar | 3 +- package.json | 1 + scripts/clarinet_manager.sh | 116 +++++++++++++++++++++++++++++ 8 files changed, 162 insertions(+), 18 deletions(-) create mode 100644 Clarinet.json create mode 100755 scripts/clarinet_manager.sh diff --git a/.gitignore b/.gitignore index 76c2842..8f260f4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ coverage *.info costs-reports.json node_modules +contracts_modules diff --git a/Clarinet.json b/Clarinet.json new file mode 100644 index 0000000..9330451 --- /dev/null +++ b/Clarinet.json @@ -0,0 +1,10 @@ +{ + "name": "btc-bridge", + "dependencies": { + "alex_v1": { + "commit": "dev", + "git": "https://github.com/alexgo-io/alex-v1.git", + "contracts_path": "clarity/contracts" + } + } +} diff --git a/Clarinet.toml b/Clarinet.toml index 4a740e6..fb662d0 100644 --- a/Clarinet.toml +++ b/Clarinet.toml @@ -9,11 +9,11 @@ cache_dir = "./.cache" [[project.requirements]] contract_id = "SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP.pox-fast-pool-v2" -[[project.requirements]] -contract_id = "SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard" +[contracts.trait-sip-010] +path = "contracts_modules/alex_v1/traits/trait-sip-010.clar" -[[project.requirements]] -contract_id = "SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx" +[contracts.token-wstx] +path = "contracts_modules/alex_v1/wrapped-token/token-wstx.clar" [contracts.lqstx-mint-endpoint] path = "contracts/lqstx-mint-endpoint.clar" diff --git a/contracts/lqstx-mint-endpoint.clar b/contracts/lqstx-mint-endpoint.clar index 17b556f..1f3acc1 100644 --- a/contracts/lqstx-mint-endpoint.clar +++ b/contracts/lqstx-mint-endpoint.clar @@ -2,7 +2,7 @@ ;; lqstx-mint-endpoint ;; -(use-trait sip010-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait) +(use-trait sip010-trait .trait-sip-010.sip-010-trait) (define-constant ERR-NOT-AUTHORIZED (err u1000)) (define-constant ERR-PAUSED (err u1001)) @@ -36,6 +36,9 @@ (define-read-only (get-mint-request-or-fail (request-id uint)) (contract-call? .lqstx-mint-registry get-mint-request-or-fail request-id)) +(define-read-only (get-burn-request-or-fail (request-id uint)) + (contract-call? .lqstx-mint-registry get-burn-request-or-fail request-id)) + (define-read-only (get-rewards-paid-upto) (contract-call? .lqstx-mint-registry get-rewards-paid-upto)) @@ -44,11 +47,13 @@ (request-details (try! (contract-call? .lqstx-mint-registry get-mint-request-or-fail request-id)))) (ok (asserts! (>= (get-rewards-paid-upto) (get requested-at request-details)) ERR-REQUEST-PENDING)))) +;; @dev it favours smaller amounts as we do not allow partial burn (define-read-only (validate-burn-request (request-id uint)) (let ( (request-details (try! (contract-call? .lqstx-mint-registry get-burn-request-or-fail request-id))) - (balance (stx-account))) - (ok (asserts! (>= (get-rewards-paid-upto) (get requested-at request-details)) ERR-REQUEST-PENDING)))) + (vaulted-amount (try! (contract-call? .token-wlqstx convert-to-tokens (get amount request-details)))) + (balance (stx-account .lqstx-mint-registry))) + (ok (asserts! (>= (get unlocked balance) vaulted-amount) ERR-REQUEST-PENDING)))) ;; governance calls @@ -72,12 +77,12 @@ (try! (is-paused-or-fail)) (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx transfer-fixed amount tx-sender .lqstx-mint-registry none)) (print { type: "mint-request", id: request-id, details: request-details}) - (ok true))) + (ok request-id))) (define-public (finalize-mint (request-id uint)) (let ( - (sender tx-sender) (request-details (try! (get-mint-request-or-fail request-id)))) + (try! (is-paused-or-fail)) (try! (validate-mint-request request-id)) (try! (contract-call? .token-lqstx mint-fixed (get amount request-details) (get requested-by request-details))) (as-contract (contract-call? .lqstx-mint-registry set-mint-request request-id (merge request-details { status: (get-finalized) }))))) @@ -87,16 +92,26 @@ (define-public (request-burn (amount uint)) (let ( + ;; @dev requested-at not used for burn (cycle (contract-call? 'SP000000000000000000002Q6VF78.pox-3 current-pox-reward-cycle)) (request-details { requested-by: tx-sender, amount: amount, requested-at: cycle, status: (get-pending) }) (request-id (as-contract (try! (contract-call? .lqstx-mint-registry set-burn-request u0 request-details))))) - (try! (is-paused-or-fail)) - (try! (contract-call? .token-lqstx transfer-fixed amount tx-sender .lqstx-mint-registry none)) - (print { type: "burn-request", id: request-id, details: request-details }) - (ok true))) + (try! (is-paused-or-fail)) + (try! (contract-call? .token-wlqstx mint-fixed amount tx-sender)) + (try! (contract-call? .token-wlqstx transfer-fixed amount tx-sender .lqstx-mint-registry none)) + (print { type: "burn-request", id: request-id, details: request-details }) + (ok request-id))) (define-public (finalize-burn (request-id uint)) - (ok true)) + (let ( + (request-details (try! (get-burn-request-or-fail request-id))) + (transfer-wlqstx (as-contract (try! (contract-call? .lqstx-mint-registry transfer-fixed (get amount request-details) tx-sender .token-wlqstx)))) + (vaulted-amount (as-contract (try! (contract-call? .token-wlqstx burn-fixed (get amount request-details) tx-sender))))) + (try! (is-paused-or-fail)) + (try! (validate-burn-request request-id)) + (as-contract (try! (contract-call? .token-lqstx burn-fixed vaulted-amount tx-sender))) + (as-contract (try! (contract-call? .lqstx-mint-registry transfer-fixed vaulted-amount (get requested-by request-details) .token-wstx))) + (as-contract (contract-call? .lqstx-mint-registry set-burn-request request-id (merge request-details { status: (get-finalized) }))))) (define-public (revoke-burn (request-id uint)) (ok true)) diff --git a/contracts/lqstx-mint-registry.clar b/contracts/lqstx-mint-registry.clar index de041da..793232d 100644 --- a/contracts/lqstx-mint-registry.clar +++ b/contracts/lqstx-mint-registry.clar @@ -2,7 +2,7 @@ ;; lqstx-mint-registry ;; -(use-trait sip010-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait) +(use-trait sip010-trait .trait-sip-010.sip-010-trait) (define-constant ERR-NOT-AUTHORIZED (err u1000)) (define-constant ERR-UNKNOWN-REQUEST-ID (err u1008)) @@ -88,10 +88,10 @@ (map-set burn-requests id details) (ok id))) -(define-public (transfer-fixed (amount uint) (recipient principal)) +(define-public (transfer-fixed (amount uint) (recipient principal) (token-trait )) (begin (try! (is-approved-operator)) - (as-contract (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx transfer-fixed amount tx-sender recipient none)))) + (as-contract (contract-call? token-trait transfer-fixed amount tx-sender recipient none)))) ;; @dev other pools can be added by upgrading registry (define-public (delegate-stx (amount uint)) diff --git a/contracts/token-wlqstx.clar b/contracts/token-wlqstx.clar index 6ae3068..f21d9b6 100644 --- a/contracts/token-wlqstx.clar +++ b/contracts/token-wlqstx.clar @@ -78,7 +78,8 @@ ) (asserts! (is-eq sender tx-sender) ERR-NOT-AUTHORIZED) (try! (ft-burn? wlqstx (fixed-to-decimals amount) sender)) - (as-contract (contract-call? .token-lqstx transfer-fixed vaulted-amount tx-sender sender none)))) + (as-contract (try! (contract-call? .token-lqstx transfer-fixed vaulted-amount tx-sender sender none))) + (ok vaulted-amount))) ;; read-only functions diff --git a/package.json b/package.json index f2c9dab..2443e9f 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "description": "Run unit tests on this project.", "private": true, "scripts": { + "setup:clarity": "./scripts/clarinet_manager.sh clean && ./scripts/clarinet_manager.sh install", "test": "vitest run", "test:report": "vitest run -- --coverage --costs", "test:watch": "chokidar \"tests/**/*.ts\" \"contracts/**/*.clar\" -c \"npm run test:report\"" diff --git a/scripts/clarinet_manager.sh b/scripts/clarinet_manager.sh new file mode 100755 index 0000000..6c3ac0d --- /dev/null +++ b/scripts/clarinet_manager.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +set -euo pipefail + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )" +TMP_GIT_DIR="$ROOT/.git_tmp_repos" +CONTRACTS_MODULE_PATH="contracts_modules" + +pre_check() { + echo "Installing from Clarinet.json..." + # check if file not exists + if [ ! -f "$DIR/../Clarinet.json" ]; then + echo "Clarity.json not found. abort..." + exit 1 + fi + + # check if command jq is installed, if not, install jq + if ! [ -x "$(command -v jq)" ]; then + echo "jq not installed. Install it before continue. (brew install jq)..." + exit 1 + fi +} + +install_project() { + project_name=${1//\"/} + echo "Installing project...$project_name" + commit=$(cat Clarinet.json | jq -cr ".dependencies.$project_name.commit") + git_repo=$(cat Clarinet.json | jq -cr ".dependencies.$project_name.git") + contracts_path=$(cat Clarinet.json | jq -cr ".dependencies.$project_name.contracts_path") + + echo "Installing from $git_repo, commit $commit, to $project_name" + mkdir -p "$TMP_GIT_DIR"/"$project_name" + + + echo git clone "$git_repo" "$TMP_GIT_DIR"/"$project_name" + git clone "$git_repo" "$TMP_GIT_DIR"/"$project_name" + pushd "$TMP_GIT_DIR"/"$project_name" > /dev/null + echo git checkout "$commit" + git checkout "$commit" + popd > /dev/null + + mkdir -p "$ROOT/$CONTRACTS_MODULE_PATH" + rm -rf "$ROOT/$CONTRACTS_MODULE_PATH/${project_name:?}" + cp -r "$TMP_GIT_DIR"/"$project_name"/"$contracts_path" "$ROOT"/"$CONTRACTS_MODULE_PATH"/$project_name + + echo "cleaning..." + rm -rf "$TMP_GIT_DIR" + echo "installed $project_name" +} + +install() { + pre_check + pushd "$DIR"/.. > /dev/null + + projects_str=$(cat Clarinet.json | jq -c ".dependencies | keys" | sed -e 's/\[//g' -e 's/\]//g' -e 's/\,/ /g') + projects=($projects_str) + + for i in "${projects[@]}"; do + install_project $i + done + + echo installed all projects: $projects +} + +clean() { + rm -rf "$TMP_GIT_DIR" + rm -rf "$ROOT/${CONTRACTS_MODULE_PATH:?}" +} + +update() { + project_name=$1 + branch=$2 + echo "Updating project...$project_name commit from branch head of [$branch]" + + git_repo=$(cat Clarinet.json | jq -cr ".dependencies.$project_name.git") + contracts_path=$(cat Clarinet.json | jq -cr ".dependencies.$project_name.contracts_path") + + echo "Installing from $git_repo, to $project_name" + mkdir -p "$TMP_GIT_DIR"/"$project_name" + echo git clone "$git_repo" "$TMP_GIT_DIR"/"$project_name" + git clone "$git_repo" "$TMP_GIT_DIR"/"$project_name" + pushd "$TMP_GIT_DIR"/"$project_name" > /dev/null + git checkout "$branch" + current_commit=$(git show -s --format=%H) + echo ------using commit------ + git log --format=%B -n 1 $(git log -1 --pretty=format:"%h") + echo ------end commit------ + popd > /dev/null + + echo branch $branch has commit $current_commit + cat <<< $(jq ".dependencies.$project_name.commit=\"$current_commit\"" Clarinet.json) > Clarinet.json + + echo "cleaning..." + rm -rf "$TMP_GIT_DIR" + echo "updated $project_name" +} + +main() { + # check if command is valid + if [ "$1" == "install" ]; then + install + elif [ "$1" == "clean" ]; then + clean + elif [ "$1" == "update" ]; then + # check if project and branch are provided + if [ -z "${2:-}" ] || [ -z "${3:-}" ]; then + echo "Usage: clarinet_manager.sh update " + exit 1 + fi + update $2 $3 + else + echo "Invalid command. Use: ./clarinet_manager.sh install | clean | update" + fi +} + +main $@