fix: account for locked stx

This commit is contained in:
friedger
2024-03-12 18:28:47 +01:00
parent 923f2a355c
commit 9a0244f7d2
7 changed files with 542 additions and 13 deletions

View File

@@ -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"]

View 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)
)
)

View File

@@ -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)

View File

@@ -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

View File

@@ -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"
}
}
}

View 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
View 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);
});
});