Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Clarinet.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ path = 'contracts/lp-token.clar'
clarity_version = 2
epoch = 2.1

[contracts.lp-token-v2]
path = 'contracts/lp-token-v2.clar'
clarity_version = 2
epoch = 2.1

[contracts.lp-trait]
path = 'contracts/lp-trait.clar'
clarity_version = 2
Expand Down
102 changes: 102 additions & 0 deletions contracts/lp-token-v2.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
;; usda-susdt-lp-token

;;;;;;;;;;;;;;;;;;;;; SIP 010 ;;;;;;;;;;;;;;;;;;;;;;
;; (impl-trait .bitflow-sip-010.bitflow-lp-trait)
(impl-trait .sip-010-trait-ft-standard.sip-010-trait)
(impl-trait .lp-trait.lp-trait)


(define-fungible-token usda-susdt-lp)


(define-constant CONTRACT-OWNER 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)
(define-constant ERR-UNAUTHORIZED-MINT (err u100))
(define-constant ERR-NOT-AUTHORIZED (err u101))

;;vars
(define-data-var token-uri (string-utf8 256) u"")
(define-data-var approved-supply-controller principal 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.stableswap)


;; ---------------------------------------------------------
;; SIP-10 Functions
;; ---------------------------------------------------------
(define-read-only (adheres-to-sip-010)
(ok true)
)

(define-read-only (get-name)
(ok "USDA-sUSDT-LP")
)

(define-read-only (get-symbol)
(ok "USDA-sUSDT-LP")
)

(define-read-only (get-decimals)
(ok u0)
)

(define-read-only (get-balance (account principal))
(ok (ft-get-balance usda-susdt-lp account))
)

(define-read-only (get-total-supply)
(ok (ft-get-supply usda-susdt-lp))
)


(define-read-only (get-token-uri)
(ok (some (var-get token-uri)))
)

(define-public (set-token-uri (uri (string-utf8 256)))
(begin
(asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
(ok (var-set token-uri uri))
)
)

(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
(begin
(asserts! (is-eq tx-sender sender) ERR-NOT-AUTHORIZED)

(match (ft-transfer? usda-susdt-lp amount sender recipient)
response (begin
(print memo)
(ok response)
)
error (err error)
)
)
)

(define-public (mint (who principal) (amount uint))
(begin
(asserts! (is-eq tx-sender (var-get approved-supply-controller)) ERR-UNAUTHORIZED-MINT)
;; amount & who are unchecked, but we let the contract owner mint to whoever they like for convenience
;; #[allow(unchecked_data)]
(ft-mint? usda-susdt-lp amount who)
)
)


(define-public (burn (burner principal) (amount uint))
(begin
(asserts! (is-eq tx-sender burner) ERR-NOT-AUTHORIZED)
;; amount & who are unchecked, but we let the contract owner mint to whoever they like for convenience
;; #[allow(unchecked_data)]
(ft-burn? usda-susdt-lp amount burner)
)
)

;; Change the supply-controller to any other principal, can only be called the current supply-controller
(define-public (set-supply-controller (who principal))
(begin
(asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
;; who is unchecked, we allow the owner to make whoever they like the new minter
;; #[allow(unchecked_data)]
(ok (var-set approved-supply-controller who))
)
)

67 changes: 67 additions & 0 deletions tests/lp-token-v2_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// tests for lp-token-v2 contract
import { Clarinet, Tx, Chain, Account, types, EmptyBlock } from 'https://deno.land/x/clarinet@v1.6.0/index.ts';
import { assertEquals } from 'https://deno.land/std@0.90.0/testing/asserts.ts';

// Test get-token-uri
Clarinet.test({
name: "Ensure we can read the Token URI",
async fn(chain: Chain, accounts: Map<string, Account>) {
const deployer = accounts.get("deployer")!;
const wallet_1 = accounts.get("wallet_1")!;

const call = chain.callReadOnlyFn("lp-token-v2", "get-token-uri", [], deployer.address)

call.result.expectOk().expectSome()
console.log(JSON.stringify(call.result));
},
});

// Test contract owner setting set-token-uri
Clarinet.test({
name: "Ensure the contract owner can set the Token URI",
async fn(chain: Chain, accounts: Map<string, Account>) {
const deployer = accounts.get("deployer")!;
const wallet_1 = accounts.get("wallet_1")!;

const block = chain.mineBlock([
Tx.contractCall("lp-token-v2", "set-token-uri", [types.utf8("https://bitflow.finance/lp-token.json")], deployer.address)
]);

block.receipts[0].result.expectOk()
console.log(JSON.stringify(block.receipts));
},
});

// Test get-token-uri after set-token-uri is called
Clarinet.test({
name: "Ensure get-token-uri returns Token URI after it's set by contract owner",
async fn(chain: Chain, accounts: Map<string, Account>) {
const deployer = accounts.get("deployer")!;
const wallet_1 = accounts.get("wallet_1")!;

chain.mineBlock([
Tx.contractCall("lp-token-v2", "set-token-uri", [types.utf8("https://bitflow.finance/lp-token.json")], deployer.address)
]);

const call = chain.callReadOnlyFn("lp-token-v2", "get-token-uri", [], deployer.address)

call.result.expectOk().expectSome()
console.log(JSON.stringify(call.result));
},
});

// Test user setting set-token-uri that isn't contract owner
Clarinet.test({
name: "Ensure nobody else can set the Token URI except for contract owner",
async fn(chain: Chain, accounts: Map<string, Account>) {
const deployer = accounts.get("deployer")!;
const wallet_1 = accounts.get("wallet_1")!;

const block = chain.mineBlock([
Tx.contractCall("lp-token-v2", "set-token-uri", [types.utf8("https://bitflow.finance/lp-token.json")], wallet_1.address)
]);

block.receipts[0].result.expectErr()
console.log(JSON.stringify(block.receipts));
},
});