From cac9e24c42a558388d2ce447485643e463f7e533 Mon Sep 17 00:00:00 2001 From: spicysquid168 Date: Tue, 7 May 2024 15:19:18 +0700 Subject: [PATCH 1/5] wip: wiring deps --- Clarinet.toml | 25 ++++ contracts/mocks/fake-position-storage.clar | 150 +++++++++++++++++++ contracts/mocks/fake-sbtc.clar | 84 +++++++++++ contracts/mocks/fake-simple-oracle.clar | 87 +++++++++++ contracts/storages/config-storage.clar | 103 +++++++++++++ contracts/storages/position-storage.clar | 1 + contracts/traits/position-storage-trait.clar | 10 ++ contracts/user-entry.clar | 32 +++- tests/user-entry.test.ts | 142 ++++++++++++++++++ tests/usr-entry.test.ts | 20 --- tests/wrappers/config-storage.ts | 36 +++++ tests/wrappers/interface.ts | 3 + tests/wrappers/position-storage.ts | 6 +- tests/wrappers/simple-oracle.ts | 6 +- tests/wrappers/user-entry.ts | 40 +++++ 15 files changed, 722 insertions(+), 23 deletions(-) create mode 100644 contracts/mocks/fake-position-storage.clar create mode 100644 contracts/mocks/fake-sbtc.clar create mode 100644 contracts/mocks/fake-simple-oracle.clar create mode 100644 contracts/storages/config-storage.clar create mode 100644 contracts/traits/position-storage-trait.clar create mode 100644 tests/user-entry.test.ts delete mode 100644 tests/usr-entry.test.ts create mode 100644 tests/wrappers/config-storage.ts create mode 100644 tests/wrappers/interface.ts create mode 100644 tests/wrappers/user-entry.ts diff --git a/Clarinet.toml b/Clarinet.toml index 6f61cd6..658c265 100644 --- a/Clarinet.toml +++ b/Clarinet.toml @@ -23,6 +23,11 @@ path = 'contracts/traits/oracle-trait.clar' clarity_version = 2 epoch = 2.4 +[contracts.position-storage-trait] +path = 'contracts/traits/position-storage-trait.clar' +clarity_version = 2 +epoch = 2.4 + [contracts.simple-oracle] path = 'contracts/oracles/simple-oracle.clar' clarity_version = 2 @@ -33,6 +38,11 @@ path = 'contracts/storages/position-storage.clar' clarity_version = 2 epoch = 2.4 +[contracts.config-storage] +path = 'contracts/storages/config-storage.clar' +clarity_version = 2 +epoch = 2.4 + [contracts.ownable-trait] path = 'contracts/traits/ownable-trait.clar' clarity_version = 2 @@ -43,6 +53,21 @@ path = 'contracts/mocks/sbtc.clar' clarity_version = 2 epoch = 2.4 +[contracts.fake-simple-oracle] +path = 'contracts/mocks/fake-simple-oracle.clar' +clarity_version = 2 +epoch = 2.4 + +[contracts.fake-position-storage] +path = 'contracts/mocks/fake-position-storage.clar' +clarity_version = 2 +epoch = 2.4 + +[contracts.fake-sbtc] +path = 'contracts/mocks/fake-sbtc.clar' +clarity_version = 2 +epoch = 2.4 + [repl.analysis.check_checker] strict = false trusted_sender = false diff --git a/contracts/mocks/fake-position-storage.clar b/contracts/mocks/fake-position-storage.clar new file mode 100644 index 0000000..fa03cec --- /dev/null +++ b/contracts/mocks/fake-position-storage.clar @@ -0,0 +1,150 @@ + +;; title: position-storge.clar +;; version: +;; summary: position storage contract +;; description: + +;; traits +;; +(impl-trait .ownable-trait.ownable-trait) +(impl-trait .position-storage-trait.position-storage-trait) + +;; token definitions +;; + +;; constants +;; +(define-constant ERR_INVALID_POSITION (err u401)) +(define-constant ERR_FORBIDDEN (err u403)) + +;; data vars +;; +(define-data-var owner principal tx-sender) + +;; data maps +;; +(define-map allow-callers principal bool) +;; status: +;; 0: Not existed +;; 1: Active +;; 2: Closed by owner +;; 3: Closed by liquidation +;; 4: Closed by redemption +(define-map positions principal + { + debt: uint, + collateral: uint, + status: uint, + arrayIndex: uint + } +) + +;; public functions +;; +(define-public (set-position-status + (borrower principal) + (status uint) + ) + (let + ( + (pos (unwrap! (get-position borrower) ERR_INVALID_POSITION)) + (data { debt: (get debt pos), collateral: (get collateral pos), status: status, arrayIndex: (get arrayIndex pos) }) + ) + (try! (assert-is-allowed-caller contract-caller)) + ;; #[allow(unchecked_data)] + (map-set positions borrower data) + (ok true) + ) +) + +(define-public (increase-collateral + (who principal) + (amount uint) + ) + (let + ( + (pos (unwrap! (get-position who) ERR_INVALID_POSITION)) + (data { debt: (get debt pos), collateral: (+ (get collateral pos) amount), status: (get status pos), arrayIndex: (get arrayIndex pos) }) + ) + (try! (assert-is-allowed-caller contract-caller)) + ;; #[allow(unchecked_data)] + (map-set positions who data) + (ok true) + ) +) + +(define-public (increase-debt + (who principal) + (amount uint) + ) + (let + ( + (pos (unwrap! (get-position who) ERR_INVALID_POSITION)) + (data { debt: (+ (get debt pos) amount), collateral: (get collateral pos), status: (get status pos), arrayIndex: (get arrayIndex pos) }) + ) + (try! (assert-is-allowed-caller contract-caller)) + ;; #[allow(unchecked_data)] + (map-set positions who data) + (ok true) + ) +) + + +;; read only functions +;; +(define-read-only (get-owner) + (ok (var-get owner)) +) + +(define-read-only (get-position + (borrower principal) + ) + (ok (default-to { debt: u0, collateral: u0, status: u0, arrayIndex: u0 } (map-get? positions borrower)) + ) +) + +(define-read-only (is-allow-caller + (caller principal) + ) + (ok (default-to false (map-get? allow-callers caller)) + ) +) + +;; admin only functions +;; +(define-public (set-allow-caller + (caller principal) + (is-allow bool) + ) + (begin + (try! (assert-is-owner)) + ;; #[allow(unchecked_data)] + (map-set allow-callers caller is-allow) + (ok true) + ) +) + +(define-public (transfer-ownership + (new-owner principal) + ) + (begin + (try! (assert-is-owner)) + ;; #[allow(unchecked_data)] + (var-set owner new-owner) + (ok true) + ) +) + +;; private functions +;; +(define-private (assert-is-owner) + (ok (asserts! (is-eq (var-get owner) tx-sender) ERR_FORBIDDEN)) +) + +(define-private (assert-is-allowed-caller + (caller principal) + ) + (ok (asserts! (is-eq (default-to false (map-get? allow-callers caller)) true) ERR_FORBIDDEN)) +) + + diff --git a/contracts/mocks/fake-sbtc.clar b/contracts/mocks/fake-sbtc.clar new file mode 100644 index 0000000..8f1f2d5 --- /dev/null +++ b/contracts/mocks/fake-sbtc.clar @@ -0,0 +1,84 @@ + +;; title: sbtc +;; version: +;; summary: +;; description: + +;; traits +;; +(impl-trait .ft-trait.ft-trait) + +;; token definitions +;; +(define-fungible-token sbtc) + +;; constants +;; +(define-constant ERR_FORBIDDEN (err u403)) + +;; data vars +;; +(define-data-var token-name (string-ascii 32) "sbtc") +(define-data-var token-symbol (string-ascii 8) "sBTC") +(define-data-var token-uri (optional (string-utf8 256)) none) +(define-data-var token-decimals uint u8) + +;; data maps +;; + +;; public functions +;; +(define-public (transfer + (amount uint) + (sender principal) + (recipient principal) + (memo (optional (buff 34))) + ) + (begin + (asserts! (or (is-eq tx-sender sender) (is-eq contract-caller sender)) ERR_FORBIDDEN) + ;; #[allow(unchecked_data)] + (ft-transfer? sbtc amount sender recipient) + ) +) + +(define-public (mint + (amount uint) + (recipient principal) + ) + (begin + ;; #[allow(unchecked_data)] + (ft-mint? sbtc amount recipient) + ) +) + +;; read only functions +;; +(define-read-only (get-name) + (ok (var-get token-name)) +) + +(define-read-only (get-symbol) + (ok (var-get token-symbol)) +) + +(define-read-only (get-decimals) + (ok (var-get token-decimals)) +) + +(define-read-only (get-balance + (account principal) + ) + (ok (ft-get-balance sbtc account)) +) + +(define-read-only (get-total-supply) + (ok (ft-get-supply sbtc)) +) + +(define-read-only (get-token-uri) + (ok (var-get token-uri)) +) + +;; private functions +;; + diff --git a/contracts/mocks/fake-simple-oracle.clar b/contracts/mocks/fake-simple-oracle.clar new file mode 100644 index 0000000..712df00 --- /dev/null +++ b/contracts/mocks/fake-simple-oracle.clar @@ -0,0 +1,87 @@ +;; title: simple_oracle +;; version: 0.0.1 +;; summary: Simple oracle contract +;; description: A plain simple oracle contract that +;; allows whitelisted accounts to set asset prices and return asset prices + +;; traits +;; +(impl-trait .oracle-trait.oracle-trait) +(impl-trait .ownable-trait.ownable-trait) +(use-trait ft .ft-trait.ft-trait) + +;; token definitions +;; + +;; constants +;; +(define-constant ERR_FORBIDDEN (err u403)) +(define-constant ERR_NOT_FOUND (err u404)) + +;; data vars +;; +(define-data-var feeder principal tx-sender) +(define-data-var owner principal tx-sender) + +;; data maps +;; +(define-map assets principal uint) + +;; public functions +;; +(define-public (set-price + (asset ) + (price uint) + ) + (begin + (asserts! (is-eq (var-get feeder) tx-sender) ERR_FORBIDDEN) + ;; #[allow(unchecked_data)] + (ok (map-set assets (contract-of asset) price)) + ) +) + +;; read only functions +;; +(define-read-only (fetch-price + (asset ) + ) + (match (map-get? assets (contract-of asset)) + ret (ok ret) + ERR_NOT_FOUND + ) +) + +(define-read-only (get-owner + ) + (ok (var-get owner)) +) + +;; admin only functions +;; +(define-public (set-feeder + (new-feeder principal) + ) + (begin + (try! (assert-is-owner)) + ;; #[allow(unchecked_data)] + (var-set feeder new-feeder) + (ok true) + ) +) + +(define-public (transfer-ownership + (new-owner principal) + ) + (begin + (try! (assert-is-owner)) + ;; #[allow(unchecked_data)] + (var-set owner new-owner) + (ok true) + ) +) + +;; private functions +;; +(define-private (assert-is-owner) + (ok (asserts! (is-eq (var-get owner) tx-sender) ERR_FORBIDDEN)) +) \ No newline at end of file diff --git a/contracts/storages/config-storage.clar b/contracts/storages/config-storage.clar new file mode 100644 index 0000000..ee4fec2 --- /dev/null +++ b/contracts/storages/config-storage.clar @@ -0,0 +1,103 @@ + +;; title: config-storge.clar +;; version: +;; summary: config storage contract +;; description: + +;; traits +;; +(impl-trait .ownable-trait.ownable-trait) + +;; token definitions +;; + +;; constants +;; +(define-constant ERR_INVALID_POSITION (err u401)) +(define-constant ERR_FORBIDDEN (err u403)) +(define-constant ERR_NOT_INITIALIZED (err u501)) + +;; data vars +;; +(define-data-var owner principal tx-sender) +(define-data-var position-storage principal tx-sender) +(define-data-var oracle principal tx-sender) +(define-data-var collateral principal tx-sender) + +(define-data-var is-initialized bool false) + +;; data maps +;; + +;; initialize function +(define-public (initialize + (init-oracle principal) + (init-position-storage principal) + (init-collateral principal) + ) + (begin + ;; #[allow(unchecked_data)] + (var-set oracle init-oracle) + ;; #[allow(unchecked_data)] + (var-set position-storage init-position-storage) + ;; #[allow(unchecked_data)] + (var-set collateral init-collateral) + (var-set is-initialized true) + (ok true) + ) +) + + +;; public functions +;; + + + +;; read only functions +;; +(define-read-only (get-owner) + (ok (var-get owner)) +) + +(define-read-only (get-configurations) + (begin + (asserts! (var-get is-initialized) ERR_NOT_INITIALIZED) + (ok { + oracle: (var-get oracle), + position-storage: (var-get position-storage), + collateral: (var-get collateral) + }) + ) +) + +;; admin only functions +;; +(define-public (set-oracle + (new-oracle principal) + ) + (begin + (try! (assert-is-owner)) + ;; #[allow(unchecked_data)] + (var-set oracle new-oracle) + (ok true) + ) +) + +(define-public (transfer-ownership + (new-owner principal) + ) + (begin + (try! (assert-is-owner)) + ;; #[allow(unchecked_data)] + (var-set owner new-owner) + (ok true) + ) +) + +;; private functions +;; +(define-private (assert-is-owner) + (ok (asserts! (is-eq (var-get owner) tx-sender) ERR_FORBIDDEN)) +) + + diff --git a/contracts/storages/position-storage.clar b/contracts/storages/position-storage.clar index 4ec49b7..fa03cec 100644 --- a/contracts/storages/position-storage.clar +++ b/contracts/storages/position-storage.clar @@ -7,6 +7,7 @@ ;; traits ;; (impl-trait .ownable-trait.ownable-trait) +(impl-trait .position-storage-trait.position-storage-trait) ;; token definitions ;; diff --git a/contracts/traits/position-storage-trait.clar b/contracts/traits/position-storage-trait.clar new file mode 100644 index 0000000..7d93119 --- /dev/null +++ b/contracts/traits/position-storage-trait.clar @@ -0,0 +1,10 @@ +;; title: position-storage-trait +;; description: A trait defines functions of position storage contract + +(define-trait position-storage-trait + ( + (set-position-status (principal uint) (response bool uint)) + (increase-collateral (principal uint) (response bool uint)) + (increase-debt (principal uint) (response bool uint)) + ) +) \ No newline at end of file diff --git a/contracts/user-entry.clar b/contracts/user-entry.clar index 42fc4e9..e37fcec 100644 --- a/contracts/user-entry.clar +++ b/contracts/user-entry.clar @@ -6,12 +6,19 @@ ;; traits ;; +(use-trait oracle-trait .oracle-trait.oracle-trait) +(use-trait position-storage-trait .position-storage-trait.position-storage-trait) +(use-trait ft .ft-trait.ft-trait) ;; token definitions ;; ;; constants ;; +(define-constant ERR_BAD_ORACLE (err u401)) +(define-constant ERR_BAD_POSITION_STORAGE (err u402)) +(define-constant ERR_BAD_COLLATERAL (err u403)) +(define-constant ERR_GET_CONFIGS (err u501)) ;; data vars ;; @@ -22,9 +29,32 @@ ;; public functions ;; (define-public (new-position + (oracle ) + (position-storage ) + (collateral ) + (collateral-amount uint) (stable-coin-amount uint) ) - (ok true) + (let + ( + (configs (unwrap! (contract-call? .config-storage get-configurations) ERR_GET_CONFIGS)) + ) + (asserts! (is-eq (contract-of oracle) (get oracle configs)) ERR_BAD_ORACLE) + (asserts! (is-eq (contract-of position-storage) (get position-storage configs)) ERR_BAD_POSITION_STORAGE) + (asserts! (is-eq (contract-of collateral) (get collateral configs)) ERR_BAD_COLLATERAL) + (let + ( + (price (try! (contract-call? oracle fetch-price collateral))) + ) + ;; set position status + (try! (contract-call? position-storage set-position-status tx-sender u1)) + ;; increase collateral + (try! (contract-call? position-storage increase-collateral tx-sender collateral-amount)) + ;; increase debt + (try! (contract-call? position-storage increase-debt tx-sender stable-coin-amount)) + ) + (ok true) + ) ) ;; read only functions diff --git a/tests/user-entry.test.ts b/tests/user-entry.test.ts new file mode 100644 index 0000000..142831c --- /dev/null +++ b/tests/user-entry.test.ts @@ -0,0 +1,142 @@ +import { beforeEach, describe, expect, it } from "vitest"; +import { SimpleOracleWrapper } from "./wrappers/simple-oracle"; +import { PositionStorageWrapper } from "./wrappers/position-storage"; +import { UserEntryWrapper } from "./wrappers/user-entry"; +import { Cl } from "@stacks/transactions"; +import { ConfigStorageWrapper } from "./wrappers/config-storage"; +import { sBTC_PRINCIPAL } from "./constants"; + +/* + The test below is an example. To learn more, read the testing documentation here: + https://docs.hiro.so/clarinet/feature-guides/test-contract-with-clarinet-sdk +*/ + +describe("user entry tests", () => { + const accounts = simnet.getAccounts(); + + let simpleOracleAsDeployer: SimpleOracleWrapper; + let simpleOracleAsFeeder: SimpleOracleWrapper; + + let configStorageAsDeployer: ConfigStorageWrapper; + + let positionStorageAsDeployer: PositionStorageWrapper; + + let userEntryAsAlice: UserEntryWrapper; + + let deployer: string; + let feeder: string; + let alice: string; + + beforeEach(() => { + deployer = accounts.get("deployer")!; + feeder = accounts.get("wallet_1")!; + alice = accounts.get("wallet_2")!; + + simpleOracleAsDeployer = new SimpleOracleWrapper( + simnet, + deployer, + deployer + ); + simpleOracleAsFeeder = new SimpleOracleWrapper(simnet, deployer, feeder); + expect(simpleOracleAsDeployer.setFeeder(feeder)).toBeOk(Cl.bool(true)); + + configStorageAsDeployer = new ConfigStorageWrapper( + simnet, + deployer, + deployer + ); + + positionStorageAsDeployer = new PositionStorageWrapper( + simnet, + deployer, + deployer + ); + + userEntryAsAlice = new UserEntryWrapper(simnet, deployer, alice); + + expect( + positionStorageAsDeployer.setAllowCaller( + userEntryAsAlice.getContractPrincipal(), + true + ) + ).toBeOk(Cl.bool(true)); + expect( + configStorageAsDeployer.initialize( + simpleOracleAsDeployer.getContractPrincipal(), + positionStorageAsDeployer.getContractPrincipal(), + sBTC_PRINCIPAL + ) + ).toBeOk(Cl.bool(true)); + + simpleOracleAsFeeder.setPrice(sBTC_PRINCIPAL, String(200 * 1e8)); + }); + + describe("when new position", () => { + describe("when injected incorrect dependency", () => { + describe("when injected fake oracle", () => { + it("should error", async () => { + expect( + userEntryAsAlice.newPosition( + `${deployer}.fake-simple-oracle`, + positionStorageAsDeployer.getContractPrincipal(), + sBTC_PRINCIPAL, + 100, + 100 + ) + ).toBeErr(Cl.uint(401)); + }); + }); + + describe("when injected fake position storage", () => { + it("should error", async () => { + expect( + userEntryAsAlice.newPosition( + simpleOracleAsDeployer.getContractPrincipal(), + `${deployer}.fake-position-storage`, + sBTC_PRINCIPAL, + 100, + 100 + ) + ).toBeErr(Cl.uint(402)); + }); + }); + + describe("when injected fake collateral", () => { + it("should error", async () => { + expect( + userEntryAsAlice.newPosition( + simpleOracleAsDeployer.getContractPrincipal(), + positionStorageAsDeployer.getContractPrincipal(), + `${deployer}.fake-sbtc`, + 100, + 100 + ) + ).toBeErr(Cl.uint(403)); + }); + }); + }); + + describe("when injected correct dependency", () => { + it("should create new position", async () => { + expect( + userEntryAsAlice.newPosition( + simpleOracleAsDeployer.getContractPrincipal(), + positionStorageAsDeployer.getContractPrincipal(), + sBTC_PRINCIPAL, + 100, + 100 + ) + ).toBeOk(Cl.bool(true)); + + expect(positionStorageAsDeployer.getPosition(alice)).toBeOk( + Cl.tuple({ + arrayIndex: Cl.uint(0), + collateral: Cl.uint(100), + debt: Cl.uint(100), + status: Cl.uint(1), + }) + ); + }); + }); + }); +}); diff --git a/tests/usr-entry.test.ts b/tests/usr-entry.test.ts deleted file mode 100644 index 6da7484..0000000 --- a/tests/usr-entry.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { describe, expect, it } from "vitest"; - -const accounts = simnet.getAccounts(); -const address1 = accounts.get("wallet_1")!; - -/* - The test below is an example. To learn more, read the testing documentation here: - https://docs.hiro.so/clarinet/feature-guides/test-contract-with-clarinet-sdk -*/ - -describe("example tests", () => { - it("ensures simnet is well initalised", () => { - expect(simnet.blockHeight).toBeDefined(); - }); - - // it("shows an example", () => { - // const { result } = simnet.callReadOnlyFn("counter", "get-counter", [], address1); - // expect(result).toBeUint(0); - // }); -}); diff --git a/tests/wrappers/config-storage.ts b/tests/wrappers/config-storage.ts new file mode 100644 index 0000000..bffa429 --- /dev/null +++ b/tests/wrappers/config-storage.ts @@ -0,0 +1,36 @@ +import { Simnet } from "@hirosystems/clarinet-sdk"; +import { Cl, ClarityValue } from "@stacks/transactions"; + +export class ConfigStorageWrapper implements WrapperInterface { + simnet: Simnet; + deployerAddress: string; + contractName: string = "config-storage"; + caller: string; + + constructor(simnet: Simnet, deployerAddress: string, caller: string) { + this.simnet = simnet; + this.deployerAddress = deployerAddress; + this.caller = caller; + } + + getContractPrincipal(): string { + return `${this.deployerAddress}.${this.contractName}`; + } + + initialize( + oraclePrincipal: string, + positionStoragePrincipal: string, + collateralPrincipal: string + ): ClarityValue { + return simnet.callPublicFn( + this.contractName, + "initialize", + [ + Cl.principal(oraclePrincipal), + Cl.principal(positionStoragePrincipal), + Cl.principal(collateralPrincipal), + ], + this.caller + ).result; + } +} diff --git a/tests/wrappers/interface.ts b/tests/wrappers/interface.ts new file mode 100644 index 0000000..3f395f4 --- /dev/null +++ b/tests/wrappers/interface.ts @@ -0,0 +1,3 @@ +interface WrapperInterface { + getContractPrincipal(): string; +} diff --git a/tests/wrappers/position-storage.ts b/tests/wrappers/position-storage.ts index 18320fa..d95c4c1 100644 --- a/tests/wrappers/position-storage.ts +++ b/tests/wrappers/position-storage.ts @@ -1,7 +1,7 @@ import { Simnet } from "@hirosystems/clarinet-sdk"; import { Cl, ClarityValue } from "@stacks/transactions"; -export class PositionStorageWrapper { +export class PositionStorageWrapper implements WrapperInterface { simnet: Simnet; deployerAddress: string; contractName: string = "position-storage"; @@ -13,6 +13,10 @@ export class PositionStorageWrapper { this.caller = caller; } + getContractPrincipal(): string { + return `${this.deployerAddress}.${this.contractName}`; + } + setAllowCaller(callerPrincipal: string, isAllow: boolean): ClarityValue { return this.simnet.callPublicFn( this.contractName, diff --git a/tests/wrappers/simple-oracle.ts b/tests/wrappers/simple-oracle.ts index eef973a..bc07aa3 100644 --- a/tests/wrappers/simple-oracle.ts +++ b/tests/wrappers/simple-oracle.ts @@ -1,7 +1,7 @@ import { Simnet } from "@hirosystems/clarinet-sdk"; import { Cl, ClarityValue } from "@stacks/transactions"; -export class SimpleOracleWrapper { +export class SimpleOracleWrapper implements WrapperInterface { simnet: Simnet; deployerAddress: string; contractName: string = "simple-oracle"; @@ -13,6 +13,10 @@ export class SimpleOracleWrapper { this.caller = caller; } + getContractPrincipal(): string { + return `${this.deployerAddress}.${this.contractName}`; + } + setFeeder(feederPrincipal: string): ClarityValue { return this.simnet.callPublicFn( this.contractName, diff --git a/tests/wrappers/user-entry.ts b/tests/wrappers/user-entry.ts new file mode 100644 index 0000000..99865d5 --- /dev/null +++ b/tests/wrappers/user-entry.ts @@ -0,0 +1,40 @@ +import { Simnet } from "@hirosystems/clarinet-sdk"; +import { Cl } from "@stacks/transactions"; + +export class UserEntryWrapper implements WrapperInterface { + simnet: Simnet; + deployerAddress: string; + contractName: string = "user-entry"; + caller: string; + + constructor(simnet: Simnet, deployerAddress: string, caller: string) { + this.simnet = simnet; + this.deployerAddress = deployerAddress; + this.caller = caller; + } + + getContractPrincipal(): string { + return `${this.deployerAddress}.${this.contractName}`; + } + + newPosition( + oraclePrincipal: string, + positionStoragePrincipal: string, + collateralPrincipal: string, + collateralAmount: number, + stablecoinAmount: number + ) { + return this.simnet.callPublicFn( + this.contractName, + "new-position", + [ + Cl.principal(oraclePrincipal), + Cl.principal(positionStoragePrincipal), + Cl.principal(collateralPrincipal), + Cl.uint(collateralAmount), + Cl.uint(stablecoinAmount), + ], + this.caller + ).result; + } +} From 3e18ac5f88f87b2e56b11bf032216a06180b0812 Mon Sep 17 00:00:00 2001 From: spicysquid168 Date: Tue, 7 May 2024 15:42:20 +0700 Subject: [PATCH 2/5] chore: position -> vault --- Clarinet.toml | 12 ++-- ...n-storage.clar => fake-vault-storage.clar} | 28 ++++----- contracts/storages/config-storage.clar | 9 ++- ...sition-storage.clar => vault-storage.clar} | 28 ++++----- contracts/traits/position-storage-trait.clar | 10 ---- contracts/traits/vault-storage-trait.clar | 10 ++++ contracts/user-entry.clar | 18 +++--- tests/position-storage.test.ts | 59 ++++++++----------- tests/user-entry.test.ts | 34 +++++------ tests/wrappers/user-entry.ts | 8 +-- .../{position-storage.ts => vault-storage.ts} | 12 ++-- 11 files changed, 110 insertions(+), 118 deletions(-) rename contracts/mocks/{fake-position-storage.clar => fake-vault-storage.clar} (80%) rename contracts/storages/{position-storage.clar => vault-storage.clar} (80%) delete mode 100644 contracts/traits/position-storage-trait.clar create mode 100644 contracts/traits/vault-storage-trait.clar rename tests/wrappers/{position-storage.ts => vault-storage.ts} (85%) diff --git a/Clarinet.toml b/Clarinet.toml index 658c265..7d5ec65 100644 --- a/Clarinet.toml +++ b/Clarinet.toml @@ -23,8 +23,8 @@ path = 'contracts/traits/oracle-trait.clar' clarity_version = 2 epoch = 2.4 -[contracts.position-storage-trait] -path = 'contracts/traits/position-storage-trait.clar' +[contracts.vault-storage-trait] +path = 'contracts/traits/vault-storage-trait.clar' clarity_version = 2 epoch = 2.4 @@ -33,8 +33,8 @@ path = 'contracts/oracles/simple-oracle.clar' clarity_version = 2 epoch = 2.4 -[contracts.position-storage] -path = 'contracts/storages/position-storage.clar' +[contracts.vault-storage] +path = 'contracts/storages/vault-storage.clar' clarity_version = 2 epoch = 2.4 @@ -58,8 +58,8 @@ path = 'contracts/mocks/fake-simple-oracle.clar' clarity_version = 2 epoch = 2.4 -[contracts.fake-position-storage] -path = 'contracts/mocks/fake-position-storage.clar' +[contracts.fake-vault-storage] +path = 'contracts/mocks/fake-vault-storage.clar' clarity_version = 2 epoch = 2.4 diff --git a/contracts/mocks/fake-position-storage.clar b/contracts/mocks/fake-vault-storage.clar similarity index 80% rename from contracts/mocks/fake-position-storage.clar rename to contracts/mocks/fake-vault-storage.clar index fa03cec..13430f7 100644 --- a/contracts/mocks/fake-position-storage.clar +++ b/contracts/mocks/fake-vault-storage.clar @@ -1,20 +1,20 @@ -;; title: position-storge.clar +;; title: vault-storge.clar ;; version: -;; summary: position storage contract +;; summary: vault storage contract ;; description: ;; traits ;; (impl-trait .ownable-trait.ownable-trait) -(impl-trait .position-storage-trait.position-storage-trait) +(impl-trait .vault-storage-trait.vault-storage-trait) ;; token definitions ;; ;; constants ;; -(define-constant ERR_INVALID_POSITION (err u401)) +(define-constant ERR_INVALID_VAULT (err u401)) (define-constant ERR_FORBIDDEN (err u403)) ;; data vars @@ -30,7 +30,7 @@ ;; 2: Closed by owner ;; 3: Closed by liquidation ;; 4: Closed by redemption -(define-map positions principal +(define-map vaults principal { debt: uint, collateral: uint, @@ -41,18 +41,18 @@ ;; public functions ;; -(define-public (set-position-status +(define-public (set-vault-status (borrower principal) (status uint) ) (let ( - (pos (unwrap! (get-position borrower) ERR_INVALID_POSITION)) + (pos (unwrap! (get-vault borrower) ERR_INVALID_VAULT)) (data { debt: (get debt pos), collateral: (get collateral pos), status: status, arrayIndex: (get arrayIndex pos) }) ) (try! (assert-is-allowed-caller contract-caller)) ;; #[allow(unchecked_data)] - (map-set positions borrower data) + (map-set vaults borrower data) (ok true) ) ) @@ -63,12 +63,12 @@ ) (let ( - (pos (unwrap! (get-position who) ERR_INVALID_POSITION)) + (pos (unwrap! (get-vault who) ERR_INVALID_VAULT)) (data { debt: (get debt pos), collateral: (+ (get collateral pos) amount), status: (get status pos), arrayIndex: (get arrayIndex pos) }) ) (try! (assert-is-allowed-caller contract-caller)) ;; #[allow(unchecked_data)] - (map-set positions who data) + (map-set vaults who data) (ok true) ) ) @@ -79,12 +79,12 @@ ) (let ( - (pos (unwrap! (get-position who) ERR_INVALID_POSITION)) + (pos (unwrap! (get-vault who) ERR_INVALID_VAULT)) (data { debt: (+ (get debt pos) amount), collateral: (get collateral pos), status: (get status pos), arrayIndex: (get arrayIndex pos) }) ) (try! (assert-is-allowed-caller contract-caller)) ;; #[allow(unchecked_data)] - (map-set positions who data) + (map-set vaults who data) (ok true) ) ) @@ -96,10 +96,10 @@ (ok (var-get owner)) ) -(define-read-only (get-position +(define-read-only (get-vault (borrower principal) ) - (ok (default-to { debt: u0, collateral: u0, status: u0, arrayIndex: u0 } (map-get? positions borrower)) + (ok (default-to { debt: u0, collateral: u0, status: u0, arrayIndex: u0 } (map-get? vaults borrower)) ) ) diff --git a/contracts/storages/config-storage.clar b/contracts/storages/config-storage.clar index ee4fec2..8b09949 100644 --- a/contracts/storages/config-storage.clar +++ b/contracts/storages/config-storage.clar @@ -13,14 +13,13 @@ ;; constants ;; -(define-constant ERR_INVALID_POSITION (err u401)) (define-constant ERR_FORBIDDEN (err u403)) (define-constant ERR_NOT_INITIALIZED (err u501)) ;; data vars ;; (define-data-var owner principal tx-sender) -(define-data-var position-storage principal tx-sender) +(define-data-var vault-storage principal tx-sender) (define-data-var oracle principal tx-sender) (define-data-var collateral principal tx-sender) @@ -32,14 +31,14 @@ ;; initialize function (define-public (initialize (init-oracle principal) - (init-position-storage principal) + (init-vault-storage principal) (init-collateral principal) ) (begin ;; #[allow(unchecked_data)] (var-set oracle init-oracle) ;; #[allow(unchecked_data)] - (var-set position-storage init-position-storage) + (var-set vault-storage init-vault-storage) ;; #[allow(unchecked_data)] (var-set collateral init-collateral) (var-set is-initialized true) @@ -64,7 +63,7 @@ (asserts! (var-get is-initialized) ERR_NOT_INITIALIZED) (ok { oracle: (var-get oracle), - position-storage: (var-get position-storage), + vault-storage: (var-get vault-storage), collateral: (var-get collateral) }) ) diff --git a/contracts/storages/position-storage.clar b/contracts/storages/vault-storage.clar similarity index 80% rename from contracts/storages/position-storage.clar rename to contracts/storages/vault-storage.clar index fa03cec..13430f7 100644 --- a/contracts/storages/position-storage.clar +++ b/contracts/storages/vault-storage.clar @@ -1,20 +1,20 @@ -;; title: position-storge.clar +;; title: vault-storge.clar ;; version: -;; summary: position storage contract +;; summary: vault storage contract ;; description: ;; traits ;; (impl-trait .ownable-trait.ownable-trait) -(impl-trait .position-storage-trait.position-storage-trait) +(impl-trait .vault-storage-trait.vault-storage-trait) ;; token definitions ;; ;; constants ;; -(define-constant ERR_INVALID_POSITION (err u401)) +(define-constant ERR_INVALID_VAULT (err u401)) (define-constant ERR_FORBIDDEN (err u403)) ;; data vars @@ -30,7 +30,7 @@ ;; 2: Closed by owner ;; 3: Closed by liquidation ;; 4: Closed by redemption -(define-map positions principal +(define-map vaults principal { debt: uint, collateral: uint, @@ -41,18 +41,18 @@ ;; public functions ;; -(define-public (set-position-status +(define-public (set-vault-status (borrower principal) (status uint) ) (let ( - (pos (unwrap! (get-position borrower) ERR_INVALID_POSITION)) + (pos (unwrap! (get-vault borrower) ERR_INVALID_VAULT)) (data { debt: (get debt pos), collateral: (get collateral pos), status: status, arrayIndex: (get arrayIndex pos) }) ) (try! (assert-is-allowed-caller contract-caller)) ;; #[allow(unchecked_data)] - (map-set positions borrower data) + (map-set vaults borrower data) (ok true) ) ) @@ -63,12 +63,12 @@ ) (let ( - (pos (unwrap! (get-position who) ERR_INVALID_POSITION)) + (pos (unwrap! (get-vault who) ERR_INVALID_VAULT)) (data { debt: (get debt pos), collateral: (+ (get collateral pos) amount), status: (get status pos), arrayIndex: (get arrayIndex pos) }) ) (try! (assert-is-allowed-caller contract-caller)) ;; #[allow(unchecked_data)] - (map-set positions who data) + (map-set vaults who data) (ok true) ) ) @@ -79,12 +79,12 @@ ) (let ( - (pos (unwrap! (get-position who) ERR_INVALID_POSITION)) + (pos (unwrap! (get-vault who) ERR_INVALID_VAULT)) (data { debt: (+ (get debt pos) amount), collateral: (get collateral pos), status: (get status pos), arrayIndex: (get arrayIndex pos) }) ) (try! (assert-is-allowed-caller contract-caller)) ;; #[allow(unchecked_data)] - (map-set positions who data) + (map-set vaults who data) (ok true) ) ) @@ -96,10 +96,10 @@ (ok (var-get owner)) ) -(define-read-only (get-position +(define-read-only (get-vault (borrower principal) ) - (ok (default-to { debt: u0, collateral: u0, status: u0, arrayIndex: u0 } (map-get? positions borrower)) + (ok (default-to { debt: u0, collateral: u0, status: u0, arrayIndex: u0 } (map-get? vaults borrower)) ) ) diff --git a/contracts/traits/position-storage-trait.clar b/contracts/traits/position-storage-trait.clar deleted file mode 100644 index 7d93119..0000000 --- a/contracts/traits/position-storage-trait.clar +++ /dev/null @@ -1,10 +0,0 @@ -;; title: position-storage-trait -;; description: A trait defines functions of position storage contract - -(define-trait position-storage-trait - ( - (set-position-status (principal uint) (response bool uint)) - (increase-collateral (principal uint) (response bool uint)) - (increase-debt (principal uint) (response bool uint)) - ) -) \ No newline at end of file diff --git a/contracts/traits/vault-storage-trait.clar b/contracts/traits/vault-storage-trait.clar new file mode 100644 index 0000000..84cd05c --- /dev/null +++ b/contracts/traits/vault-storage-trait.clar @@ -0,0 +1,10 @@ +;; title: vault-storage-trait +;; description: A trait defines functions of vault storage contract + +(define-trait vault-storage-trait + ( + (set-vault-status (principal uint) (response bool uint)) + (increase-collateral (principal uint) (response bool uint)) + (increase-debt (principal uint) (response bool uint)) + ) +) \ No newline at end of file diff --git a/contracts/user-entry.clar b/contracts/user-entry.clar index e37fcec..c8cf899 100644 --- a/contracts/user-entry.clar +++ b/contracts/user-entry.clar @@ -7,7 +7,7 @@ ;; traits ;; (use-trait oracle-trait .oracle-trait.oracle-trait) -(use-trait position-storage-trait .position-storage-trait.position-storage-trait) +(use-trait vault-storage-trait .vault-storage-trait.vault-storage-trait) (use-trait ft .ft-trait.ft-trait) ;; token definitions @@ -16,7 +16,7 @@ ;; constants ;; (define-constant ERR_BAD_ORACLE (err u401)) -(define-constant ERR_BAD_POSITION_STORAGE (err u402)) +(define-constant ERR_BAD_VAULT_STORAGE (err u402)) (define-constant ERR_BAD_COLLATERAL (err u403)) (define-constant ERR_GET_CONFIGS (err u501)) @@ -28,9 +28,9 @@ ;; public functions ;; -(define-public (new-position +(define-public (new-vault (oracle ) - (position-storage ) + (vault-storage ) (collateral ) (collateral-amount uint) (stable-coin-amount uint) @@ -40,18 +40,18 @@ (configs (unwrap! (contract-call? .config-storage get-configurations) ERR_GET_CONFIGS)) ) (asserts! (is-eq (contract-of oracle) (get oracle configs)) ERR_BAD_ORACLE) - (asserts! (is-eq (contract-of position-storage) (get position-storage configs)) ERR_BAD_POSITION_STORAGE) + (asserts! (is-eq (contract-of vault-storage) (get vault-storage configs)) ERR_BAD_VAULT_STORAGE) (asserts! (is-eq (contract-of collateral) (get collateral configs)) ERR_BAD_COLLATERAL) (let ( (price (try! (contract-call? oracle fetch-price collateral))) ) - ;; set position status - (try! (contract-call? position-storage set-position-status tx-sender u1)) + ;; set vault status + (try! (contract-call? vault-storage set-vault-status tx-sender u1)) ;; increase collateral - (try! (contract-call? position-storage increase-collateral tx-sender collateral-amount)) + (try! (contract-call? vault-storage increase-collateral tx-sender collateral-amount)) ;; increase debt - (try! (contract-call? position-storage increase-debt tx-sender stable-coin-amount)) + (try! (contract-call? vault-storage increase-debt tx-sender stable-coin-amount)) ) (ok true) ) diff --git a/tests/position-storage.test.ts b/tests/position-storage.test.ts index 16879ce..4e1692c 100644 --- a/tests/position-storage.test.ts +++ b/tests/position-storage.test.ts @@ -1,13 +1,13 @@ import { beforeEach, describe, expect, it } from "vitest"; -import { PositionStorageWrapper } from "./wrappers/position-storage"; +import { VaultStorageWrapper } from "./wrappers/vault-storage"; import { Cl } from "@stacks/transactions"; -describe("position storage tests", () => { +describe("vault storage tests", () => { const accounts = simnet.getAccounts(); - let positionStorageAsDeployer: PositionStorageWrapper; - let positionStorageAsAllowedCaller: PositionStorageWrapper; - let positionStorageAsAlice: PositionStorageWrapper; + let vaultStorageAsDeployer: VaultStorageWrapper; + let vaultStorageAsAllowedCaller: VaultStorageWrapper; + let vaultStorageAsAlice: VaultStorageWrapper; let deployer: string; let allowedCaller: string; @@ -18,60 +18,53 @@ describe("position storage tests", () => { allowedCaller = accounts.get("wallet_1")!; alice = accounts.get("wallet_2")!; - positionStorageAsDeployer = new PositionStorageWrapper( + vaultStorageAsDeployer = new VaultStorageWrapper( simnet, deployer, deployer ); - positionStorageAsAllowedCaller = new PositionStorageWrapper( + vaultStorageAsAllowedCaller = new VaultStorageWrapper( simnet, deployer, allowedCaller ); - positionStorageAsAlice = new PositionStorageWrapper( - simnet, - deployer, - alice - ); + vaultStorageAsAlice = new VaultStorageWrapper(simnet, deployer, alice); - positionStorageAsDeployer.setAllowCaller(allowedCaller, true); + vaultStorageAsDeployer.setAllowCaller(allowedCaller, true); }); describe("when call set-allow-caller", () => { describe("when caller is not an owner", () => { it("should error", async () => { - expect( - positionStorageAsAlice.setAllowCaller(allowedCaller, true) - ).toBeErr(Cl.uint(403)); + expect(vaultStorageAsAlice.setAllowCaller(allowedCaller, true)).toBeErr( + Cl.uint(403) + ); }); }); describe("when caller is an owner", () => { it("should set allow caller", async () => { - positionStorageAsDeployer.setAllowCaller( - accounts.get("wallet_3")!, - true - ); + vaultStorageAsDeployer.setAllowCaller(accounts.get("wallet_3")!, true); expect( - positionStorageAsAlice.isAllowCaller(accounts.get("wallet_3")!) + vaultStorageAsAlice.isAllowCaller(accounts.get("wallet_3")!) ).toBeOk(Cl.bool(true)); }); }); }); - describe("when call set-position-status", () => { + describe("when call set-vault-status", () => { describe("when caller is not an allowed caller", () => { it("should error", async () => { - expect(positionStorageAsAlice.setPositionStatus(alice, 1)).toBeErr( + expect(vaultStorageAsAlice.setVaultStatus(alice, 1)).toBeErr( Cl.uint(403) ); }); }); describe("when caller is an allowed caller", () => { - it("should set position status", async () => { - positionStorageAsAllowedCaller.setPositionStatus(alice, 1); - expect(positionStorageAsAlice.getPosition(alice)).toBeOk( + it("should set vault status", async () => { + vaultStorageAsAllowedCaller.setVaultStatus(alice, 1); + expect(vaultStorageAsAlice.getVault(alice)).toBeOk( Cl.tuple({ arrayIndex: Cl.uint(0), collateral: Cl.uint(0), @@ -86,7 +79,7 @@ describe("position storage tests", () => { describe("when call increase-collateral", () => { describe("when caller is not an allowed caller", () => { it("should error", async () => { - expect(positionStorageAsAlice.increaseCollateral(alice, 100)).toBeErr( + expect(vaultStorageAsAlice.increaseCollateral(alice, 100)).toBeErr( Cl.uint(403) ); }); @@ -95,9 +88,9 @@ describe("position storage tests", () => { describe("when caller is an allowed caller", () => { it("should increase collateral", async () => { expect( - positionStorageAsAllowedCaller.increaseCollateral(alice, 100) + vaultStorageAsAllowedCaller.increaseCollateral(alice, 100) ).toBeOk(Cl.bool(true)); - expect(positionStorageAsAlice.getPosition(alice)).toBeOk( + expect(vaultStorageAsAlice.getVault(alice)).toBeOk( Cl.tuple({ arrayIndex: Cl.uint(0), collateral: Cl.uint(100), @@ -112,7 +105,7 @@ describe("position storage tests", () => { describe("when call increase-debt", () => { describe("when caller is not an allowed caller", () => { it("should error", async () => { - expect(positionStorageAsAlice.increaseDebt(alice, 100)).toBeErr( + expect(vaultStorageAsAlice.increaseDebt(alice, 100)).toBeErr( Cl.uint(403) ); }); @@ -121,12 +114,12 @@ describe("position storage tests", () => { describe("when caller is an allowed caller", () => { it("should increase debt", async () => { expect( - positionStorageAsAllowedCaller.increaseCollateral(alice, 100) + vaultStorageAsAllowedCaller.increaseCollateral(alice, 100) ).toBeOk(Cl.bool(true)); - expect(positionStorageAsAllowedCaller.increaseDebt(alice, 100)).toBeOk( + expect(vaultStorageAsAllowedCaller.increaseDebt(alice, 100)).toBeOk( Cl.bool(true) ); - expect(positionStorageAsAlice.getPosition(alice)).toBeOk( + expect(vaultStorageAsAlice.getVault(alice)).toBeOk( Cl.tuple({ arrayIndex: Cl.uint(0), collateral: Cl.uint(100), diff --git a/tests/user-entry.test.ts b/tests/user-entry.test.ts index 142831c..be0c487 100644 --- a/tests/user-entry.test.ts +++ b/tests/user-entry.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it } from "vitest"; import { SimpleOracleWrapper } from "./wrappers/simple-oracle"; -import { PositionStorageWrapper } from "./wrappers/position-storage"; +import { VaultStorageWrapper } from "./wrappers/vault-storage"; import { UserEntryWrapper } from "./wrappers/user-entry"; import { Cl } from "@stacks/transactions"; import { ConfigStorageWrapper } from "./wrappers/config-storage"; @@ -19,7 +19,7 @@ describe("user entry tests", () => { let configStorageAsDeployer: ConfigStorageWrapper; - let positionStorageAsDeployer: PositionStorageWrapper; + let vaultStorageAsDeployer: VaultStorageWrapper; let userEntryAsAlice: UserEntryWrapper; @@ -46,7 +46,7 @@ describe("user entry tests", () => { deployer ); - positionStorageAsDeployer = new PositionStorageWrapper( + vaultStorageAsDeployer = new VaultStorageWrapper( simnet, deployer, deployer @@ -55,7 +55,7 @@ describe("user entry tests", () => { userEntryAsAlice = new UserEntryWrapper(simnet, deployer, alice); expect( - positionStorageAsDeployer.setAllowCaller( + vaultStorageAsDeployer.setAllowCaller( userEntryAsAlice.getContractPrincipal(), true ) @@ -63,7 +63,7 @@ describe("user entry tests", () => { expect( configStorageAsDeployer.initialize( simpleOracleAsDeployer.getContractPrincipal(), - positionStorageAsDeployer.getContractPrincipal(), + vaultStorageAsDeployer.getContractPrincipal(), sBTC_PRINCIPAL ) ).toBeOk(Cl.bool(true)); @@ -71,14 +71,14 @@ describe("user entry tests", () => { simpleOracleAsFeeder.setPrice(sBTC_PRINCIPAL, String(200 * 1e8)); }); - describe("when new position", () => { + describe("when new vault", () => { describe("when injected incorrect dependency", () => { describe("when injected fake oracle", () => { it("should error", async () => { expect( - userEntryAsAlice.newPosition( + userEntryAsAlice.newVault( `${deployer}.fake-simple-oracle`, - positionStorageAsDeployer.getContractPrincipal(), + vaultStorageAsDeployer.getContractPrincipal(), sBTC_PRINCIPAL, 100, 100 @@ -87,12 +87,12 @@ describe("user entry tests", () => { }); }); - describe("when injected fake position storage", () => { + describe("when injected fake vault storage", () => { it("should error", async () => { expect( - userEntryAsAlice.newPosition( + userEntryAsAlice.newVault( simpleOracleAsDeployer.getContractPrincipal(), - `${deployer}.fake-position-storage`, + `${deployer}.fake-vault-storage`, sBTC_PRINCIPAL, 100, 100 @@ -104,9 +104,9 @@ describe("user entry tests", () => { describe("when injected fake collateral", () => { it("should error", async () => { expect( - userEntryAsAlice.newPosition( + userEntryAsAlice.newVault( simpleOracleAsDeployer.getContractPrincipal(), - positionStorageAsDeployer.getContractPrincipal(), + vaultStorageAsDeployer.getContractPrincipal(), `${deployer}.fake-sbtc`, 100, 100 @@ -117,18 +117,18 @@ describe("user entry tests", () => { }); describe("when injected correct dependency", () => { - it("should create new position", async () => { + it("should create new vault", async () => { expect( - userEntryAsAlice.newPosition( + userEntryAsAlice.newVault( simpleOracleAsDeployer.getContractPrincipal(), - positionStorageAsDeployer.getContractPrincipal(), + vaultStorageAsDeployer.getContractPrincipal(), sBTC_PRINCIPAL, 100, 100 ) ).toBeOk(Cl.bool(true)); - expect(positionStorageAsDeployer.getPosition(alice)).toBeOk( + expect(vaultStorageAsDeployer.getVault(alice)).toBeOk( Cl.tuple({ arrayIndex: Cl.uint(0), collateral: Cl.uint(100), diff --git a/tests/wrappers/user-entry.ts b/tests/wrappers/user-entry.ts index 99865d5..3b39f06 100644 --- a/tests/wrappers/user-entry.ts +++ b/tests/wrappers/user-entry.ts @@ -17,19 +17,19 @@ export class UserEntryWrapper implements WrapperInterface { return `${this.deployerAddress}.${this.contractName}`; } - newPosition( + newVault( oraclePrincipal: string, - positionStoragePrincipal: string, + vaultStoragePrincipal: string, collateralPrincipal: string, collateralAmount: number, stablecoinAmount: number ) { return this.simnet.callPublicFn( this.contractName, - "new-position", + "new-vault", [ Cl.principal(oraclePrincipal), - Cl.principal(positionStoragePrincipal), + Cl.principal(vaultStoragePrincipal), Cl.principal(collateralPrincipal), Cl.uint(collateralAmount), Cl.uint(stablecoinAmount), diff --git a/tests/wrappers/position-storage.ts b/tests/wrappers/vault-storage.ts similarity index 85% rename from tests/wrappers/position-storage.ts rename to tests/wrappers/vault-storage.ts index d95c4c1..fdf8144 100644 --- a/tests/wrappers/position-storage.ts +++ b/tests/wrappers/vault-storage.ts @@ -1,10 +1,10 @@ import { Simnet } from "@hirosystems/clarinet-sdk"; import { Cl, ClarityValue } from "@stacks/transactions"; -export class PositionStorageWrapper implements WrapperInterface { +export class VaultStorageWrapper implements WrapperInterface { simnet: Simnet; deployerAddress: string; - contractName: string = "position-storage"; + contractName: string = "vault-storage"; caller: string; constructor(simnet: Simnet, deployerAddress: string, caller: string) { @@ -35,19 +35,19 @@ export class PositionStorageWrapper implements WrapperInterface { ).result; } - setPositionStatus(borrower: string, status: number): ClarityValue { + setVaultStatus(borrower: string, status: number): ClarityValue { return this.simnet.callPublicFn( this.contractName, - "set-position-status", + "set-vault-status", [Cl.principal(borrower), Cl.uint(status)], this.caller ).result; } - getPosition(borrower: string): ClarityValue { + getVault(borrower: string): ClarityValue { return this.simnet.callReadOnlyFn( this.contractName, - "get-position", + "get-vault", [Cl.principal(borrower)], this.caller ).result; From 942806edb211dd735ef40986cbbf7014d6c14b3e Mon Sep 17 00:00:00 2001 From: spicysquid168 Date: Tue, 7 May 2024 16:09:35 +0700 Subject: [PATCH 3/5] wip: add only not active vault check --- contracts/storages/config-storage.clar | 4 ++-- contracts/storages/vault-storage.clar | 4 ++-- contracts/traits/vault-storage-trait.clar | 20 +++++++++++++++++++ contracts/user-entry.clar | 11 ++++++---- tests/user-entry.test.ts | 6 +++--- ...-storage.test.ts => vault-storage.test.ts} | 8 ++++---- 6 files changed, 38 insertions(+), 15 deletions(-) rename tests/{position-storage.test.ts => vault-storage.test.ts} (97%) diff --git a/contracts/storages/config-storage.clar b/contracts/storages/config-storage.clar index 8b09949..da85ae2 100644 --- a/contracts/storages/config-storage.clar +++ b/contracts/storages/config-storage.clar @@ -13,8 +13,8 @@ ;; constants ;; -(define-constant ERR_FORBIDDEN (err u403)) -(define-constant ERR_NOT_INITIALIZED (err u501)) +(define-constant ERR_FORBIDDEN (err u3001)) +(define-constant ERR_NOT_INITIALIZED (err u3002)) ;; data vars ;; diff --git a/contracts/storages/vault-storage.clar b/contracts/storages/vault-storage.clar index 13430f7..55a902e 100644 --- a/contracts/storages/vault-storage.clar +++ b/contracts/storages/vault-storage.clar @@ -14,8 +14,8 @@ ;; constants ;; -(define-constant ERR_INVALID_VAULT (err u401)) -(define-constant ERR_FORBIDDEN (err u403)) +(define-constant ERR_INVALID_VAULT (err u2001)) +(define-constant ERR_FORBIDDEN (err u2002)) ;; data vars ;; diff --git a/contracts/traits/vault-storage-trait.clar b/contracts/traits/vault-storage-trait.clar index 84cd05c..6bcce2a 100644 --- a/contracts/traits/vault-storage-trait.clar +++ b/contracts/traits/vault-storage-trait.clar @@ -1,10 +1,30 @@ ;; title: vault-storage-trait ;; description: A trait defines functions of vault storage contract +;; (cumulate-balance +;; (principal) +;; (response (tuple +;; (previous-user-balance uint) +;; (current-balance uint) +;; (balance-increase uint) +;; (index uint)) +;; uint)) (define-trait vault-storage-trait ( (set-vault-status (principal uint) (response bool uint)) (increase-collateral (principal uint) (response bool uint)) (increase-debt (principal uint) (response bool uint)) + (get-vault + (principal) + (response + (tuple + (debt uint) + (collateral uint) + (status uint) + (arrayIndex uint) + ) + uint + ) + ) ) ) \ No newline at end of file diff --git a/contracts/user-entry.clar b/contracts/user-entry.clar index c8cf899..bbb0599 100644 --- a/contracts/user-entry.clar +++ b/contracts/user-entry.clar @@ -15,10 +15,11 @@ ;; constants ;; -(define-constant ERR_BAD_ORACLE (err u401)) -(define-constant ERR_BAD_VAULT_STORAGE (err u402)) -(define-constant ERR_BAD_COLLATERAL (err u403)) -(define-constant ERR_GET_CONFIGS (err u501)) +(define-constant ERR_BAD_ORACLE (err u1001)) +(define-constant ERR_BAD_VAULT_STORAGE (err u1002)) +(define-constant ERR_BAD_COLLATERAL (err u1003)) +(define-constant ERR_VAULT_ALREADY_EXISTS (err u1004)) +(define-constant ERR_GET_CONFIGS (err u1005)) ;; data vars ;; @@ -45,7 +46,9 @@ (let ( (price (try! (contract-call? oracle fetch-price collateral))) + (vault-data (try! (contract-call? vault-storage get-vault tx-sender))) ) + (asserts! (not (is-eq (get status vault-data) u1)) ERR_VAULT_ALREADY_EXISTS) ;; set vault status (try! (contract-call? vault-storage set-vault-status tx-sender u1)) ;; increase collateral diff --git a/tests/user-entry.test.ts b/tests/user-entry.test.ts index be0c487..9570456 100644 --- a/tests/user-entry.test.ts +++ b/tests/user-entry.test.ts @@ -83,7 +83,7 @@ describe("user entry tests", () => { 100, 100 ) - ).toBeErr(Cl.uint(401)); + ).toBeErr(Cl.uint(1001)); }); }); @@ -97,7 +97,7 @@ describe("user entry tests", () => { 100, 100 ) - ).toBeErr(Cl.uint(402)); + ).toBeErr(Cl.uint(1002)); }); }); @@ -111,7 +111,7 @@ describe("user entry tests", () => { 100, 100 ) - ).toBeErr(Cl.uint(403)); + ).toBeErr(Cl.uint(1003)); }); }); }); diff --git a/tests/position-storage.test.ts b/tests/vault-storage.test.ts similarity index 97% rename from tests/position-storage.test.ts rename to tests/vault-storage.test.ts index 4e1692c..c7ca76a 100644 --- a/tests/position-storage.test.ts +++ b/tests/vault-storage.test.ts @@ -37,7 +37,7 @@ describe("vault storage tests", () => { describe("when caller is not an owner", () => { it("should error", async () => { expect(vaultStorageAsAlice.setAllowCaller(allowedCaller, true)).toBeErr( - Cl.uint(403) + Cl.uint(2002) ); }); }); @@ -56,7 +56,7 @@ describe("vault storage tests", () => { describe("when caller is not an allowed caller", () => { it("should error", async () => { expect(vaultStorageAsAlice.setVaultStatus(alice, 1)).toBeErr( - Cl.uint(403) + Cl.uint(2002) ); }); }); @@ -80,7 +80,7 @@ describe("vault storage tests", () => { describe("when caller is not an allowed caller", () => { it("should error", async () => { expect(vaultStorageAsAlice.increaseCollateral(alice, 100)).toBeErr( - Cl.uint(403) + Cl.uint(2002) ); }); }); @@ -106,7 +106,7 @@ describe("vault storage tests", () => { describe("when caller is not an allowed caller", () => { it("should error", async () => { expect(vaultStorageAsAlice.increaseDebt(alice, 100)).toBeErr( - Cl.uint(403) + Cl.uint(2002) ); }); }); From 23f2e9f50fa0ef27f24934ef61014d9e06624bb7 Mon Sep 17 00:00:00 2001 From: spicysquid168 Date: Tue, 7 May 2024 16:20:50 +0700 Subject: [PATCH 4/5] wip: add min debt check --- contracts/storages/config-storage.clar | 26 +++++++++++++++++++++++++- contracts/user-entry.clar | 6 ++++-- tests/user-entry.test.ts | 8 ++++---- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/contracts/storages/config-storage.clar b/contracts/storages/config-storage.clar index da85ae2..1a6b512 100644 --- a/contracts/storages/config-storage.clar +++ b/contracts/storages/config-storage.clar @@ -22,6 +22,7 @@ (define-data-var vault-storage principal tx-sender) (define-data-var oracle principal tx-sender) (define-data-var collateral principal tx-sender) +(define-data-var min-debt uint u100000000000) (define-data-var is-initialized bool false) @@ -64,7 +65,8 @@ (ok { oracle: (var-get oracle), vault-storage: (var-get vault-storage), - collateral: (var-get collateral) + collateral: (var-get collateral), + min-debt: (var-get min-debt) }) ) ) @@ -82,6 +84,28 @@ ) ) +(define-public (set-vault-storage + (new-vault-storage principal) + ) + (begin + (try! (assert-is-owner)) + ;; #[allow(unchecked_data)] + (var-set vault-storage new-vault-storage) + (ok true) + ) +) + +(define-public (set-min-debt + (new-min-debt uint) + ) + (begin + (try! (assert-is-owner)) + ;; #[allow(unchecked_data)] + (var-set min-debt new-min-debt) + (ok true) + ) +) + (define-public (transfer-ownership (new-owner principal) ) diff --git a/contracts/user-entry.clar b/contracts/user-entry.clar index bbb0599..4e8f751 100644 --- a/contracts/user-entry.clar +++ b/contracts/user-entry.clar @@ -20,6 +20,7 @@ (define-constant ERR_BAD_COLLATERAL (err u1003)) (define-constant ERR_VAULT_ALREADY_EXISTS (err u1004)) (define-constant ERR_GET_CONFIGS (err u1005)) +(define-constant ERR_DEBT_TOO_SMALL (err u1006)) ;; data vars ;; @@ -34,7 +35,7 @@ (vault-storage ) (collateral ) (collateral-amount uint) - (stable-coin-amount uint) + (stablecoin-amount uint) ) (let ( @@ -49,12 +50,13 @@ (vault-data (try! (contract-call? vault-storage get-vault tx-sender))) ) (asserts! (not (is-eq (get status vault-data) u1)) ERR_VAULT_ALREADY_EXISTS) + (asserts! (>= stablecoin-amount (get min-debt configs)) ERR_DEBT_TOO_SMALL) ;; set vault status (try! (contract-call? vault-storage set-vault-status tx-sender u1)) ;; increase collateral (try! (contract-call? vault-storage increase-collateral tx-sender collateral-amount)) ;; increase debt - (try! (contract-call? vault-storage increase-debt tx-sender stable-coin-amount)) + (try! (contract-call? vault-storage increase-debt tx-sender stablecoin-amount)) ) (ok true) ) diff --git a/tests/user-entry.test.ts b/tests/user-entry.test.ts index 9570456..5e84cc5 100644 --- a/tests/user-entry.test.ts +++ b/tests/user-entry.test.ts @@ -123,16 +123,16 @@ describe("user entry tests", () => { simpleOracleAsDeployer.getContractPrincipal(), vaultStorageAsDeployer.getContractPrincipal(), sBTC_PRINCIPAL, - 100, - 100 + 100000000, + 200000000000 ) ).toBeOk(Cl.bool(true)); expect(vaultStorageAsDeployer.getVault(alice)).toBeOk( Cl.tuple({ arrayIndex: Cl.uint(0), - collateral: Cl.uint(100), - debt: Cl.uint(100), + collateral: Cl.uint(100000000), + debt: Cl.uint(200000000000), status: Cl.uint(1), }) ); From 4016c98933756fa4776977fe2739c1c63a44d6e4 Mon Sep 17 00:00:00 2001 From: spicysquid168 Date: Tue, 7 May 2024 17:01:12 +0700 Subject: [PATCH 5/5] wip: mint stablecoin --- Clarinet.toml | 10 +++ contracts/stablecoin.clar | 98 ++++++++++++++++++++++++++ contracts/storages/config-storage.clar | 7 +- contracts/traits/stablecoin-trait.clar | 6 ++ contracts/user-entry.clar | 6 ++ tests/user-entry.test.ts | 22 +++++- tests/wrappers/config-storage.ts | 8 ++- tests/wrappers/stablecoin.ts | 28 ++++++++ tests/wrappers/user-entry.ts | 2 + 9 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 contracts/stablecoin.clar create mode 100644 contracts/traits/stablecoin-trait.clar create mode 100644 tests/wrappers/stablecoin.ts diff --git a/Clarinet.toml b/Clarinet.toml index 7d5ec65..2b088e0 100644 --- a/Clarinet.toml +++ b/Clarinet.toml @@ -28,6 +28,11 @@ path = 'contracts/traits/vault-storage-trait.clar' clarity_version = 2 epoch = 2.4 +[contracts.stablecoin-trait] +path = 'contracts/traits/stablecoin-trait.clar' +clarity_version = 2 +epoch = 2.4 + [contracts.simple-oracle] path = 'contracts/oracles/simple-oracle.clar' clarity_version = 2 @@ -43,6 +48,11 @@ path = 'contracts/storages/config-storage.clar' clarity_version = 2 epoch = 2.4 +[contracts.stablecoin] +path = 'contracts/stablecoin.clar' +clarity_version = 2 +epoch = 2.4 + [contracts.ownable-trait] path = 'contracts/traits/ownable-trait.clar' clarity_version = 2 diff --git a/contracts/stablecoin.clar b/contracts/stablecoin.clar new file mode 100644 index 0000000..28c4d46 --- /dev/null +++ b/contracts/stablecoin.clar @@ -0,0 +1,98 @@ +;; title: stablecoin +;; version: +;; summary: +;; description: + +;; traits +;; +(impl-trait .ft-trait.ft-trait) +(impl-trait .stablecoin-trait.stablecoin-trait) + +;; token definitions +;; +(define-fungible-token stablecoin) + +;; constants +;; +(define-constant deployer-principal tx-sender) + +;; errors +;; +(define-constant ERR_INITIALIZED (err u4001)) +(define-constant ERR_FORBIDDEN (err u4002)) + +;; data vars +;; +(define-data-var token-uri (optional (string-utf8 256)) none) + +;; data maps +;; +(define-map minters principal bool) + +;; public functions +;; +(define-public (transfer (amount uint) (from principal) (to principal) (memo (optional (buff 34)))) + (begin + (asserts! (is-eq from tx-sender) ERR_FORBIDDEN) + ;; #[allow(unchecked_data)] + (match (ft-transfer? stablecoin amount from to) + response (begin + (print memo) + (ok response) + ) + error (err error) + ) + ) +) + +(define-public (mint + (to principal) + (amount uint) + ) + (begin + (asserts! (default-to false (map-get? minters contract-caller)) ERR_FORBIDDEN) + ;; #[allow(unchecked_data)] + (try! (ft-mint? stablecoin amount to)) + (ok true) + ) +) + +;; read only functions +;; +(define-read-only (get-name) (ok "stablecoin")) + +(define-read-only (get-symbol) (ok "USD")) + +(define-read-only (get-decimals) (ok u8)) + +(define-read-only (get-balance (who principal)) + (ok (ft-get-balance stablecoin who)) +) + +(define-read-only (get-total-supply) (ok (ft-get-supply stablecoin))) + +(define-read-only (get-token-uri) + (ok (var-get token-uri)) +) + +;; admin functions +;; +(define-public (set-token-uri (value (string-utf8 256))) + (if (is-eq tx-sender deployer-principal) + ;; #[allow(unchecked_data)] + (ok (var-set token-uri (some value))) + ERR_FORBIDDEN + ) +) + +(define-public (set-minter + (minter principal) + (status bool) + ) + (begin + (asserts! (is-eq tx-sender deployer-principal) ERR_FORBIDDEN) + ;; #[allow(unchecked_data)] + (map-set minters minter status) + (ok true) + ) +) diff --git a/contracts/storages/config-storage.clar b/contracts/storages/config-storage.clar index 1a6b512..1b1bcae 100644 --- a/contracts/storages/config-storage.clar +++ b/contracts/storages/config-storage.clar @@ -23,6 +23,7 @@ (define-data-var oracle principal tx-sender) (define-data-var collateral principal tx-sender) (define-data-var min-debt uint u100000000000) +(define-data-var stablecoin principal tx-sender) (define-data-var is-initialized bool false) @@ -34,6 +35,7 @@ (init-oracle principal) (init-vault-storage principal) (init-collateral principal) + (init-stablecoin principal) ) (begin ;; #[allow(unchecked_data)] @@ -42,6 +44,8 @@ (var-set vault-storage init-vault-storage) ;; #[allow(unchecked_data)] (var-set collateral init-collateral) + ;; #[allow(unchecked_data)] + (var-set stablecoin init-stablecoin) (var-set is-initialized true) (ok true) ) @@ -66,7 +70,8 @@ oracle: (var-get oracle), vault-storage: (var-get vault-storage), collateral: (var-get collateral), - min-debt: (var-get min-debt) + min-debt: (var-get min-debt), + stablecoin: (var-get stablecoin) }) ) ) diff --git a/contracts/traits/stablecoin-trait.clar b/contracts/traits/stablecoin-trait.clar new file mode 100644 index 0000000..93f8c8f --- /dev/null +++ b/contracts/traits/stablecoin-trait.clar @@ -0,0 +1,6 @@ +(define-trait stablecoin-trait + ( + ;; Mint new tokens + (mint (principal uint) (response bool uint)) + ) +) diff --git a/contracts/user-entry.clar b/contracts/user-entry.clar index 4e8f751..02f9daf 100644 --- a/contracts/user-entry.clar +++ b/contracts/user-entry.clar @@ -8,6 +8,7 @@ ;; (use-trait oracle-trait .oracle-trait.oracle-trait) (use-trait vault-storage-trait .vault-storage-trait.vault-storage-trait) +(use-trait stablecoin-trait .stablecoin-trait.stablecoin-trait) (use-trait ft .ft-trait.ft-trait) ;; token definitions @@ -21,6 +22,7 @@ (define-constant ERR_VAULT_ALREADY_EXISTS (err u1004)) (define-constant ERR_GET_CONFIGS (err u1005)) (define-constant ERR_DEBT_TOO_SMALL (err u1006)) +(define-constant ERR_BAD_STABLECOIN (err u1007)) ;; data vars ;; @@ -34,6 +36,7 @@ (oracle ) (vault-storage ) (collateral ) + (stablecoin ) (collateral-amount uint) (stablecoin-amount uint) ) @@ -44,6 +47,7 @@ (asserts! (is-eq (contract-of oracle) (get oracle configs)) ERR_BAD_ORACLE) (asserts! (is-eq (contract-of vault-storage) (get vault-storage configs)) ERR_BAD_VAULT_STORAGE) (asserts! (is-eq (contract-of collateral) (get collateral configs)) ERR_BAD_COLLATERAL) + (asserts! (is-eq (contract-of stablecoin) (get stablecoin configs)) ERR_BAD_STABLECOIN) (let ( (price (try! (contract-call? oracle fetch-price collateral))) @@ -57,6 +61,8 @@ (try! (contract-call? vault-storage increase-collateral tx-sender collateral-amount)) ;; increase debt (try! (contract-call? vault-storage increase-debt tx-sender stablecoin-amount)) + ;; mint stablecoin to user + (try! (contract-call? stablecoin mint tx-sender stablecoin-amount)) ) (ok true) ) diff --git a/tests/user-entry.test.ts b/tests/user-entry.test.ts index 5e84cc5..6a97e89 100644 --- a/tests/user-entry.test.ts +++ b/tests/user-entry.test.ts @@ -5,6 +5,7 @@ import { UserEntryWrapper } from "./wrappers/user-entry"; import { Cl } from "@stacks/transactions"; import { ConfigStorageWrapper } from "./wrappers/config-storage"; import { sBTC_PRINCIPAL } from "./constants"; +import { StablecoinWrapper } from "./wrappers/stablecoin"; /* The test below is an example. To learn more, read the testing documentation here: @@ -17,6 +18,8 @@ describe("user entry tests", () => { let simpleOracleAsDeployer: SimpleOracleWrapper; let simpleOracleAsFeeder: SimpleOracleWrapper; + let stablecoinAsDeployer: StablecoinWrapper; + let configStorageAsDeployer: ConfigStorageWrapper; let vaultStorageAsDeployer: VaultStorageWrapper; @@ -40,6 +43,8 @@ describe("user entry tests", () => { simpleOracleAsFeeder = new SimpleOracleWrapper(simnet, deployer, feeder); expect(simpleOracleAsDeployer.setFeeder(feeder)).toBeOk(Cl.bool(true)); + stablecoinAsDeployer = new StablecoinWrapper(simnet, deployer, deployer); + configStorageAsDeployer = new ConfigStorageWrapper( simnet, deployer, @@ -54,6 +59,12 @@ describe("user entry tests", () => { userEntryAsAlice = new UserEntryWrapper(simnet, deployer, alice); + expect( + stablecoinAsDeployer.setMinter( + userEntryAsAlice.getContractPrincipal(), + true + ) + ).toBeOk(Cl.bool(true)); expect( vaultStorageAsDeployer.setAllowCaller( userEntryAsAlice.getContractPrincipal(), @@ -64,7 +75,8 @@ describe("user entry tests", () => { configStorageAsDeployer.initialize( simpleOracleAsDeployer.getContractPrincipal(), vaultStorageAsDeployer.getContractPrincipal(), - sBTC_PRINCIPAL + sBTC_PRINCIPAL, + stablecoinAsDeployer.getContractPrincipal() ) ).toBeOk(Cl.bool(true)); @@ -80,6 +92,7 @@ describe("user entry tests", () => { `${deployer}.fake-simple-oracle`, vaultStorageAsDeployer.getContractPrincipal(), sBTC_PRINCIPAL, + stablecoinAsDeployer.getContractPrincipal(), 100, 100 ) @@ -94,6 +107,7 @@ describe("user entry tests", () => { simpleOracleAsDeployer.getContractPrincipal(), `${deployer}.fake-vault-storage`, sBTC_PRINCIPAL, + stablecoinAsDeployer.getContractPrincipal(), 100, 100 ) @@ -108,6 +122,7 @@ describe("user entry tests", () => { simpleOracleAsDeployer.getContractPrincipal(), vaultStorageAsDeployer.getContractPrincipal(), `${deployer}.fake-sbtc`, + stablecoinAsDeployer.getContractPrincipal(), 100, 100 ) @@ -123,7 +138,8 @@ describe("user entry tests", () => { simpleOracleAsDeployer.getContractPrincipal(), vaultStorageAsDeployer.getContractPrincipal(), sBTC_PRINCIPAL, - 100000000, + stablecoinAsDeployer.getContractPrincipal(), + 3000000000, 200000000000 ) ).toBeOk(Cl.bool(true)); @@ -131,7 +147,7 @@ describe("user entry tests", () => { expect(vaultStorageAsDeployer.getVault(alice)).toBeOk( Cl.tuple({ arrayIndex: Cl.uint(0), - collateral: Cl.uint(100000000), + collateral: Cl.uint(3000000000), debt: Cl.uint(200000000000), status: Cl.uint(1), }) diff --git a/tests/wrappers/config-storage.ts b/tests/wrappers/config-storage.ts index bffa429..a60d406 100644 --- a/tests/wrappers/config-storage.ts +++ b/tests/wrappers/config-storage.ts @@ -19,16 +19,18 @@ export class ConfigStorageWrapper implements WrapperInterface { initialize( oraclePrincipal: string, - positionStoragePrincipal: string, - collateralPrincipal: string + vaultStoragePrincipal: string, + collateralPrincipal: string, + stablecoinPrincipal: string ): ClarityValue { return simnet.callPublicFn( this.contractName, "initialize", [ Cl.principal(oraclePrincipal), - Cl.principal(positionStoragePrincipal), + Cl.principal(vaultStoragePrincipal), Cl.principal(collateralPrincipal), + Cl.principal(stablecoinPrincipal), ], this.caller ).result; diff --git a/tests/wrappers/stablecoin.ts b/tests/wrappers/stablecoin.ts new file mode 100644 index 0000000..4c336f3 --- /dev/null +++ b/tests/wrappers/stablecoin.ts @@ -0,0 +1,28 @@ +import { Simnet } from "@hirosystems/clarinet-sdk"; +import { Cl, ClarityValue } from "@stacks/transactions"; + +export class StablecoinWrapper { + simnet: Simnet; + deployerAddress: string; + contractName: string = "stablecoin"; + caller: string; + + constructor(simnet: Simnet, deployerAddress: string, caller: string) { + this.simnet = simnet; + this.deployerAddress = deployerAddress; + this.caller = caller; + } + + getContractPrincipal(): string { + return `${this.deployerAddress}.${this.contractName}`; + } + + setMinter(minterPrincipal: string, isAllow: boolean): ClarityValue { + return this.simnet.callPublicFn( + this.contractName, + "set-minter", + [Cl.principal(minterPrincipal), Cl.bool(isAllow)], + this.caller + ).result; + } +} diff --git a/tests/wrappers/user-entry.ts b/tests/wrappers/user-entry.ts index 3b39f06..15b3ab7 100644 --- a/tests/wrappers/user-entry.ts +++ b/tests/wrappers/user-entry.ts @@ -21,6 +21,7 @@ export class UserEntryWrapper implements WrapperInterface { oraclePrincipal: string, vaultStoragePrincipal: string, collateralPrincipal: string, + stablecoinPrincipal: string, collateralAmount: number, stablecoinAmount: number ) { @@ -31,6 +32,7 @@ export class UserEntryWrapper implements WrapperInterface { Cl.principal(oraclePrincipal), Cl.principal(vaultStoragePrincipal), Cl.principal(collateralPrincipal), + Cl.principal(stablecoinPrincipal), Cl.uint(collateralAmount), Cl.uint(stablecoinAmount), ],