mirror of
https://github.com/zhigang1992/liquid-stacking.git
synced 2026-04-29 12:35:48 +08:00
fix: account for locked stx
This commit is contained in:
@@ -235,6 +235,10 @@ epoch = 2.4
|
||||
path = "contracts/regtest-boot.clar"
|
||||
epoch = 2.4
|
||||
|
||||
[contracts.simnet-boot]
|
||||
path = "contracts/simnet-boot.clar"
|
||||
epoch = 2.4
|
||||
|
||||
[contracts.amm-swap-pool-v1-1]
|
||||
path = "contracts_modules/alex_v1/pool/amm-swap-pool-v1-1.clar"
|
||||
depends_on = ["trait-ownable", "trait-sip-010", "token-amm-swap-pool-v1-1"]
|
||||
|
||||
60
contracts/simnet-boot.clar
Normal file
60
contracts/simnet-boot.clar
Normal file
@@ -0,0 +1,60 @@
|
||||
(impl-trait .proposal-trait.proposal-trait)
|
||||
|
||||
(define-public (execute (sender principal))
|
||||
(begin
|
||||
(try! (contract-call? .lisa-dao set-extensions (list
|
||||
{ extension: .lqstx-mint-endpoint, enabled: false }
|
||||
{ extension: .lqstx-mint-endpoint-v1-01, enabled: true }
|
||||
{ extension: .lqstx-vault, enabled: true }
|
||||
{ extension: .treasury, enabled: true }
|
||||
{ extension: .token-vesting, enabled: true }
|
||||
{ extension: .public-pools-strategy-manager, enabled: true }
|
||||
{ extension: .lisa-rebase, enabled: true }
|
||||
{ extension: .rebase-1, enabled: true }
|
||||
{ extension: .operators, enabled: true }
|
||||
)))
|
||||
|
||||
;; Set initial operators
|
||||
(try! (contract-call? .operators set-operators (list
|
||||
;; three from ALEX
|
||||
{ operator: 'SP3BQ65DRM8DMTYDD5HWMN60EYC0JFS5NC2V5CWW7, enabled: true }
|
||||
{ operator: 'SPHFAXDZVFHMY8YR3P9J7ZCV6N89SBET203ZAY25, enabled: true }
|
||||
{ operator: 'SPSZ26REB731JN8H00TD010S600F4AB4Z8F0JRB7, enabled: true }
|
||||
;; three from Ryder/FAST Pool
|
||||
{ operator: 'SP12BFYTH3NJ6N63KE0S50GHSYV0M91NGQND2B704, enabled: true }
|
||||
{ operator: 'SP1ZPTDQ3801C1AYEZ37NJWNDZ3HM60HC2TCFP228, enabled: true }
|
||||
{ operator: 'SPGAB1P3YV109E22KXFJYM63GK0G21BYX50CQ80B, enabled: true }
|
||||
)))
|
||||
;; Set operator signal threshold, i.e. 4-of-6
|
||||
(try! (contract-call? .operators set-proposal-threshold 4))
|
||||
|
||||
;; Set initial strategy managers, sender is the deployer
|
||||
;; TODO add manager
|
||||
(try! (contract-call? .public-pools-strategy-manager set-authorised-manager sender true))
|
||||
|
||||
;; Mint max LISA token supply (1bn)
|
||||
(try! (contract-call? .token-lisa dao-mint-many (list
|
||||
{ recipient: .treasury, amount: u1000000000000000 }
|
||||
)))
|
||||
|
||||
;; Enable whitelist
|
||||
(try! (contract-call? .lqstx-mint-endpoint-v1-01 set-use-whitelist false))
|
||||
(try! (contract-call? .lqstx-mint-endpoint-v1-01 set-whitelisted-many
|
||||
(list
|
||||
'SP3BQ65DRM8DMTYDD5HWMN60EYC0JFS5NC2V5CWW7
|
||||
'SP2VZBR9GCVM33BN0WXA05VJP6QV7CJ3Z3SQKJ5HH
|
||||
'SP12BFYTH3NJ6N63KE0S50GHSYV0M91NGQND2B704
|
||||
'SPGAB1P3YV109E22KXFJYM63GK0G21BYX50CQ80B
|
||||
'SPFJVM9Y1A4KJ31T8ZBDESZH36YGPDAZ9WXEFC53
|
||||
)
|
||||
(list
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
)))
|
||||
(try! (contract-call? .lqstx-mint-endpoint-v1-01 set-paused false))
|
||||
(ok true)
|
||||
)
|
||||
)
|
||||
@@ -90,7 +90,8 @@
|
||||
)
|
||||
|
||||
(define-private (get-member-balance-iter (member <pool-member>) (accumulator uint))
|
||||
(+ (stx-get-balance (contract-of member)) accumulator)
|
||||
(let ((member-account (stx-account (contract-of member))))
|
||||
(+ (get locked member-account) (get unlocked member-account) accumulator))
|
||||
)
|
||||
|
||||
(define-read-only (get-total-member-balances)
|
||||
|
||||
@@ -39,6 +39,7 @@ genesis:
|
||||
- pox
|
||||
- pox-2
|
||||
- pox-3
|
||||
- pox-4
|
||||
- lockup
|
||||
- costs-2
|
||||
- costs-3
|
||||
@@ -53,9 +54,6 @@ plan:
|
||||
emulated-sender: SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE
|
||||
path: "./.cache/requirements/SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.clar"
|
||||
clarity-version: 1
|
||||
epoch: "2.0"
|
||||
- id: 1
|
||||
transactions:
|
||||
- emulated-contract-publish:
|
||||
contract-name: trait-sip-010
|
||||
emulated-sender: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM
|
||||
@@ -101,8 +99,8 @@ plan:
|
||||
emulated-sender: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM
|
||||
path: contracts_modules/alex_v1/traits/trait-vault.clar
|
||||
clarity-version: 1
|
||||
epoch: "2.05"
|
||||
- id: 2
|
||||
epoch: "2.1"
|
||||
- id: 1
|
||||
transactions:
|
||||
- emulated-contract-publish:
|
||||
contract-name: pox-pools-1-cycle-v2
|
||||
@@ -230,7 +228,7 @@ plan:
|
||||
path: contracts/strategies/public-pools/fastpool-member.clar
|
||||
clarity-version: 2
|
||||
epoch: "2.4"
|
||||
- id: 3
|
||||
- id: 2
|
||||
transactions:
|
||||
- emulated-contract-publish:
|
||||
contract-name: xverse-member1
|
||||
@@ -358,13 +356,18 @@ plan:
|
||||
path: contracts/traits/rebase-strategy-trait.clar
|
||||
clarity-version: 2
|
||||
epoch: "2.4"
|
||||
- id: 4
|
||||
- id: 3
|
||||
transactions:
|
||||
- emulated-contract-publish:
|
||||
contract-name: regtest-boot
|
||||
emulated-sender: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM
|
||||
path: contracts/regtest-boot.clar
|
||||
clarity-version: 2
|
||||
- emulated-contract-publish:
|
||||
contract-name: simnet-boot
|
||||
emulated-sender: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM
|
||||
path: contracts/simnet-boot.clar
|
||||
clarity-version: 2
|
||||
- emulated-contract-publish:
|
||||
contract-name: sip-010-extensions-trait
|
||||
emulated-sender: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM
|
||||
|
||||
13
package.json
13
package.json
@@ -19,15 +19,18 @@
|
||||
},
|
||||
"author": "",
|
||||
"license": "BSL",
|
||||
"prettier": "@stacks/prettier-config",
|
||||
"dependencies": {
|
||||
"@hirosystems/clarinet-sdk": "^1.0.0",
|
||||
"@hirosystems/clarinet-sdk": "2.4.0-beta2",
|
||||
"@stacks/stacking": "6.11.4-pr.36558cf.0",
|
||||
"@stacks/prettier-config": "^0.0.10",
|
||||
"@stacks/transactions": "^6.9.0",
|
||||
"chokidar-cli": "^3.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^4.4.9",
|
||||
"vitest": "^0.34.4",
|
||||
"vitest-environment-clarinet": "^1.0.0",
|
||||
"vite": "^5.1.4",
|
||||
"vitest": "^1.3.1",
|
||||
"vitest-environment-clarinet": "^2.0.0",
|
||||
"yaml": "^2.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
321
tests/lqstx-mint-endpoint-with-public-pools.test.ts
Normal file
321
tests/lqstx-mint-endpoint-with-public-pools.test.ts
Normal file
@@ -0,0 +1,321 @@
|
||||
import { tx } from '@hirosystems/clarinet-sdk';
|
||||
import { BufferCV, Cl, ResponseOkCV, TupleCV, UIntCV, cvToString } from '@stacks/transactions';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
const mintDelay = 432;
|
||||
const accounts = simnet.getAccounts();
|
||||
const user = accounts.get('wallet_1')!;
|
||||
const oracle = accounts.get('wallet_2')!;
|
||||
const bot = accounts.get('wallet_3')!;
|
||||
const manager = accounts.get('deployer')!;
|
||||
const operator = accounts.get('wallet_4')!;
|
||||
|
||||
const contracts = {
|
||||
endpoint: 'lqstx-mint-endpoint-v1-01',
|
||||
registry: 'lqstx-mint-registry',
|
||||
vault: 'lqstx-vault',
|
||||
lqstx: 'token-lqstx',
|
||||
vlqstx: 'token-vlqstx',
|
||||
wstx: 'token-wstx',
|
||||
strategy: 'public-pools-strategy',
|
||||
rebase: 'lisa-rebase',
|
||||
rebase1: 'rebase-1',
|
||||
amm: 'amm-swap-pool-v1-1',
|
||||
wlqstx: 'token-wlqstx',
|
||||
dao: 'lisa-dao',
|
||||
boot: 'simnet-boot',
|
||||
manager: 'public-pools-strategy-manager',
|
||||
operators: 'operators',
|
||||
proposal: 'mock-proposal',
|
||||
};
|
||||
|
||||
const prepareTest = () =>
|
||||
simnet.mineBlock([
|
||||
tx.callPublicFn(
|
||||
contracts.dao,
|
||||
'construct',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.boot)],
|
||||
simnet.deployer
|
||||
),
|
||||
]);
|
||||
|
||||
const getRewardCycle = () => {
|
||||
return (
|
||||
simnet.callReadOnlyFn(
|
||||
contracts.endpoint,
|
||||
'get-reward-cycle',
|
||||
[Cl.uint(simnet.blockHeight)],
|
||||
user
|
||||
).result as ResponseOkCV<UIntCV>
|
||||
).value.value;
|
||||
};
|
||||
|
||||
const getBlocksToStartOfCycle = (cycle: bigint) => {
|
||||
return (
|
||||
Number(
|
||||
(
|
||||
simnet.callReadOnlyFn(
|
||||
contracts.endpoint,
|
||||
'get-first-burn-block-in-reward-cycle',
|
||||
[Cl.uint(cycle)],
|
||||
user
|
||||
).result as ResponseOkCV<UIntCV>
|
||||
).value
|
||||
) - simnet.blockHeight
|
||||
);
|
||||
};
|
||||
const goToNextCycle = () => {
|
||||
const cycle = getRewardCycle();
|
||||
const blocksToMine = getBlocksToStartOfCycle(cycle + 1n);
|
||||
|
||||
simnet.mineEmptyBlocks(blocksToMine);
|
||||
};
|
||||
|
||||
const requestMint = () =>
|
||||
simnet.callPublicFn(contracts.endpoint, 'request-mint', [Cl.uint(100e6)], user);
|
||||
|
||||
// lock 99 stx and request burn of 1 stx
|
||||
const requestBurn = () =>
|
||||
simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.rebase1, 'rebase', [], oracle),
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(contracts.manager, 'fund-strategy', [Cl.list([Cl.uint(100e6)])], manager),
|
||||
tx.callPublicFn(contracts.rebase1, 'rebase', [], oracle),
|
||||
tx.callPublicFn(contracts.rebase1, 'request-burn', [Cl.uint(1e6)], user),
|
||||
]);
|
||||
|
||||
describe(contracts.endpoint, () => {
|
||||
it('can request mint', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
const response = requestMint();
|
||||
expect(response.result).toBeOk(Cl.uint(1));
|
||||
});
|
||||
|
||||
it('can finalize mint', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
expect(requestMint().result).toBeOk(Cl.uint(1));
|
||||
|
||||
goToNextCycle();
|
||||
|
||||
const finaliseErr = simnet.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot);
|
||||
expect(finaliseErr.result).toBeErr(Cl.uint(1006));
|
||||
|
||||
simnet.mineEmptyBlocks(mintDelay + 1); // mint-delay
|
||||
|
||||
let responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(contracts.endpoint, 'revoke-mint', [Cl.uint(1)], user),
|
||||
]);
|
||||
expect(responses[0].result).toBeOk(Cl.bool(true));
|
||||
expect(responses[1].result).toBeErr(Cl.uint(1007));
|
||||
});
|
||||
|
||||
it('can revoke mint', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
expect(requestMint().result).toBeOk(Cl.uint(1));
|
||||
|
||||
let responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.endpoint, 'revoke-mint', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(contracts.endpoint, 'revoke-mint', [Cl.uint(1)], user),
|
||||
]);
|
||||
expect(responses[0].result).toBeErr(Cl.uint(1000));
|
||||
expect(responses[1].result).toBeOk(Cl.bool(true));
|
||||
|
||||
goToNextCycle();
|
||||
simnet.mineEmptyBlocks(mintDelay + 1);
|
||||
responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot),
|
||||
]);
|
||||
expect(responses[0].result).toBeErr(Cl.uint(1007));
|
||||
});
|
||||
|
||||
it('can request burn', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
expect(requestMint().result).toBeOk(Cl.uint(1));
|
||||
|
||||
goToNextCycle();
|
||||
simnet.mineEmptyBlocks(mintDelay + 1);
|
||||
|
||||
const responses = requestBurn();
|
||||
expect(responses[0].result).toBeOk(Cl.uint(0));
|
||||
expect(responses[1].result).toBeOk(Cl.bool(true));
|
||||
expect(responses[2].result).toBeOk(Cl.uint(100e6));
|
||||
expect(responses[3].result).toBeOk(Cl.uint(100e6));
|
||||
console.log(cvToString(responses[4].result));
|
||||
expect(responses[4].result).toBeOk(
|
||||
Cl.tuple({ 'request-id': Cl.uint(1), status: Cl.bufferFromHex('00') })
|
||||
);
|
||||
});
|
||||
|
||||
it('can finalize burn', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
expect(requestMint().result).toBeOk(Cl.uint(1));
|
||||
goToNextCycle();
|
||||
simnet.mineEmptyBlocks(mintDelay + 1);
|
||||
|
||||
const burnResponses = requestBurn();
|
||||
expect(burnResponses[0].result).toBeOk(Cl.uint(0));
|
||||
expect(burnResponses[1].result).toBeOk(Cl.bool(true));
|
||||
expect(burnResponses[2].result).toBeOk(Cl.uint(100e6));
|
||||
expect(burnResponses[3].result).toBeOk(Cl.uint(100e6));
|
||||
expect(burnResponses[4].result).toBeOk(
|
||||
Cl.tuple({ 'request-id': Cl.uint(1), status: Cl.bufferFromHex('00') })
|
||||
);
|
||||
|
||||
const responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.manager, 'refund-strategy', [Cl.list([Cl.bool(true)])], manager),
|
||||
tx.callPublicFn(contracts.rebase1, 'rebase', [], oracle),
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-burn', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(contracts.endpoint, 'revoke-burn', [Cl.uint(1)], user),
|
||||
]);
|
||||
expect(responses[0].result).toBeOk(Cl.uint(1e6));
|
||||
expect(responses[1].result).toBeOk(Cl.uint(100e6));
|
||||
expect(responses[2].result).toBeOk(Cl.bool(true));
|
||||
expect(responses[3].result).toBeErr(Cl.uint(1007));
|
||||
});
|
||||
|
||||
it('can revoke burn', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
expect(requestMint().result).toBeOk(Cl.uint(1));
|
||||
goToNextCycle();
|
||||
simnet.mineEmptyBlocks(mintDelay + 1);
|
||||
|
||||
const burnResponses = requestBurn();
|
||||
expect(burnResponses[0].result).toBeOk(Cl.uint(0));
|
||||
expect(burnResponses[1].result).toBeOk(Cl.bool(true));
|
||||
expect(burnResponses[2].result).toBeOk(Cl.uint(100e6));
|
||||
expect(burnResponses[3].result).toBeOk(Cl.uint(100e6));
|
||||
expect(burnResponses[4].result).toBeOk(
|
||||
Cl.tuple({ 'request-id': Cl.uint(1), status: Cl.bufferFromHex('00') })
|
||||
);
|
||||
|
||||
const responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.manager, 'refund-strategy', [Cl.list([Cl.bool(true)])], manager),
|
||||
tx.callPublicFn(contracts.endpoint, 'revoke-burn', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(contracts.endpoint, 'revoke-burn', [Cl.uint(1)], user),
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot),
|
||||
]);
|
||||
expect(responses[0].result).toBeOk(Cl.uint(1e6));
|
||||
expect(responses[1].result).toBeErr(Cl.uint(1000));
|
||||
expect(responses[2].result).toBeOk(Cl.bool(true));
|
||||
expect(responses[3].result).toBeErr(Cl.uint(1007));
|
||||
});
|
||||
|
||||
it('can interact with strategies', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
expect(requestMint().result).toBeOk(Cl.uint(1));
|
||||
|
||||
const cycle = (
|
||||
simnet.callReadOnlyFn(
|
||||
contracts.endpoint,
|
||||
'get-reward-cycle',
|
||||
[Cl.uint(simnet.blockHeight)],
|
||||
user
|
||||
).result as ResponseOkCV<UIntCV>
|
||||
).value.value;
|
||||
const blocksToMine =
|
||||
Number(
|
||||
(
|
||||
simnet.callReadOnlyFn(
|
||||
contracts.endpoint,
|
||||
'get-first-burn-block-in-reward-cycle',
|
||||
[Cl.uint(cycle + 1n)],
|
||||
user
|
||||
).result as UIntCV
|
||||
).value
|
||||
) - simnet.blockHeight;
|
||||
simnet.mineEmptyBlocks(blocksToMine - 100);
|
||||
|
||||
let responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(contracts.manager, 'fund-strategy', [Cl.list([Cl.uint(100e6)])], bot),
|
||||
tx.callPublicFn(contracts.manager, 'fund-strategy', [Cl.list([Cl.uint(100e6)])], manager),
|
||||
]);
|
||||
expect(responses[0].result).toBeErr(Cl.uint(1006)); // request pending
|
||||
expect(responses[1].result).toBeErr(Cl.uint(3000)); // not authorized
|
||||
expect(responses[2].result).toBeOk(Cl.uint(100e6)); // 100 stx transferred, 99 stx locked
|
||||
|
||||
const stxAccountFastPoolMember1 = simnet.runSnippet(
|
||||
`(stx-account '${simnet.deployer}.fastpool-member1)`
|
||||
) as TupleCV<{ locked: UIntCV }>;
|
||||
expect(stxAccountFastPoolMember1.data.locked).toBeUint(99e6);
|
||||
|
||||
goToNextCycle(); // go to the next cycle
|
||||
simnet.mineEmptyBlocks(mintDelay + 1); // mint-delay
|
||||
|
||||
responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(contracts.rebase1, 'request-burn', [Cl.uint(100e6)], user),
|
||||
tx.callPublicFn(contracts.rebase1, 'request-burn', [Cl.uint(1e6)], user),
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-burn', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(contracts.manager, 'refund-strategy', [Cl.list([Cl.bool(true)])], bot),
|
||||
tx.callPublicFn(contracts.manager, 'refund-strategy', [Cl.list([Cl.bool(true)])], manager),
|
||||
tx.callPublicFn(contracts.manager, 'refund-strategy', [Cl.list([Cl.bool(true)])], manager),
|
||||
tx.callPublicFn(contracts.rebase1, 'rebase', [], oracle),
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-burn', [Cl.uint(1)], bot),
|
||||
]);
|
||||
expect(responses[0].result).toBeOk(Cl.bool(true));
|
||||
expect(responses[1].result).toBeOk(
|
||||
Cl.tuple({ 'request-id': Cl.uint(1), status: Cl.bufferFromHex('00') })
|
||||
);
|
||||
console.log(responses[2].result);
|
||||
expect(responses[2].result).toBeErr(Cl.uint(1)); // not enough funds
|
||||
expect(responses[3].result).toBeErr(Cl.uint(1006)); // request pending
|
||||
expect(responses[4].result).toBeErr(Cl.uint(3000)); // not authorized
|
||||
expect(responses[5].result).toBeOk(Cl.uint(1e6)); // refund 1 stx
|
||||
expect(responses[6].result).toBeOk(Cl.uint(0)); // refund 0 stx
|
||||
expect(responses[7].result).toBeOk(Cl.uint(100e6)); // rebase 100 stx
|
||||
expect(responses[8].result).toBeErr(Cl.uint(1006)); // request pending
|
||||
|
||||
// refund remaining stx after unlock
|
||||
goToNextCycle();
|
||||
|
||||
responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.manager, 'refund-strategy', [Cl.list([Cl.bool(true)])], manager),
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-burn', [Cl.uint(1)], bot),
|
||||
]);
|
||||
console.log(responses.map(r => r.result));
|
||||
expect(responses[0].result).toBeOk(Cl.uint(99e6));
|
||||
expect(responses[1].result).toBeOk(Cl.bool(true));
|
||||
});
|
||||
|
||||
it('can set up amm pool', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
expect(requestMint().result).toBeOk(Cl.uint(1));
|
||||
|
||||
const cycle = getRewardCycle();
|
||||
const blocksToMine = getBlocksToStartOfCycle(cycle + 1n);
|
||||
simnet.mineEmptyBlocks(blocksToMine); // go to the next cycle
|
||||
|
||||
const finaliseErr = simnet.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot);
|
||||
expect(finaliseErr.result).toBeErr(Cl.uint(1006));
|
||||
|
||||
simnet.mineEmptyBlocks(mintDelay + 1); // mint-delay
|
||||
|
||||
let responses = simnet.mineBlock([
|
||||
tx.callPublicFn(contracts.rebase1, 'finalize-mint', [Cl.uint(1)], bot),
|
||||
tx.callPublicFn(
|
||||
contracts.amm,
|
||||
'create-pool',
|
||||
[
|
||||
Cl.principal(simnet.deployer + '.' + contracts.wstx),
|
||||
Cl.principal(simnet.deployer + '.' + contracts.wlqstx),
|
||||
Cl.uint(1e8),
|
||||
Cl.principal(user),
|
||||
Cl.uint(1e8),
|
||||
Cl.uint(1e8),
|
||||
],
|
||||
user
|
||||
),
|
||||
]);
|
||||
expect(responses[0].result).toBeOk(Cl.bool(true));
|
||||
expect(responses[1].result).toBeOk(Cl.bool(true));
|
||||
});
|
||||
});
|
||||
137
tests/operators.test.ts
Normal file
137
tests/operators.test.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { ParsedTransactionResult, tx } from '@hirosystems/clarinet-sdk';
|
||||
import { BooleanCV, Cl, IntCV, SomeCV, TupleCV, UIntCV } from '@stacks/transactions';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
const accounts = simnet.getAccounts();
|
||||
const user = accounts.get('wallet_1')!;
|
||||
const oracle = accounts.get('wallet_2')!;
|
||||
const bot = accounts.get('wallet_3')!;
|
||||
const manager = accounts.get('wallet_4')!;
|
||||
|
||||
const contracts = {
|
||||
endpoint: 'lqstx-mint-endpoint-v1-01',
|
||||
registry: 'lqstx-mint-registry',
|
||||
vault: 'lqstx-vault',
|
||||
lqstx: 'token-lqstx',
|
||||
vlqstx: 'token-vlqstx',
|
||||
wstx: 'token-wstx',
|
||||
strategy: 'mock-strategy',
|
||||
rebase: 'lisa-rebase',
|
||||
rebase1: 'rebase-mock',
|
||||
amm: 'amm-swap-pool-v1-1',
|
||||
wlqstx: 'token-wlqstx',
|
||||
dao: 'lisa-dao',
|
||||
boot: 'regtest-boot',
|
||||
manager: 'mock-strategy-manager',
|
||||
operators: 'operators',
|
||||
proposal: 'mock-proposal',
|
||||
};
|
||||
|
||||
const prepareTest = () =>
|
||||
simnet.mineBlock([
|
||||
tx.callPublicFn(
|
||||
contracts.dao,
|
||||
'construct',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.boot)],
|
||||
simnet.deployer
|
||||
),
|
||||
]);
|
||||
const expectProposalDataToBe = (proposedAt: number, signals: number, executed: boolean) => {
|
||||
const proposalData = simnet.getMapEntry(
|
||||
contracts.operators,
|
||||
'proposals',
|
||||
Cl.contractPrincipal(simnet.deployer, contracts.proposal)
|
||||
) as SomeCV<TupleCV<{ 'proposed-at': UIntCV; signals: IntCV; executed: BooleanCV }>>;
|
||||
expect(proposalData.value).toStrictEqual(
|
||||
Cl.tuple({
|
||||
'proposed-at': Cl.uint(proposedAt),
|
||||
signals: Cl.int(signals),
|
||||
executed: Cl.bool(executed),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
describe('operators contract', () => {
|
||||
it('operator extension works', () => {
|
||||
prepareTest().map((e: any) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
let responses = simnet.mineBlock([
|
||||
tx.callPublicFn(
|
||||
contracts.operators,
|
||||
'propose',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.proposal)],
|
||||
bot
|
||||
),
|
||||
tx.callPublicFn(
|
||||
contracts.operators,
|
||||
'propose',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.proposal)],
|
||||
simnet.deployer
|
||||
),
|
||||
]);
|
||||
expect(responses[0].result).toBeErr(Cl.uint(1001));
|
||||
expect(responses[1].result).toBeOk(Cl.bool(false));
|
||||
|
||||
responses = simnet.mineBlock([
|
||||
tx.callPublicFn(
|
||||
contracts.operators,
|
||||
'signal',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.proposal), Cl.bool(true)],
|
||||
bot
|
||||
),
|
||||
tx.callPublicFn(
|
||||
contracts.operators,
|
||||
'signal',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.proposal), Cl.bool(true)],
|
||||
manager
|
||||
),
|
||||
]);
|
||||
expect(responses[0].result).toBeErr(Cl.uint(1001));
|
||||
expect(responses[1].result).toBeOk(Cl.bool(true));
|
||||
});
|
||||
|
||||
it('signals should be reset when reproposed', () => {
|
||||
prepareTest().map((e: ParsedTransactionResult) => expect(e.result).toBeOk(Cl.bool(true)));
|
||||
|
||||
let responses = simnet.mineBlock([
|
||||
tx.callPublicFn(
|
||||
contracts.operators,
|
||||
'propose',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.proposal)],
|
||||
simnet.deployer
|
||||
),
|
||||
tx.callPublicFn(
|
||||
contracts.operators,
|
||||
'propose',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.proposal)],
|
||||
simnet.deployer
|
||||
),
|
||||
]);
|
||||
expect(responses[0].result).toBeOk(Cl.bool(false));
|
||||
expect(responses[1].result).toBeErr(Cl.uint(1005));
|
||||
expectProposalDataToBe(4, 1, false);
|
||||
|
||||
let responses2 = simnet.mineBlock([
|
||||
tx.callPublicFn(
|
||||
contracts.operators,
|
||||
'propose',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.proposal)],
|
||||
simnet.deployer
|
||||
),
|
||||
]);
|
||||
expect(responses2[0].result).toBeErr(Cl.uint(1005)); // not yet expired
|
||||
|
||||
simnet.mineEmptyBlocks(143);
|
||||
let responses3 = simnet.mineBlock([
|
||||
tx.callPublicFn(
|
||||
contracts.operators,
|
||||
'propose',
|
||||
[Cl.contractPrincipal(simnet.deployer, contracts.proposal)],
|
||||
simnet.deployer
|
||||
),
|
||||
]);
|
||||
expect(responses3[0].result).toBeOk(Cl.bool(false));
|
||||
|
||||
expectProposalDataToBe(149, 1, false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user