From 16c07e63a90fc4f7d0fe4937d977e6a64cee6ec3 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Fri, 1 Mar 2024 20:36:50 +0200 Subject: [PATCH 01/24] added property tests for pox-4 read only functions --- .../tests/pox-4/pox-4.prop.test.ts | 434 ++++++++++++++++++ 1 file changed, 434 insertions(+) create mode 100644 contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts new file mode 100644 index 0000000000..65dc88cc08 --- /dev/null +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -0,0 +1,434 @@ +import Cl, { ClarityType, bufferCV, isClarityType } from "@stacks/transactions"; +import { assert, describe, expect, it } from "vitest"; +import fc from "fast-check"; + +const POX_4 = "pox-4"; +const GET_POX_INFO = "get-pox-info"; + +describe("test pox-4 contract read only functions", () => { + it("should return correct reward-cycle-to-burn-height", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, reward_cycle) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "reward-cycle-to-burn-height", + [Cl.uintCV(reward_cycle)], + account + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + + const expected = + Number(first_burn_block_height.value) + + Number(reward_cycle_length.value) * reward_cycle; + expect(actual).toBeUint(expected); + } + ), + { numRuns: 300 } + ); + }); + + it("should return correct burn-height-to-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, burn_height) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "burn-height-to-reward-cycle", + [Cl.uintCV(burn_height)], + account + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + const expected = Math.floor( + (burn_height - Number(first_burn_block_height.value)) / + Number(reward_cycle_length.value) + ); + expect(actual).toBeUint(expected); + } + ), + { numRuns: 300 } + ); + }); + + it("should return none stacker-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (stacker, caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-stacker-info", + [Cl.principalCV(stacker)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); + + it("should return correct check-caller-allowed", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-caller-allowed", + [], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(true); + } + ) + ); + }); + + it("should return u0 get-reward-set-size", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-reward-set-size", + [Cl.uintCV(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return u0 get-total-ustx-stacked", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-total-ustx-stacked", + [Cl.uintCV(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return none get-reward-set-pox-address", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + fc.nat(), + (caller, index, reward_cycle) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-reward-set-pox-address", + [Cl.uintCV(index), Cl.uintCV(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); + + it("should return correct get-stacking-minimum", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const testnet_stacking_threshold_25 = 8000; + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const stx_liq_supply = + pox_4_info.value.data["total-liquid-supply-ustx"]; + + assert(isClarityType(stx_liq_supply, ClarityType.UInt)); + const expected = Math.floor( + Number(stx_liq_supply.value) / testnet_stacking_threshold_25 + ); + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-stacking-minimum", + [], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return correct check-pox-addr-version", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 255 }), + (caller, version) => { + // Arrange + const expected = version > 6 ? false : true; + + // Act + let { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-addr-version", + [Cl.bufferCV(Uint8Array.from([version]))], + caller + ); + + // Assert + assert( + isClarityType( + actual, + expected ? ClarityType.BoolTrue : ClarityType.BoolFalse + ) + ); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return correct check-pox-lock-period", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycles) => { + // Arrange + const expected = + reward_cycles > 0 && reward_cycles <= 12 ? true : false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-lock-period", + [Cl.uintCV(reward_cycles)], + caller + ); + + // Assert + assert( + isClarityType( + actual, + expected ? ClarityType.BoolTrue : ClarityType.BoolFalse + ) + ); + expect(actual).toBeBool(expected); + } + ) + ), + { numRuns: 250 }; + }); + + it("should return correct can-stack-stx", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 255 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.bigInt({ min: 0n, max: 340282366920938463463374607431768211455n }), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const testnet_stacking_threshold_25 = 8000; + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const stacking_valid_amount = amount_ustx > 0; + const pox_lock_period_valid = num_cycles > 0 && num_cycles <= 12; + const pox_version_valid = version <= 6; + const pox_hashbytes_valid = + hashbytes.length === 20 || hashbytes.length === 32; + const stx_liq_supply = + pox_4_info.value.data["total-liquid-supply-ustx"]; + + assert(isClarityType(stx_liq_supply, ClarityType.UInt)); + const stacking_threshold_met = + amount_ustx >= + Math.floor( + Number(stx_liq_supply.value) / testnet_stacking_threshold_25 + ); + const expectedResponseErr = !stacking_threshold_met + ? 11 + : !stacking_valid_amount + ? 18 + : !pox_lock_period_valid + ? 2 + : !pox_version_valid + ? 13 + : !pox_hashbytes_valid + ? 13 + : 0; + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tupleCV({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uintCV(amount_ustx), + Cl.uintCV(first_rew_cycle), + Cl.uintCV(num_cycles), + ], + caller + ); + + // Assert + assert( + isClarityType( + actual, + stacking_threshold_met && + stacking_valid_amount && + pox_lock_period_valid && + pox_version_valid && + pox_hashbytes_valid + ? ClarityType.ResponseOk + : ClarityType.ResponseErr + ) + ); + + assert( + isClarityType( + actual.value, + stacking_threshold_met && + stacking_valid_amount && + pox_lock_period_valid && + pox_version_valid && + pox_hashbytes_valid + ? ClarityType.BoolTrue + : ClarityType.Int + ) + ); + if (expectedResponseErr === 0) { + expect(actual).toBeOk( + Cl.responseOkCV(Cl.boolCV(expectedResponseOk)) + ); + expect(actual.value).toBeBool(expectedResponseOk); + } else { + expect(actual).toBeErr(Cl.intCV(expectedResponseErr)); + expect(actual.value).toBeInt(expectedResponseErr); + } + } + ), + { numRuns: 300 } + ); + }); +}); From 301fb2056bfb2b2d3c66f2e287ee488217d06e67 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Fri, 1 Mar 2024 20:46:36 +0200 Subject: [PATCH 02/24] rename get-stacker-info test --- contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 65dc88cc08..54d5f5dd22 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -94,7 +94,7 @@ describe("test pox-4 contract read only functions", () => { ); }); - it("should return none stacker-info", () => { + it("should return none get-stacker-info", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), From 7fd3bb5c6a13c88f39eac2118ac71433ada21e74 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Mon, 4 Mar 2024 16:51:39 +0200 Subject: [PATCH 03/24] Split conditional tests --- .../tests/pox-4/pox-4.prop.test.ts | 332 ++++++++++++------ 1 file changed, 231 insertions(+), 101 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 54d5f5dd22..d084d7759d 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,9 +1,11 @@ -import Cl, { ClarityType, bufferCV, isClarityType } from "@stacks/transactions"; +import { Cl, ClarityType, bufferCV, isClarityType } from "@stacks/transactions"; import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; const POX_4 = "pox-4"; const GET_POX_INFO = "get-pox-info"; +const testnet_stacking_threshold_25 = 8000; +fc.configureGlobal({ numRuns: 250 }); describe("test pox-4 contract read only functions", () => { it("should return correct reward-cycle-to-burn-height", () => { @@ -31,7 +33,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "reward-cycle-to-burn-height", - [Cl.uintCV(reward_cycle)], + [Cl.uint(reward_cycle)], account ); @@ -45,8 +47,7 @@ describe("test pox-4 contract read only functions", () => { Number(reward_cycle_length.value) * reward_cycle; expect(actual).toBeUint(expected); } - ), - { numRuns: 300 } + ) ); }); @@ -75,7 +76,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "burn-height-to-reward-cycle", - [Cl.uintCV(burn_height)], + [Cl.uint(burn_height)], account ); @@ -89,8 +90,7 @@ describe("test pox-4 contract read only functions", () => { ); expect(actual).toBeUint(expected); } - ), - { numRuns: 300 } + ) ); }); @@ -106,7 +106,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "get-stacker-info", - [Cl.principalCV(stacker)], + [Cl.principal(stacker)], caller ); @@ -118,7 +118,7 @@ describe("test pox-4 contract read only functions", () => { ); }); - it("should return correct check-caller-allowed", () => { + it("should return true check-caller-allowed", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), @@ -154,7 +154,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "get-reward-set-size", - [Cl.uintCV(reward_cycle)], + [Cl.uint(reward_cycle)], caller ); @@ -179,7 +179,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "get-total-ustx-stacked", - [Cl.uintCV(reward_cycle)], + [Cl.uint(reward_cycle)], caller ); @@ -204,7 +204,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "get-reward-set-pox-address", - [Cl.uintCV(index), Cl.uintCV(reward_cycle)], + [Cl.uint(index), Cl.uint(reward_cycle)], caller ); @@ -222,7 +222,6 @@ describe("test pox-4 contract read only functions", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - const testnet_stacking_threshold_25 = 8000; const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, @@ -257,77 +256,206 @@ describe("test pox-4 contract read only functions", () => { ); }); - it("should return correct check-pox-addr-version", () => { + it("should return true check-pox-addr-version for version <= 6 ", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 255 }), + fc.nat({ max: 6 }), (caller, version) => { // Arrange - const expected = version > 6 ? false : true; + const expected = true; // Act let { result: actual } = simnet.callReadOnlyFn( POX_4, "check-pox-addr-version", - [Cl.bufferCV(Uint8Array.from([version]))], + [Cl.buffer(Uint8Array.from([version]))], caller ); // Assert - assert( - isClarityType( - actual, - expected ? ClarityType.BoolTrue : ClarityType.BoolFalse - ) + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-addr-version for version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 7, max: 255 }), + (caller, version) => { + // Arrange + const expected = false; + + // Act + let { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-addr-version", + [Cl.buffer(Uint8Array.from([version]))], + caller ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); } ) ); }); - it("should return correct check-pox-lock-period", () => { + it("should return true check-pox-lock-period for valid reward cycles number", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), + fc.integer({ min: 1, max: 12 }), (caller, reward_cycles) => { // Arrange - const expected = - reward_cycles > 0 && reward_cycles <= 12 ? true : false; + const expected = true; // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, "check-pox-lock-period", - [Cl.uintCV(reward_cycles)], + [Cl.uint(reward_cycles)], caller ); // Assert - assert( - isClarityType( - actual, - expected ? ClarityType.BoolTrue : ClarityType.BoolFalse - ) + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-lock-period for reward cycles number > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 13 }), + (caller, reward_cycles) => { + // Arrange + const expected = false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-lock-period", + [Cl.uint(reward_cycles)], + caller ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); } ) - ), - { numRuns: 250 }; + ); }); - it("should return correct can-stack-stx", () => { + it("should return false check-pox-lock-period for reward cycles number == 0", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 255 }), - fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), - fc.bigInt({ min: 0n, max: 340282366920938463463374607431768211455n }), + (caller) => { + // Arrange + const reward_cycles = 0; + const expected = false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-lock-period", + [Cl.uint(reward_cycles)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), fc.nat(), + fc.integer({ min: 1, max: 12 }), ( caller, version, @@ -337,7 +465,6 @@ describe("test pox-4 contract read only functions", () => { num_cycles ) => { // Arrange - const testnet_stacking_threshold_25 = 8000; const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, @@ -348,31 +475,6 @@ describe("test pox-4 contract read only functions", () => { assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const stacking_valid_amount = amount_ustx > 0; - const pox_lock_period_valid = num_cycles > 0 && num_cycles <= 12; - const pox_version_valid = version <= 6; - const pox_hashbytes_valid = - hashbytes.length === 20 || hashbytes.length === 32; - const stx_liq_supply = - pox_4_info.value.data["total-liquid-supply-ustx"]; - - assert(isClarityType(stx_liq_supply, ClarityType.UInt)); - const stacking_threshold_met = - amount_ustx >= - Math.floor( - Number(stx_liq_supply.value) / testnet_stacking_threshold_25 - ); - const expectedResponseErr = !stacking_threshold_met - ? 11 - : !stacking_valid_amount - ? 18 - : !pox_lock_period_valid - ? 2 - : !pox_version_valid - ? 13 - : !pox_hashbytes_valid - ? 13 - : 0; const expectedResponseOk = true; // Act @@ -380,55 +482,83 @@ describe("test pox-4 contract read only functions", () => { POX_4, "can-stack-stx", [ - Cl.tupleCV({ + Cl.tuple({ version: bufferCV(Uint8Array.from([version])), hashbytes: bufferCV(Uint8Array.from(hashbytes)), }), - Cl.uintCV(amount_ustx), - Cl.uintCV(first_rew_cycle), - Cl.uintCV(num_cycles), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), ], caller ); // Assert - assert( - isClarityType( - actual, - stacking_threshold_met && - stacking_valid_amount && - pox_lock_period_valid && - pox_version_valid && - pox_hashbytes_valid - ? ClarityType.ResponseOk - : ClarityType.ResponseErr - ) + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = 13; - assert( - isClarityType( - actual.value, - stacking_threshold_met && - stacking_valid_amount && - pox_lock_period_valid && - pox_version_valid && - pox_hashbytes_valid - ? ClarityType.BoolTrue - : ClarityType.Int - ) + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller ); - if (expectedResponseErr === 0) { - expect(actual).toBeOk( - Cl.responseOkCV(Cl.boolCV(expectedResponseOk)) - ); - expect(actual.value).toBeBool(expectedResponseOk); - } else { - expect(actual).toBeErr(Cl.intCV(expectedResponseErr)); - expect(actual.value).toBeInt(expectedResponseErr); - } + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); } - ), - { numRuns: 300 } + ) ); }); }); From 5e1147ef57d83cf1522bf764ca81ac3d39255952 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Tue, 5 Mar 2024 16:49:33 +0200 Subject: [PATCH 04/24] Added tests for minimal-can-stack-stx --- .../tests/pox-4/pox-4.prop.test.ts | 786 +++++++++++++++++- 1 file changed, 782 insertions(+), 4 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index d084d7759d..a377fa9915 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,10 +1,25 @@ -import { Cl, ClarityType, bufferCV, isClarityType } from "@stacks/transactions"; +import { + Cl, + ClarityType, + bufferCV, + cvToJSON, + isClarityType, +} from "@stacks/transactions"; import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; +// contracts const POX_4 = "pox-4"; +// methods const GET_POX_INFO = "get-pox-info"; -const testnet_stacking_threshold_25 = 8000; +// contract consts +const TESTNET_STACKING_THRESHOLD_25 = 8000; +// error codes +const ERR_STACKING_INVALID_LOCK_PERIOD = 2; +const ERR_STACKING_THRESHOLD_NOT_MET = 11; +const ERR_STACKING_INVALID_POX_ADDRESS = 13; +const ERR_STACKING_INVALID_AMOUNT = 18; + fc.configureGlobal({ numRuns: 250 }); describe("test pox-4 contract read only functions", () => { @@ -237,7 +252,7 @@ describe("test pox-4 contract read only functions", () => { assert(isClarityType(stx_liq_supply, ClarityType.UInt)); const expected = Math.floor( - Number(stx_liq_supply.value) / testnet_stacking_threshold_25 + Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 ); // Act @@ -502,6 +517,69 @@ describe("test pox-4 contract read only functions", () => { ); }); + it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { fc.assert( fc.property( @@ -535,7 +613,182 @@ describe("test pox-4 contract read only functions", () => { assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = 13; + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 0n, + max: 124_999_999_999n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; // Act const { result: actual } = simnet.callReadOnlyFn( @@ -561,4 +814,529 @@ describe("test pox-4 contract read only functions", () => { ) ); }); + + it("should return (err 2) can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + // minimal can stack stx + it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer(), + fc.array(fc.nat({ max: 255 })), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + (caller, version, hashbytes, first_rew_cycle, num_cycles) => { + // Arrange + const amount_ustx = 0; + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); }); From 195c413ef5318bca1a0155264d3576a5be99e4aa Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Wed, 6 Mar 2024 19:04:20 +0200 Subject: [PATCH 05/24] added tests for read only functions - get-check-delegation - get-delegation-info - get-allowance-contract-callers - get-pox-info - minimal-can-stack-stx --- .../tests/pox-4/pox-4.prop.test.ts | 2843 +++++++++-------- 1 file changed, 1514 insertions(+), 1329 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index a377fa9915..506ebd2864 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,1342 +1,1527 @@ -import { - Cl, - ClarityType, - bufferCV, - cvToJSON, - isClarityType, -} from "@stacks/transactions"; +import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; -// contracts +// Contracts const POX_4 = "pox-4"; -// methods +// Methods const GET_POX_INFO = "get-pox-info"; -// contract consts +const GET_STACKER_INFO = "get-stacker-info"; +const REWARD_CYCLE_TO_BURN_HEIGHT = "reward-cycle-to-burn-height"; +const BURN_HEIGHT_TO_REWARD_CYCLE = "burn-height-to-reward-cycle"; +const CURRENT_POX_REWARD_CYCLE = "current-pox-reward-cycle"; +const CHECK_CALLER_ALLOWED = "check-caller-allowed"; +const GET_REWARD_SET_SIZE = "get-reward-set-size"; +const GET_REWARD_SET_POX_ADDRESS = "get-reward-set-pox-address"; +const GET_TOTAL_USTX_STACKED = "get-total-ustx-stacked"; +const CHECK_POX_ADDR_VERSION = "check-pox-addr-version"; +const CHECK_POX_LOCK_PERIOD = "check-pox-lock-period"; +const GET_STACKING_MINIMUM = "get-stacking-minimum"; +const CAN_STACK_STX = "can-stack-stx"; +const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; +const GET_CHECK_DELEGATION = "get-check-delegation"; +const GET_DELEGATION_INFO = "get-delegation-info"; +const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; +const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; +// Contract Consts const TESTNET_STACKING_THRESHOLD_25 = 8000; -// error codes +const TESTNET_REWARD_CYCLE_LENGTH = 1050; +const TESTNET_PREPARE_CYCLE_LENGTH = 50; +const INITIAL_TOTAL_LIQ_SUPPLY = 1_000_000_000_000_000; +const MIN_AMOUNT_USTX = 125_000_000_000n; +// Clarity Constraints +const MAX_CLAR_UINT = 340282366920938463463374607431768211455n; +// Error Codes const ERR_STACKING_INVALID_LOCK_PERIOD = 2; const ERR_STACKING_THRESHOLD_NOT_MET = 11; const ERR_STACKING_INVALID_POX_ADDRESS = 13; const ERR_STACKING_INVALID_AMOUNT = 18; -fc.configureGlobal({ numRuns: 250 }); - -describe("test pox-4 contract read only functions", () => { - it("should return correct reward-cycle-to-burn-height", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (account, reward_cycle) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - account - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const first_burn_block_height = - pox_4_info.value.data["first-burnchain-block-height"]; - const reward_cycle_length = - pox_4_info.value.data["reward-cycle-length"]; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "reward-cycle-to-burn-height", - [Cl.uint(reward_cycle)], - account - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - assert(isClarityType(first_burn_block_height, ClarityType.UInt)); - assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - - const expected = - Number(first_burn_block_height.value) + - Number(reward_cycle_length.value) * reward_cycle; - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return correct burn-height-to-reward-cycle", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (account, burn_height) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - account - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const first_burn_block_height = - pox_4_info.value.data["first-burnchain-block-height"]; - const reward_cycle_length = - pox_4_info.value.data["reward-cycle-length"]; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "burn-height-to-reward-cycle", - [Cl.uint(burn_height)], - account - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - assert(isClarityType(first_burn_block_height, ClarityType.UInt)); - assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - const expected = Math.floor( - (burn_height - Number(first_burn_block_height.value)) / - Number(reward_cycle_length.value) - ); - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return none get-stacker-info", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - (stacker, caller) => { - // Arrange - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-stacker-info", - [Cl.principal(stacker)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - expect(actual).toBeNone(); - } - ) - ); - }); - - it("should return true check-caller-allowed", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-caller-allowed", - [], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(true); - } - ) - ); - }); - - it("should return u0 get-reward-set-size", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-reward-set-size", - [Cl.uint(reward_cycle)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return u0 get-total-ustx-stacked", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-total-ustx-stacked", - [Cl.uint(reward_cycle)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return none get-reward-set-pox-address", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - fc.nat(), - (caller, index, reward_cycle) => { - // Arrange - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-reward-set-pox-address", - [Cl.uint(index), Cl.uint(reward_cycle)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - expect(actual).toBeNone(); - } - ) - ); - }); - - it("should return correct get-stacking-minimum", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const stx_liq_supply = - pox_4_info.value.data["total-liquid-supply-ustx"]; - - assert(isClarityType(stx_liq_supply, ClarityType.UInt)); - const expected = Math.floor( - Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 - ); - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-stacking-minimum", - [], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return true check-pox-addr-version for version <= 6 ", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 6 }), - (caller, version) => { - // Arrange - const expected = true; - - // Act - let { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-addr-version", - [Cl.buffer(Uint8Array.from([version]))], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return false check-pox-addr-version for version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 7, max: 255 }), - (caller, version) => { - // Arrange - const expected = false; - - // Act - let { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-addr-version", - [Cl.buffer(Uint8Array.from([version]))], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return true check-pox-lock-period for valid reward cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 1, max: 12 }), - (caller, reward_cycles) => { - // Arrange - const expected = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return false check-pox-lock-period for reward cycles number > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 13 }), - (caller, reward_cycles) => { - // Arrange - const expected = false; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return false check-pox-lock-period for reward cycles number == 0", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - const reward_cycles = 0; - const expected = false; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 20, - maxLength: 20, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseOk = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); - - it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 5, max: 6 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseOk = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); - - it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ - min: 7, - max: 255, - }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 21, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 19, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 31, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: 0n, - max: 124_999_999_999n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 2) can-stack-stx for lock period > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 13 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - // minimal can stack stx - it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 20, - maxLength: 20, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseOk = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); - - it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 5, max: 6 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseOk = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); - - it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ - min: 7, - max: 255, - }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 21, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 19, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 31, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 13 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer(), - fc.array(fc.nat({ max: 255 })), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - (caller, version, hashbytes, first_rew_cycle, num_cycles) => { - // Arrange - const amount_ustx = 0; - - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); +describe("test pox-4 contract", () => { + describe("test pox-4 contract read only functions", () => { + it("should return correct reward-cycle-to-burn-height", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, reward_cycle) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + REWARD_CYCLE_TO_BURN_HEIGHT, + [Cl.uint(reward_cycle)], + account + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + + const expected = + Number(first_burn_block_height.value) + + Number(reward_cycle_length.value) * reward_cycle; + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return correct burn-height-to-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, burn_height) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + BURN_HEIGHT_TO_REWARD_CYCLE, + [Cl.uint(burn_height)], + account + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + const expected = Math.floor( + (burn_height - Number(first_burn_block_height.value)) / + Number(reward_cycle_length.value) + ); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return u0 current-pox-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + let expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CURRENT_POX_REWARD_CYCLE, + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return none get-stacker-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (stacker, caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_STACKER_INFO, + [Cl.principal(stacker)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); + + it("should return true check-caller-allowed", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_CALLER_ALLOWED, + [], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(true); + } + ) + ); + }); + + it("should return u0 get-reward-set-size", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_REWARD_SET_SIZE, + [Cl.uint(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return u0 get-total-ustx-stacked", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_TOTAL_USTX_STACKED, + [Cl.uint(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return none get-reward-set-pox-address", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + fc.nat(), + (caller, index, reward_cycle) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_REWARD_SET_POX_ADDRESS, + [Cl.uint(index), Cl.uint(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); + + it("should return correct get-stacking-minimum", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const stx_liq_supply = + pox_4_info.value.data["total-liquid-supply-ustx"]; + + assert(isClarityType(stx_liq_supply, ClarityType.UInt)); + const expected = Math.floor( + Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 + ); + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_STACKING_MINIMUM, + [], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return true check-pox-addr-version for version <= 6 ", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + (caller, version) => { + // Arrange + const expected = true; + + // Act + let { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_ADDR_VERSION, + [Cl.buffer(Uint8Array.from([version]))], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-addr-version for version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 7, max: 255 }), + (caller, version) => { + // Arrange + const expected = false; + + // Act + let { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_ADDR_VERSION, + [Cl.buffer(Uint8Array.from([version]))], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return true check-pox-lock-period for valid reward cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 1, max: 12 }), + (caller, reward_cycles) => { + // Arrange + const expected = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_LOCK_PERIOD, + [Cl.uint(reward_cycles)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-lock-period for reward cycles number > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 13 }), + (caller, reward_cycles) => { + // Arrange + const expected = false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_LOCK_PERIOD, + [Cl.uint(reward_cycles)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-lock-period for reward cycles number == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const reward_cycles = 0; + const expected = false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_LOCK_PERIOD, + [Cl.uint(reward_cycles)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 0n, + max: 124_999_999_999n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 2) can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + // minimal can stack stx + it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + (caller, version, hashbytes, first_rew_cycle, num_cycles) => { + // Arrange + const amount_ustx = 0; + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return none get-check-delegation", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_CHECK_DELEGATION, + [Cl.principal(caller)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + + it("should return none get-delegation-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_DELEGATION_INFO, + [Cl.principal(caller)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + + it("should return correct get-pox-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const expected_reward_cycle_id = 0, + expected_first_burn_block_height = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual.value.data["first-burnchain-block-height"]).toBeUint( + expected_first_burn_block_height + ); + expect(actual.value.data["min-amount-ustx"]).toBeUint( + MIN_AMOUNT_USTX + ); + expect(actual.value.data["prepare-cycle-length"]).toBeUint( + TESTNET_PREPARE_CYCLE_LENGTH + ); + expect(actual.value.data["reward-cycle-id"]).toBeUint( + expected_reward_cycle_id + ); + expect(actual.value.data["reward-cycle-length"]).toBeUint( + TESTNET_REWARD_CYCLE_LENGTH + ); + expect(actual.value.data["total-liquid-supply-ustx"]).toBeUint( + INITIAL_TOTAL_LIQ_SUPPLY + ); + } + ) + ); + }); + + it("should return none get-allowance-contract-caller", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, sender, contract_caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_ALLOWANCE_CONTRACT_CALLERS, + [Cl.principal(sender), Cl.principal(contract_caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + + it("should return some get-allowance-contract-caller after allow-contract-caller", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, sender, contract_caller) => { + // Arrange + const { result: allow } = simnet.callPublicFn( + POX_4, + ALLOW_CONTRACT_CALLER, + [Cl.principal(contract_caller), Cl.none()], + sender + ); + + assert(isClarityType(allow, ClarityType.ResponseOk)); + assert(isClarityType(allow.value, ClarityType.BoolTrue)); + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_ALLOWANCE_CONTRACT_CALLERS, + [Cl.principal(sender), Cl.principal(contract_caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalSome)); + assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual.value).toBeTuple({ "until-burn-ht": Cl.none() }); + } + ) + ); + }); + + // get-signer-key-message-hash + // verify-signer-key-sig + // get-num-reward-set-pox-addresses + // get-partial-stacked-by-cycle }); }); From 1ca367d7f05ee2ec8fcf693b278bf57b8c80c83b Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Wed, 6 Mar 2024 20:14:27 +0200 Subject: [PATCH 06/24] added tests for get-num-reward-set-pox-addresses, get-partial-stacked-by-cycle --- .../tests/pox-4/pox-4.prop.test.ts | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 506ebd2864..d16dd76f1a 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -22,6 +22,8 @@ const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; const GET_CHECK_DELEGATION = "get-check-delegation"; const GET_DELEGATION_INFO = "get-delegation-info"; const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; +const GET_NUM_REWARD_SET_POX_ADDRESSES = "get-num-reward-set-pox-addresses"; +const GET_PARTIAL_STACKED_BY_CYCLE = "get-partial-stacked-by-cycle"; const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; // Contract Consts const TESTNET_STACKING_THRESHOLD_25 = 8000; @@ -1486,7 +1488,7 @@ describe("test pox-4 contract", () => { ); }); - it("should return some get-allowance-contract-caller after allow-contract-caller", () => { + it("should return some(until-burn-ht: none) get-allowance-contract-caller after allow-contract-caller", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), @@ -1519,9 +1521,61 @@ describe("test pox-4 contract", () => { ); }); + it("should return u0 get-num-reward-set-pox-addresses", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_NUM_REWARD_SET_POX_ADDRESSES, + [Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return none get-partial-stacked-by-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, version, hashbytes, reward_cycle, sender) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_PARTIAL_STACKED_BY_CYCLE, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.principal(sender), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + // get-signer-key-message-hash // verify-signer-key-sig - // get-num-reward-set-pox-addresses - // get-partial-stacked-by-cycle }); }); From 19c959f7b7f216150d3d1008668ac6562d68388f Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Thu, 7 Mar 2024 14:09:12 +0200 Subject: [PATCH 07/24] added test for get-signer-key-message-hash and utils file --- .../tests/pox-4/pox-4-utils/utils.ts | 58 +++++++ .../tests/pox-4/pox-4.prop.test.ts | 164 +++++++----------- 2 files changed, 116 insertions(+), 106 deletions(-) create mode 100644 contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts new file mode 100644 index 0000000000..81164c3338 --- /dev/null +++ b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts @@ -0,0 +1,58 @@ +import { Cl, ClarityValue, serializeCV } from "@stacks/transactions"; +import { createHash } from "crypto"; + +function sha256(data: Buffer): Buffer { + return createHash("sha256").update(data).digest(); +} + +function structuredDataHash(structuredData: ClarityValue): Buffer { + return sha256(Buffer.from(serializeCV(structuredData))); +} + +const generateDomainHash = () => + Cl.tuple({ + name: Cl.stringAscii("pox-4-signer"), + version: Cl.stringAscii("1.0.0"), + "chain-id": Cl.uint(2147483648), + }); + +const generateMessageHash = ( + version: number, + hashbytes: number[], + reward_cycle: number, + topic: string, + period: number +) => + Cl.tuple({ + "pox-addr": Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + "reward-cycle": Cl.uint(reward_cycle), + topic: Cl.stringAscii(topic), + period: Cl.uint(period), + }); + +const generateMessagePrefixBuffer = (prefix: string) => + Buffer.from(prefix, "hex"); + +export const buildSignerKeyMessageHash = ( + version: number, + hashbytes: number[], + reward_cycle: number, + topic: string, + period: number +) => { + const sip018_msg_prefix = "534950303138"; + const domain_hash = structuredDataHash(generateDomainHash()); + const message_hash = structuredDataHash( + generateMessageHash(version, hashbytes, reward_cycle, topic, period) + ); + const structuredDataPrefix = generateMessagePrefixBuffer(sip018_msg_prefix); + + const signer_key_message_hash = sha256( + Buffer.concat([structuredDataPrefix, domain_hash, message_hash]) + ); + + return signer_key_message_hash; +}; diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index d16dd76f1a..b54eaafa5c 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,36 +1,39 @@ import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; +import { buildSignerKeyMessageHash } from "./pox-4-utils/utils"; // Contracts const POX_4 = "pox-4"; // Methods -const GET_POX_INFO = "get-pox-info"; -const GET_STACKER_INFO = "get-stacker-info"; -const REWARD_CYCLE_TO_BURN_HEIGHT = "reward-cycle-to-burn-height"; +const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; const BURN_HEIGHT_TO_REWARD_CYCLE = "burn-height-to-reward-cycle"; -const CURRENT_POX_REWARD_CYCLE = "current-pox-reward-cycle"; +const CAN_STACK_STX = "can-stack-stx"; const CHECK_CALLER_ALLOWED = "check-caller-allowed"; -const GET_REWARD_SET_SIZE = "get-reward-set-size"; -const GET_REWARD_SET_POX_ADDRESS = "get-reward-set-pox-address"; -const GET_TOTAL_USTX_STACKED = "get-total-ustx-stacked"; const CHECK_POX_ADDR_VERSION = "check-pox-addr-version"; const CHECK_POX_LOCK_PERIOD = "check-pox-lock-period"; -const GET_STACKING_MINIMUM = "get-stacking-minimum"; -const CAN_STACK_STX = "can-stack-stx"; -const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; +const CURRENT_POX_REWARD_CYCLE = "current-pox-reward-cycle"; +const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; const GET_CHECK_DELEGATION = "get-check-delegation"; const GET_DELEGATION_INFO = "get-delegation-info"; -const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; const GET_NUM_REWARD_SET_POX_ADDRESSES = "get-num-reward-set-pox-addresses"; const GET_PARTIAL_STACKED_BY_CYCLE = "get-partial-stacked-by-cycle"; -const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; +const GET_POX_INFO = "get-pox-info"; +const GET_REWARD_SET_POX_ADDRESS = "get-reward-set-pox-address"; +const GET_REWARD_SET_SIZE = "get-reward-set-size"; +const GET_SIGNER_KEY_MESSAGE_HASH = "get-signer-key-message-hash"; +const GET_STACKER_INFO = "get-stacker-info"; +const GET_STACKING_MINIMUM = "get-stacking-minimum"; +const GET_TOTAL_USTX_STACKED = "get-total-ustx-stacked"; +const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; +const REWARD_CYCLE_TO_BURN_HEIGHT = "reward-cycle-to-burn-height"; +const VERIFY_SIGNER_KEY_SIG = "verify-signer-key-sig"; // Contract Consts -const TESTNET_STACKING_THRESHOLD_25 = 8000; -const TESTNET_REWARD_CYCLE_LENGTH = 1050; -const TESTNET_PREPARE_CYCLE_LENGTH = 50; const INITIAL_TOTAL_LIQ_SUPPLY = 1_000_000_000_000_000; const MIN_AMOUNT_USTX = 125_000_000_000n; +const TESTNET_PREPARE_CYCLE_LENGTH = 50; +const TESTNET_REWARD_CYCLE_LENGTH = 1050; +const TESTNET_STACKING_THRESHOLD_25 = 8000; // Clarity Constraints const MAX_CLAR_UINT = 340282366920938463463374607431768211455n; // Error Codes @@ -56,12 +59,10 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const first_burn_block_height = pox_4_info.value.data["first-burnchain-block-height"]; const reward_cycle_length = pox_4_info.value.data["reward-cycle-length"]; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -69,12 +70,10 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycle)], account ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); assert(isClarityType(first_burn_block_height, ClarityType.UInt)); assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - const expected = Number(first_burn_block_height.value) + Number(reward_cycle_length.value) * reward_cycle; @@ -99,12 +98,10 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const first_burn_block_height = pox_4_info.value.data["first-burnchain-block-height"]; const reward_cycle_length = pox_4_info.value.data["reward-cycle-length"]; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -112,7 +109,6 @@ describe("test pox-4 contract", () => { [Cl.uint(burn_height)], account ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); assert(isClarityType(first_burn_block_height, ClarityType.UInt)); @@ -156,7 +152,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (stacker, caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -164,7 +159,6 @@ describe("test pox-4 contract", () => { [Cl.principal(stacker)], caller ); - // Assert assert(isClarityType(actual, ClarityType.OptionalNone)); expect(actual).toBeNone(); @@ -179,7 +173,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -187,7 +180,6 @@ describe("test pox-4 contract", () => { [], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolTrue)); expect(actual).toBeBool(true); @@ -204,7 +196,6 @@ describe("test pox-4 contract", () => { (caller, reward_cycle) => { // Arrange const expected = 0; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -212,7 +203,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycle)], caller ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); expect(actual).toBeUint(expected); @@ -229,7 +219,6 @@ describe("test pox-4 contract", () => { (caller, reward_cycle) => { // Arrange const expected = 0; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -237,7 +226,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycle)], caller ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); expect(actual).toBeUint(expected); @@ -254,7 +242,6 @@ describe("test pox-4 contract", () => { fc.nat(), (caller, index, reward_cycle) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -262,7 +249,6 @@ describe("test pox-4 contract", () => { [Cl.uint(index), Cl.uint(reward_cycle)], caller ); - // Assert assert(isClarityType(actual, ClarityType.OptionalNone)); expect(actual).toBeNone(); @@ -277,7 +263,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, GET_POX_INFO, @@ -286,15 +271,12 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const stx_liq_supply = pox_4_info.value.data["total-liquid-supply-ustx"]; - assert(isClarityType(stx_liq_supply, ClarityType.UInt)); const expected = Math.floor( Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 ); - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -302,7 +284,6 @@ describe("test pox-4 contract", () => { [], caller ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); expect(actual).toBeUint(expected); @@ -319,7 +300,6 @@ describe("test pox-4 contract", () => { (caller, version) => { // Arrange const expected = true; - // Act let { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -327,7 +307,6 @@ describe("test pox-4 contract", () => { [Cl.buffer(Uint8Array.from([version]))], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolTrue)); expect(actual).toBeBool(expected); @@ -344,7 +323,6 @@ describe("test pox-4 contract", () => { (caller, version) => { // Arrange const expected = false; - // Act let { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -352,7 +330,6 @@ describe("test pox-4 contract", () => { [Cl.buffer(Uint8Array.from([version]))], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); @@ -369,7 +346,6 @@ describe("test pox-4 contract", () => { (caller, reward_cycles) => { // Arrange const expected = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -377,7 +353,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycles)], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolTrue)); expect(actual).toBeBool(expected); @@ -394,7 +369,6 @@ describe("test pox-4 contract", () => { (caller, reward_cycles) => { // Arrange const expected = false; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -402,7 +376,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycles)], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); @@ -419,7 +392,6 @@ describe("test pox-4 contract", () => { // Arrange const reward_cycles = 0; const expected = false; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -427,7 +399,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycles)], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); @@ -468,9 +439,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -486,7 +455,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseOk)); assert(isClarityType(actual.value, ClarityType.BoolTrue)); @@ -520,7 +488,6 @@ describe("test pox-4 contract", () => { num_cycles ) => { // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, GET_POX_INFO, @@ -529,9 +496,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -547,7 +512,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseOk)); assert(isClarityType(actual.value, ClarityType.BoolTrue)); @@ -592,9 +556,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -610,7 +572,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -652,9 +613,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -670,7 +629,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -711,9 +669,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -729,7 +685,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -770,9 +725,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -788,7 +741,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -827,9 +779,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -845,7 +795,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -884,9 +833,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -902,7 +849,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -912,7 +858,6 @@ describe("test pox-4 contract", () => { ); }); - // minimal can stack stx it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { fc.assert( fc.property( @@ -945,9 +890,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -963,7 +906,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseOk)); assert(isClarityType(actual.value, ClarityType.BoolTrue)); @@ -997,7 +939,6 @@ describe("test pox-4 contract", () => { num_cycles ) => { // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, GET_POX_INFO, @@ -1006,9 +947,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1024,7 +963,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseOk)); assert(isClarityType(actual.value, ClarityType.BoolTrue)); @@ -1069,9 +1007,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1087,7 +1023,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1129,9 +1064,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1147,7 +1080,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1188,9 +1120,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1206,7 +1136,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1247,9 +1176,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1265,7 +1192,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1304,9 +1230,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1322,7 +1246,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1343,7 +1266,6 @@ describe("test pox-4 contract", () => { (caller, version, hashbytes, first_rew_cycle, num_cycles) => { // Arrange const amount_ustx = 0; - const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, GET_POX_INFO, @@ -1352,9 +1274,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1370,7 +1290,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1386,7 +1305,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1394,7 +1312,6 @@ describe("test pox-4 contract", () => { [Cl.principal(caller)], caller ); - // Assert assert(isClarityType(actual, ClarityType.OptionalNone)); } @@ -1408,7 +1325,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1416,7 +1332,6 @@ describe("test pox-4 contract", () => { [Cl.principal(caller)], caller ); - // Assert assert(isClarityType(actual, ClarityType.OptionalNone)); } @@ -1473,7 +1388,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller, sender, contract_caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1502,7 +1416,6 @@ describe("test pox-4 contract", () => { [Cl.principal(contract_caller), Cl.none()], sender ); - assert(isClarityType(allow, ClarityType.ResponseOk)); assert(isClarityType(allow.value, ClarityType.BoolTrue)); // Act @@ -1575,7 +1488,46 @@ describe("test pox-4 contract", () => { ); }); - // get-signer-key-message-hash + it("should return correct hash get-signer-key-message-hash", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + (caller, version, hashbytes, reward_cycle, period) => { + // Arrange + const topic = "test"; + const signer_key_message_hash = buildSignerKeyMessageHash( + version, + hashbytes, + reward_cycle, + topic, + period + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_SIGNER_KEY_MESSAGE_HASH, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii(topic), + Cl.uint(period), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.Buffer)); + expect(actual).toBeBuff(signer_key_message_hash); + } + ) + ); + }); // verify-signer-key-sig }); }); From 4eb89e4aae720b8e422677a7f109479bbe05705f Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Thu, 7 Mar 2024 16:49:58 +0200 Subject: [PATCH 08/24] updated get-signer-key-message-hash test to match the new function structure --- .../tests/pox-4/pox-4-utils/utils.ts | 20 +++++++++++-- .../tests/pox-4/pox-4.prop.test.ts | 30 +++++++++++++++---- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts index 81164c3338..1f53c81a92 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts @@ -21,7 +21,9 @@ const generateMessageHash = ( hashbytes: number[], reward_cycle: number, topic: string, - period: number + period: number, + auth_id: number, + max_amount: number ) => Cl.tuple({ "pox-addr": Cl.tuple({ @@ -31,6 +33,8 @@ const generateMessageHash = ( "reward-cycle": Cl.uint(reward_cycle), topic: Cl.stringAscii(topic), period: Cl.uint(period), + "auth-id": Cl.uint(auth_id), + "max-amount": Cl.uint(max_amount), }); const generateMessagePrefixBuffer = (prefix: string) => @@ -41,12 +45,22 @@ export const buildSignerKeyMessageHash = ( hashbytes: number[], reward_cycle: number, topic: string, - period: number + period: number, + max_amount: number, + auth_id: number ) => { const sip018_msg_prefix = "534950303138"; const domain_hash = structuredDataHash(generateDomainHash()); const message_hash = structuredDataHash( - generateMessageHash(version, hashbytes, reward_cycle, topic, period) + generateMessageHash( + version, + hashbytes, + reward_cycle, + topic, + period, + auth_id, + max_amount + ) ); const structuredDataPrefix = generateMessagePrefixBuffer(sip018_msg_prefix); diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index b54eaafa5c..e1c1e04833 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,6 +1,6 @@ import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; -import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; +import { assert, describe, expect, it } from "vitest"; import { buildSignerKeyMessageHash } from "./pox-4-utils/utils"; // Contracts @@ -1496,15 +1496,31 @@ describe("test pox-4 contract", () => { fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), fc.nat(), fc.nat(), - (caller, version, hashbytes, reward_cycle, period) => { + // fc.asciiString({ maxLength: 10, minLength: 1 }), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + // topic, + max_amount, + auth_id + ) => { // Arrange - const topic = "test"; + // clarinet bug string: + // r;NT=" + const signer_key_message_hash = buildSignerKeyMessageHash( version, hashbytes, reward_cycle, - topic, - period + "topic", + period, + max_amount, + auth_id ); // Act const { result: actual } = simnet.callReadOnlyFn( @@ -1516,8 +1532,10 @@ describe("test pox-4 contract", () => { hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), }), Cl.uint(reward_cycle), - Cl.stringAscii(topic), + Cl.stringAscii("topic"), Cl.uint(period), + Cl.uint(max_amount), + Cl.uint(auth_id), ], caller ); From 37f226561550035a879be1e676bdb69320e5212f Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Thu, 7 Mar 2024 20:21:11 +0200 Subject: [PATCH 09/24] Move utils to test file, inlined methods and contract name --- .../tests/pox-4/pox-4-utils/utils.ts | 72 ---- .../tests/pox-4/pox-4.prop.test.ts | 342 ++++++++++-------- 2 files changed, 198 insertions(+), 216 deletions(-) delete mode 100644 contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts deleted file mode 100644 index 1f53c81a92..0000000000 --- a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Cl, ClarityValue, serializeCV } from "@stacks/transactions"; -import { createHash } from "crypto"; - -function sha256(data: Buffer): Buffer { - return createHash("sha256").update(data).digest(); -} - -function structuredDataHash(structuredData: ClarityValue): Buffer { - return sha256(Buffer.from(serializeCV(structuredData))); -} - -const generateDomainHash = () => - Cl.tuple({ - name: Cl.stringAscii("pox-4-signer"), - version: Cl.stringAscii("1.0.0"), - "chain-id": Cl.uint(2147483648), - }); - -const generateMessageHash = ( - version: number, - hashbytes: number[], - reward_cycle: number, - topic: string, - period: number, - auth_id: number, - max_amount: number -) => - Cl.tuple({ - "pox-addr": Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - "reward-cycle": Cl.uint(reward_cycle), - topic: Cl.stringAscii(topic), - period: Cl.uint(period), - "auth-id": Cl.uint(auth_id), - "max-amount": Cl.uint(max_amount), - }); - -const generateMessagePrefixBuffer = (prefix: string) => - Buffer.from(prefix, "hex"); - -export const buildSignerKeyMessageHash = ( - version: number, - hashbytes: number[], - reward_cycle: number, - topic: string, - period: number, - max_amount: number, - auth_id: number -) => { - const sip018_msg_prefix = "534950303138"; - const domain_hash = structuredDataHash(generateDomainHash()); - const message_hash = structuredDataHash( - generateMessageHash( - version, - hashbytes, - reward_cycle, - topic, - period, - auth_id, - max_amount - ) - ); - const structuredDataPrefix = generateMessagePrefixBuffer(sip018_msg_prefix); - - const signer_key_message_hash = sha256( - Buffer.concat([structuredDataPrefix, domain_hash, message_hash]) - ); - - return signer_key_message_hash; -}; diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index e1c1e04833..1a56d314c2 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,47 +1,101 @@ -import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; +import { + Cl, + ClarityType, + ClarityValue, + isClarityType, + serializeCV, +} from "@stacks/transactions"; import fc from "fast-check"; import { assert, describe, expect, it } from "vitest"; -import { buildSignerKeyMessageHash } from "./pox-4-utils/utils"; +import { createHash } from "crypto"; -// Contracts -const POX_4 = "pox-4"; -// Methods -const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; -const BURN_HEIGHT_TO_REWARD_CYCLE = "burn-height-to-reward-cycle"; -const CAN_STACK_STX = "can-stack-stx"; -const CHECK_CALLER_ALLOWED = "check-caller-allowed"; -const CHECK_POX_ADDR_VERSION = "check-pox-addr-version"; -const CHECK_POX_LOCK_PERIOD = "check-pox-lock-period"; -const CURRENT_POX_REWARD_CYCLE = "current-pox-reward-cycle"; -const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; -const GET_CHECK_DELEGATION = "get-check-delegation"; -const GET_DELEGATION_INFO = "get-delegation-info"; -const GET_NUM_REWARD_SET_POX_ADDRESSES = "get-num-reward-set-pox-addresses"; -const GET_PARTIAL_STACKED_BY_CYCLE = "get-partial-stacked-by-cycle"; -const GET_POX_INFO = "get-pox-info"; -const GET_REWARD_SET_POX_ADDRESS = "get-reward-set-pox-address"; -const GET_REWARD_SET_SIZE = "get-reward-set-size"; -const GET_SIGNER_KEY_MESSAGE_HASH = "get-signer-key-message-hash"; -const GET_STACKER_INFO = "get-stacker-info"; -const GET_STACKING_MINIMUM = "get-stacking-minimum"; -const GET_TOTAL_USTX_STACKED = "get-total-ustx-stacked"; -const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; -const REWARD_CYCLE_TO_BURN_HEIGHT = "reward-cycle-to-burn-height"; -const VERIFY_SIGNER_KEY_SIG = "verify-signer-key-sig"; // Contract Consts const INITIAL_TOTAL_LIQ_SUPPLY = 1_000_000_000_000_000; const MIN_AMOUNT_USTX = 125_000_000_000n; const TESTNET_PREPARE_CYCLE_LENGTH = 50; const TESTNET_REWARD_CYCLE_LENGTH = 1050; const TESTNET_STACKING_THRESHOLD_25 = 8000; -// Clarity Constraints +// Clarity const MAX_CLAR_UINT = 340282366920938463463374607431768211455n; +const TESTNET_CHAIN_ID = 2147483648; +const SIP_018_MESSAGE_PREFIX = "534950303138"; // Error Codes const ERR_STACKING_INVALID_LOCK_PERIOD = 2; const ERR_STACKING_THRESHOLD_NOT_MET = 11; const ERR_STACKING_INVALID_POX_ADDRESS = 13; const ERR_STACKING_INVALID_AMOUNT = 18; +function sha256(data: Buffer): Buffer { + return createHash("sha256").update(data).digest(); +} + +function structuredDataHash(structuredData: ClarityValue): Buffer { + return sha256(Buffer.from(serializeCV(structuredData))); +} + +const generateDomainHash = (): ClarityValue => + Cl.tuple({ + name: Cl.stringAscii("pox-4-signer"), + version: Cl.stringAscii("1.0.0"), + "chain-id": Cl.uint(TESTNET_CHAIN_ID), + }); + +const generateMessageHash = ( + version: number, + hashbytes: number[], + reward_cycle: number, + topic: string, + period: number, + auth_id: number, + max_amount: number +): ClarityValue => + Cl.tuple({ + "pox-addr": Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + "reward-cycle": Cl.uint(reward_cycle), + topic: Cl.stringAscii(topic), + period: Cl.uint(period), + "auth-id": Cl.uint(auth_id), + "max-amount": Cl.uint(max_amount), + }); + +const generateMessagePrefixBuffer = (prefix: string) => + Buffer.from(prefix, "hex"); + +export const buildSignerKeyMessageHash = ( + version: number, + hashbytes: number[], + reward_cycle: number, + topic: string, + period: number, + max_amount: number, + auth_id: number +) => { + const domain_hash = structuredDataHash(generateDomainHash()); + const message_hash = structuredDataHash( + generateMessageHash( + version, + hashbytes, + reward_cycle, + topic, + period, + auth_id, + max_amount + ) + ); + const structuredDataPrefix = generateMessagePrefixBuffer( + SIP_018_MESSAGE_PREFIX + ); + + const signer_key_message_hash = sha256( + Buffer.concat([structuredDataPrefix, domain_hash, message_hash]) + ); + + return signer_key_message_hash; +}; + describe("test pox-4 contract", () => { describe("test pox-4 contract read only functions", () => { it("should return correct reward-cycle-to-burn-height", () => { @@ -52,8 +106,8 @@ describe("test pox-4 contract", () => { (account, reward_cycle) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], account ); @@ -65,8 +119,8 @@ describe("test pox-4 contract", () => { pox_4_info.value.data["reward-cycle-length"]; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - REWARD_CYCLE_TO_BURN_HEIGHT, + "pox-4", + "reward-cycle-to-burn-height", [Cl.uint(reward_cycle)], account ); @@ -91,8 +145,8 @@ describe("test pox-4 contract", () => { (account, burn_height) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], account ); @@ -104,8 +158,8 @@ describe("test pox-4 contract", () => { pox_4_info.value.data["reward-cycle-length"]; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - BURN_HEIGHT_TO_REWARD_CYCLE, + "pox-4", + "burn-height-to-reward-cycle", [Cl.uint(burn_height)], account ); @@ -132,8 +186,8 @@ describe("test pox-4 contract", () => { let expected = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CURRENT_POX_REWARD_CYCLE, + "pox-4", + "current-pox-reward-cycle", [], caller ); @@ -154,8 +208,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_STACKER_INFO, + "pox-4", + "get-stacker-info", [Cl.principal(stacker)], caller ); @@ -175,8 +229,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_CALLER_ALLOWED, + "pox-4", + "check-caller-allowed", [], caller ); @@ -198,8 +252,8 @@ describe("test pox-4 contract", () => { const expected = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_REWARD_SET_SIZE, + "pox-4", + "get-reward-set-size", [Cl.uint(reward_cycle)], caller ); @@ -221,8 +275,8 @@ describe("test pox-4 contract", () => { const expected = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_TOTAL_USTX_STACKED, + "pox-4", + "get-total-ustx-stacked", [Cl.uint(reward_cycle)], caller ); @@ -244,8 +298,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_REWARD_SET_POX_ADDRESS, + "pox-4", + "get-reward-set-pox-address", [Cl.uint(index), Cl.uint(reward_cycle)], caller ); @@ -264,8 +318,8 @@ describe("test pox-4 contract", () => { (caller) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -279,8 +333,8 @@ describe("test pox-4 contract", () => { ); // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_STACKING_MINIMUM, + "pox-4", + "get-stacking-minimum", [], caller ); @@ -302,8 +356,8 @@ describe("test pox-4 contract", () => { const expected = true; // Act let { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_ADDR_VERSION, + "pox-4", + "check-pox-addr-version", [Cl.buffer(Uint8Array.from([version]))], caller ); @@ -325,8 +379,8 @@ describe("test pox-4 contract", () => { const expected = false; // Act let { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_ADDR_VERSION, + "pox-4", + "check-pox-addr-version", [Cl.buffer(Uint8Array.from([version]))], caller ); @@ -348,8 +402,8 @@ describe("test pox-4 contract", () => { const expected = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_LOCK_PERIOD, + "pox-4", + "check-pox-lock-period", [Cl.uint(reward_cycles)], caller ); @@ -371,8 +425,8 @@ describe("test pox-4 contract", () => { const expected = false; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_LOCK_PERIOD, + "pox-4", + "check-pox-lock-period", [Cl.uint(reward_cycles)], caller ); @@ -394,8 +448,8 @@ describe("test pox-4 contract", () => { const expected = false; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_LOCK_PERIOD, + "pox-4", + "check-pox-lock-period", [Cl.uint(reward_cycles)], caller ); @@ -432,8 +486,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -442,8 +496,8 @@ describe("test pox-4 contract", () => { const expectedResponseOk = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -489,8 +543,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -499,8 +553,8 @@ describe("test pox-4 contract", () => { const expectedResponseOk = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -549,8 +603,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -559,8 +613,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -606,8 +660,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -616,8 +670,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -662,8 +716,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -672,8 +726,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -718,8 +772,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -728,8 +782,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -772,8 +826,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -782,8 +836,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -826,8 +880,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -836,8 +890,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -883,8 +937,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -893,8 +947,8 @@ describe("test pox-4 contract", () => { const expectedResponseOk = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -940,8 +994,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -950,8 +1004,8 @@ describe("test pox-4 contract", () => { const expectedResponseOk = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1000,8 +1054,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1010,8 +1064,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1057,8 +1111,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1067,8 +1121,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1113,8 +1167,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1123,8 +1177,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1169,8 +1223,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1179,8 +1233,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1223,8 +1277,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1233,8 +1287,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1267,8 +1321,8 @@ describe("test pox-4 contract", () => { // Arrange const amount_ustx = 0; const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1277,8 +1331,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1307,8 +1361,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_CHECK_DELEGATION, + "pox-4", + "get-check-delegation", [Cl.principal(caller)], caller ); @@ -1327,8 +1381,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_DELEGATION_INFO, + "pox-4", + "get-delegation-info", [Cl.principal(caller)], caller ); @@ -1349,8 +1403,8 @@ describe("test pox-4 contract", () => { expected_first_burn_block_height = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1390,8 +1444,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_ALLOWANCE_CONTRACT_CALLERS, + "pox-4", + "get-allowance-contract-callers", [Cl.principal(sender), Cl.principal(contract_caller)], caller ); @@ -1411,8 +1465,8 @@ describe("test pox-4 contract", () => { (caller, sender, contract_caller) => { // Arrange const { result: allow } = simnet.callPublicFn( - POX_4, - ALLOW_CONTRACT_CALLER, + "pox-4", + "allow-contract-caller", [Cl.principal(contract_caller), Cl.none()], sender ); @@ -1420,8 +1474,8 @@ describe("test pox-4 contract", () => { assert(isClarityType(allow.value, ClarityType.BoolTrue)); // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_ALLOWANCE_CONTRACT_CALLERS, + "pox-4", + "get-allowance-contract-callers", [Cl.principal(sender), Cl.principal(contract_caller)], caller ); @@ -1444,8 +1498,8 @@ describe("test pox-4 contract", () => { const expected = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_NUM_REWARD_SET_POX_ADDRESSES, + "pox-4", + "get-num-reward-set-pox-addresses", [Cl.uint(reward_cycle)], caller ); @@ -1469,8 +1523,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_PARTIAL_STACKED_BY_CYCLE, + "pox-4", + "get-partial-stacked-by-cycle", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1524,8 +1578,8 @@ describe("test pox-4 contract", () => { ); // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_SIGNER_KEY_MESSAGE_HASH, + "pox-4", + "get-signer-key-message-hash", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), From 7572bb01155b38f7a3681baa851c6f68b006a51d Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Fri, 8 Mar 2024 13:10:10 +0200 Subject: [PATCH 10/24] Update according to comments --- .../tests/pox-4/pox-4.prop.test.ts | 2916 ++++++++--------- 1 file changed, 1454 insertions(+), 1462 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 1a56d314c2..b82d212477 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -96,1510 +96,1502 @@ export const buildSignerKeyMessageHash = ( return signer_key_message_hash; }; -describe("test pox-4 contract", () => { - describe("test pox-4 contract read only functions", () => { - it("should return correct reward-cycle-to-burn-height", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (account, reward_cycle) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - account - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const first_burn_block_height = - pox_4_info.value.data["first-burnchain-block-height"]; - const reward_cycle_length = - pox_4_info.value.data["reward-cycle-length"]; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "reward-cycle-to-burn-height", - [Cl.uint(reward_cycle)], - account - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - assert(isClarityType(first_burn_block_height, ClarityType.UInt)); - assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - const expected = - Number(first_burn_block_height.value) + - Number(reward_cycle_length.value) * reward_cycle; - expect(actual).toBeUint(expected); - } - ) - ); - }); +describe("test pox-4 contract read only functions", () => { + it("should return correct reward-cycle-to-burn-height", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, reward_cycle) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "reward-cycle-to-burn-height", + [Cl.uint(reward_cycle)], + account + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + const expected = + Number(first_burn_block_height.value) + + Number(reward_cycle_length.value) * reward_cycle; + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return correct burn-height-to-reward-cycle", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (account, burn_height) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - account - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const first_burn_block_height = - pox_4_info.value.data["first-burnchain-block-height"]; - const reward_cycle_length = - pox_4_info.value.data["reward-cycle-length"]; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "burn-height-to-reward-cycle", - [Cl.uint(burn_height)], - account - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - assert(isClarityType(first_burn_block_height, ClarityType.UInt)); - assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - const expected = Math.floor( - (burn_height - Number(first_burn_block_height.value)) / - Number(reward_cycle_length.value) - ); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return correct burn-height-to-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, burn_height) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "burn-height-to-reward-cycle", + [Cl.uint(burn_height)], + account + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + const expected = Math.floor( + (burn_height - Number(first_burn_block_height.value)) / + Number(reward_cycle_length.value) + ); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return u0 current-pox-reward-cycle", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - let expected = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "current-pox-reward-cycle", - [], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return u0 current-pox-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + let expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "current-pox-reward-cycle", + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return none get-stacker-info", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - (stacker, caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-stacker-info", - [Cl.principal(stacker)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - expect(actual).toBeNone(); - } - ) - ); - }); + it("should return none get-stacker-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (stacker, caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-stacker-info", + [Cl.principal(stacker)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); - it("should return true check-caller-allowed", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-caller-allowed", - [], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(true); - } - ) - ); - }); + it("should return true check-caller-allowed", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-caller-allowed", + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(true); + } + ) + ); + }); - it("should return u0 get-reward-set-size", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-reward-set-size", - [Cl.uint(reward_cycle)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return u0 get-reward-set-size", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-reward-set-size", + [Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return u0 get-total-ustx-stacked", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-total-ustx-stacked", - [Cl.uint(reward_cycle)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return u0 get-total-ustx-stacked", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-total-ustx-stacked", + [Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return none get-reward-set-pox-address", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - fc.nat(), - (caller, index, reward_cycle) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-reward-set-pox-address", - [Cl.uint(index), Cl.uint(reward_cycle)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - expect(actual).toBeNone(); - } - ) - ); - }); + it("should return none get-reward-set-pox-address", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + fc.nat(), + (caller, index, reward_cycle) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-reward-set-pox-address", + [Cl.uint(index), Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); - it("should return correct get-stacking-minimum", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const stx_liq_supply = - pox_4_info.value.data["total-liquid-supply-ustx"]; - assert(isClarityType(stx_liq_supply, ClarityType.UInt)); - const expected = Math.floor( - Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 - ); - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-stacking-minimum", - [], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return correct get-stacking-minimum", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const stx_liq_supply = + pox_4_info.value.data["total-liquid-supply-ustx"]; + assert(isClarityType(stx_liq_supply, ClarityType.UInt)); + const expected = Math.floor( + Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-stacking-minimum", + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return true check-pox-addr-version for version <= 6 ", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 6 }), - (caller, version) => { - // Arrange - const expected = true; - // Act - let { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-addr-version", - [Cl.buffer(Uint8Array.from([version]))], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return true check-pox-addr-version for version <= 6 ", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + (caller, version) => { + // Arrange + const expected = true; + // Act + let { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-addr-version", + [Cl.buffer(Uint8Array.from([version]))], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return false check-pox-addr-version for version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 7, max: 255 }), - (caller, version) => { - // Arrange - const expected = false; - // Act - let { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-addr-version", - [Cl.buffer(Uint8Array.from([version]))], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return false check-pox-addr-version for version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 7, max: 255 }), + (caller, version) => { + // Arrange + const expected = false; + // Act + let { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-addr-version", + [Cl.buffer(Uint8Array.from([version]))], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return true check-pox-lock-period for valid reward cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 1, max: 12 }), - (caller, reward_cycles) => { - // Arrange - const expected = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return true check-pox-lock-period for valid reward cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 1, max: 12 }), + (caller, valid_reward_cycles) => { + // Arrange + const expected = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-lock-period", + [Cl.uint(valid_reward_cycles)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return false check-pox-lock-period for reward cycles number > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 13 }), - (caller, reward_cycles) => { - // Arrange - const expected = false; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return false check-pox-lock-period for reward cycles number > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 13 }), + (caller, invalid_reward_cycles) => { + // Arrange + const expected = false; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-lock-period", + [Cl.uint(invalid_reward_cycles)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return false check-pox-lock-period for reward cycles number == 0", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - const reward_cycles = 0; - const expected = false; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return false check-pox-lock-period for reward cycles number == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const invalid_reward_cycles = 0; + const expected = false; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-lock-period", + [Cl.uint(invalid_reward_cycles)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 20, - maxLength: 20, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); + it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseOk = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); - it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 5, max: 6 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); + it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseOk = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); - it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ - min: 7, - max: 255, - }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 21, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 19, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 31, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: 0n, - max: 124_999_999_999n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 0n, + max: 124_999_999_999n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 2) can-stack-stx for lock period > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 13 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 2) can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 20, - maxLength: 20, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); + it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseOk = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); - it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 5, max: 6 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); + it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseOk = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); - it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ - min: 7, - max: 255, - }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 21, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 19, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 31, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 13 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - (caller, version, hashbytes, first_rew_cycle, num_cycles) => { - // Arrange - const amount_ustx = 0; - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + (caller, version, hashbytes, first_rew_cycle, num_cycles) => { + // Arrange + const amount_ustx = 0; + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return none get-check-delegation", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-check-delegation", - [Cl.principal(caller)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - } - ) - ); - }); + it("should return none get-check-delegation", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-check-delegation", + [Cl.principal(caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); - it("should return none get-delegation-info", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-delegation-info", - [Cl.principal(caller)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - } - ) - ); - }); + it("should return none get-delegation-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-delegation-info", + [Cl.principal(caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + + it("should return correct get-pox-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const expected_reward_cycle_id = 0, + expected_first_burn_block_height = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual.value.data["first-burnchain-block-height"]).toBeUint( + expected_first_burn_block_height + ); + expect(actual.value.data["min-amount-ustx"]).toBeUint( + MIN_AMOUNT_USTX + ); + expect(actual.value.data["prepare-cycle-length"]).toBeUint( + TESTNET_PREPARE_CYCLE_LENGTH + ); + expect(actual.value.data["reward-cycle-id"]).toBeUint( + expected_reward_cycle_id + ); + expect(actual.value.data["reward-cycle-length"]).toBeUint( + TESTNET_REWARD_CYCLE_LENGTH + ); + expect(actual.value.data["total-liquid-supply-ustx"]).toBeUint( + INITIAL_TOTAL_LIQ_SUPPLY + ); + } + ) + ); + }); - it("should return correct get-pox-info", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - const expected_reward_cycle_id = 0, - expected_first_burn_block_height = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.Tuple)); - expect(actual.value.data["first-burnchain-block-height"]).toBeUint( - expected_first_burn_block_height - ); - expect(actual.value.data["min-amount-ustx"]).toBeUint( - MIN_AMOUNT_USTX - ); - expect(actual.value.data["prepare-cycle-length"]).toBeUint( - TESTNET_PREPARE_CYCLE_LENGTH - ); - expect(actual.value.data["reward-cycle-id"]).toBeUint( - expected_reward_cycle_id - ); - expect(actual.value.data["reward-cycle-length"]).toBeUint( - TESTNET_REWARD_CYCLE_LENGTH - ); - expect(actual.value.data["total-liquid-supply-ustx"]).toBeUint( - INITIAL_TOTAL_LIQ_SUPPLY - ); - } - ) - ); - }); + it("should return none get-allowance-contract-caller", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, sender, contract_caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-allowance-contract-callers", + [Cl.principal(sender), Cl.principal(contract_caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); - it("should return none get-allowance-contract-caller", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - (caller, sender, contract_caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-allowance-contract-callers", - [Cl.principal(sender), Cl.principal(contract_caller)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - } - ) - ); - }); + it("should return some(until-burn-ht: none) get-allowance-contract-caller after allow-contract-caller", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, sender, contract_caller) => { + // Arrange + const { result: allow } = simnet.callPublicFn( + "pox-4", + "allow-contract-caller", + [Cl.principal(contract_caller), Cl.none()], + sender + ); + assert(isClarityType(allow, ClarityType.ResponseOk)); + assert(isClarityType(allow.value, ClarityType.BoolTrue)); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-allowance-contract-callers", + [Cl.principal(sender), Cl.principal(contract_caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalSome)); + assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual.value).toBeTuple({ "until-burn-ht": Cl.none() }); + } + ) + ); + }); - it("should return some(until-burn-ht: none) get-allowance-contract-caller after allow-contract-caller", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - (caller, sender, contract_caller) => { - // Arrange - const { result: allow } = simnet.callPublicFn( - "pox-4", - "allow-contract-caller", - [Cl.principal(contract_caller), Cl.none()], - sender - ); - assert(isClarityType(allow, ClarityType.ResponseOk)); - assert(isClarityType(allow.value, ClarityType.BoolTrue)); - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-allowance-contract-callers", - [Cl.principal(sender), Cl.principal(contract_caller)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalSome)); - assert(isClarityType(actual.value, ClarityType.Tuple)); - expect(actual.value).toBeTuple({ "until-burn-ht": Cl.none() }); - } - ) - ); - }); + it("should return u0 get-num-reward-set-pox-addresses", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-num-reward-set-pox-addresses", + [Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return u0 get-num-reward-set-pox-addresses", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-num-reward-set-pox-addresses", - [Cl.uint(reward_cycle)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return none get-partial-stacked-by-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, version, hashbytes, reward_cycle, sender) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-partial-stacked-by-cycle", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.principal(sender), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); - it("should return none get-partial-stacked-by-cycle", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 6 }), - fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), - fc.nat(), - fc.constantFrom(...simnet.getAccounts().values()), - (caller, version, hashbytes, reward_cycle, sender) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-partial-stacked-by-cycle", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(reward_cycle), - Cl.principal(sender), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - } - ) - ); - }); + it("should return correct hash get-signer-key-message-hash", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + max_amount, + auth_id + ) => { + // Arrange - it("should return correct hash get-signer-key-message-hash", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 6 }), - fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), - fc.nat(), - fc.nat(), - // fc.asciiString({ maxLength: 10, minLength: 1 }), - fc.nat(), - fc.nat(), - ( - caller, + const signer_key_message_hash = buildSignerKeyMessageHash( version, hashbytes, reward_cycle, + "topic", period, - // topic, max_amount, auth_id - ) => { - // Arrange - // clarinet bug string: - // r;NT=" - - const signer_key_message_hash = buildSignerKeyMessageHash( - version, - hashbytes, - reward_cycle, - "topic", - period, - max_amount, - auth_id - ); - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-signer-key-message-hash", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(reward_cycle), - Cl.stringAscii("topic"), - Cl.uint(period), - Cl.uint(max_amount), - Cl.uint(auth_id), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.Buffer)); - expect(actual).toBeBuff(signer_key_message_hash); - } - ) - ); - }); - // verify-signer-key-sig + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-signer-key-message-hash", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii("topic"), + Cl.uint(period), + Cl.uint(max_amount), + Cl.uint(auth_id), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.Buffer)); + expect(actual).toBeBuff(signer_key_message_hash); + } + ) + ); }); + // verify-signer-key-sig }); From 91bf380f18e770a33761c0c87f0e03b8b52517d7 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Fri, 8 Mar 2024 18:53:36 +0200 Subject: [PATCH 11/24] added tests for verify-signer-key-sig --- .../tests/pox-4/pox-4.prop.test.ts | 257 +++++++++++++++++- 1 file changed, 249 insertions(+), 8 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index b82d212477..485d42eebd 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -2,8 +2,11 @@ import { Cl, ClarityType, ClarityValue, + createStacksPrivateKey, isClarityType, + pubKeyfromPrivKey, serializeCV, + signWithKey, } from "@stacks/transactions"; import fc from "fast-check"; import { assert, describe, expect, it } from "vitest"; @@ -24,14 +27,39 @@ const ERR_STACKING_INVALID_LOCK_PERIOD = 2; const ERR_STACKING_THRESHOLD_NOT_MET = 11; const ERR_STACKING_INVALID_POX_ADDRESS = 13; const ERR_STACKING_INVALID_AMOUNT = 18; +const ERR_INVALID_SIGNATURE_PUBKEY = 35; +const ERR_SIGNER_AUTH_AMOUNT_TOO_HIGH = 38; +// Private Keys +const privateKeyMapping: { + [key: string]: string; +} = { + ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM: + "753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601", + ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5: + "7287ba251d44a4d3fd9276c88ce34c5c52a038955511cccaf77e61068649c17801", + ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG: + "530d9f61984c888536871c6573073bdfc0058896dc1adfe9a6a10dfacadc209101", + ST2JHG361ZXG51QTKY2NQCVBPPRRE2KZB1HR05NNC: + "d655b2523bcd65e34889725c73064feb17ceb796831c0e111ba1a552b0f31b3901", + ST2NEB84ASENDXKYGJPQW86YXQCEFEX2ZQPG87ND: + "f9d7206a47f14d2870c163ebab4bf3e70d18f5d14ce1031f3902fbbc894fe4c701", + ST2REHHS5J3CERCRBEPMGH7921Q6PYKAADT7JP2VB: + "3eccc5dac8056590432db6a35d52b9896876a3d5cbdea53b72400bc9c2099fe801", + ST3AM1A56AK2C1XAFJ4115ZSV26EB49BVQ10MGCS0: + "7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01", + ST3PF13W7Z0RRM42A8VZRVFQ75SV1K26RXEP8YGKJ: + "b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401", + ST3NBRSFKX28FQ2ZJ1MAKX58HKHSDGNV5N7R21XCP: + "6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01", + STNHKEPYEPJ8ET55ZZ0M5A34J0R3N5FM2CMMMAZ6: + "de433bdfa14ec43aa1098d5be594c8ffb20a31485ff9de2923b2689471c401b801", +}; -function sha256(data: Buffer): Buffer { - return createHash("sha256").update(data).digest(); -} +const sha256 = (data: Buffer): Buffer => + createHash("sha256").update(data).digest(); -function structuredDataHash(structuredData: ClarityValue): Buffer { - return sha256(Buffer.from(serializeCV(structuredData))); -} +const structuredDataHash = (structuredData: ClarityValue): Buffer => + sha256(Buffer.from(serializeCV(structuredData))); const generateDomainHash = (): ClarityValue => Cl.tuple({ @@ -64,7 +92,7 @@ const generateMessageHash = ( const generateMessagePrefixBuffer = (prefix: string) => Buffer.from(prefix, "hex"); -export const buildSignerKeyMessageHash = ( +const buildSignerKeyMessageHash = ( version: number, hashbytes: number[], reward_cycle: number, @@ -96,6 +124,14 @@ export const buildSignerKeyMessageHash = ( return signer_key_message_hash; }; +const signMessageHash = (privateKey: string, messageHash: Buffer) => { + const data = signWithKey( + createStacksPrivateKey(privateKey), + messageHash.toString("hex") + ).data; + return Buffer.from(data.slice(2) + data.slice(0, 2), "hex"); +}; + describe("test pox-4 contract read only functions", () => { it("should return correct reward-cycle-to-burn-height", () => { fc.assert( @@ -1593,5 +1629,210 @@ describe("test pox-4 contract read only functions", () => { ) ); }); - // verify-signer-key-sig + + it("should return (ok true) verify-signer-key-sig called with correct data", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + amount, + max_amount, + auth_id + ) => { + // Arrange + fc.pre(amount <= max_amount); + const signer_private_key = privateKeyMapping[caller] ?? ""; + const signer_key_message_hash = buildSignerKeyMessageHash( + version, + hashbytes, + reward_cycle, + "topic", + period, + max_amount, + auth_id + ); + const signer_sig = signMessageHash( + signer_private_key, + signer_key_message_hash + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "verify-signer-key-sig", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii("topic"), + Cl.uint(period), + Cl.some(Cl.buffer(signer_sig)), + Cl.buffer(pubKeyfromPrivKey(signer_private_key).data), + Cl.uint(amount), + Cl.uint(max_amount), + Cl.uint(auth_id), + ], + caller + ); + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(true)); + expect(actual.value).toBeBool(true); + } + ) + ); + }); + + it("should return (err 35) verify-signer-key-sig called with wrong public key", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + fc.constantFrom(...simnet.getAccounts().values()), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + amount, + max_amount, + auth_id, + wrong_address + ) => { + // Arrange + fc.pre(amount <= max_amount); + fc.pre(wrong_address !== caller); + const expectedResponseErr = ERR_INVALID_SIGNATURE_PUBKEY; + const signer_private_key = privateKeyMapping[caller]; + const wrong_private_key = privateKeyMapping[wrong_address]; + const signer_key_message_hash = buildSignerKeyMessageHash( + version, + hashbytes, + reward_cycle, + "topic", + period, + max_amount, + auth_id + ); + const signer_sig = signMessageHash( + signer_private_key, + signer_key_message_hash + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "verify-signer-key-sig", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii("topic"), + Cl.uint(period), + Cl.some(Cl.buffer(signer_sig)), + Cl.buffer(pubKeyfromPrivKey(wrong_private_key).data), + Cl.uint(amount), + Cl.uint(max_amount), + Cl.uint(auth_id), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + expect(actual.value).toBeInt(expectedResponseErr); + } + ) + ); + }); + + it("should return (err 38) verify-signer-key-sig called with wrong public key", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + amount, + max_amount, + auth_id + ) => { + // Arrange + fc.pre(amount > max_amount); + const expectedResponseErr = ERR_SIGNER_AUTH_AMOUNT_TOO_HIGH; + const signer_private_key = privateKeyMapping[caller]; + const signer_key_message_hash = buildSignerKeyMessageHash( + version, + hashbytes, + reward_cycle, + "topic", + period, + max_amount, + auth_id + ); + const signer_sig = signMessageHash( + signer_private_key, + signer_key_message_hash + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "verify-signer-key-sig", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii("topic"), + Cl.uint(period), + Cl.some(Cl.buffer(signer_sig)), + Cl.buffer(pubKeyfromPrivKey(signer_private_key).data), + Cl.uint(amount), + Cl.uint(max_amount), + Cl.uint(auth_id), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + expect(actual.value).toBeInt(expectedResponseErr); + } + ) + ); + }); }); From 05c4a7af602e11e154af0cd22e5f251ede33481a Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Fri, 1 Mar 2024 20:36:50 +0200 Subject: [PATCH 12/24] added property tests for pox-4 read only functions --- .../tests/pox-4/pox-4.prop.test.ts | 434 ++++++++++++++++++ 1 file changed, 434 insertions(+) create mode 100644 contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts new file mode 100644 index 0000000000..65dc88cc08 --- /dev/null +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -0,0 +1,434 @@ +import Cl, { ClarityType, bufferCV, isClarityType } from "@stacks/transactions"; +import { assert, describe, expect, it } from "vitest"; +import fc from "fast-check"; + +const POX_4 = "pox-4"; +const GET_POX_INFO = "get-pox-info"; + +describe("test pox-4 contract read only functions", () => { + it("should return correct reward-cycle-to-burn-height", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, reward_cycle) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "reward-cycle-to-burn-height", + [Cl.uintCV(reward_cycle)], + account + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + + const expected = + Number(first_burn_block_height.value) + + Number(reward_cycle_length.value) * reward_cycle; + expect(actual).toBeUint(expected); + } + ), + { numRuns: 300 } + ); + }); + + it("should return correct burn-height-to-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, burn_height) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "burn-height-to-reward-cycle", + [Cl.uintCV(burn_height)], + account + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + const expected = Math.floor( + (burn_height - Number(first_burn_block_height.value)) / + Number(reward_cycle_length.value) + ); + expect(actual).toBeUint(expected); + } + ), + { numRuns: 300 } + ); + }); + + it("should return none stacker-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (stacker, caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-stacker-info", + [Cl.principalCV(stacker)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); + + it("should return correct check-caller-allowed", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-caller-allowed", + [], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(true); + } + ) + ); + }); + + it("should return u0 get-reward-set-size", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-reward-set-size", + [Cl.uintCV(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return u0 get-total-ustx-stacked", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-total-ustx-stacked", + [Cl.uintCV(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return none get-reward-set-pox-address", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + fc.nat(), + (caller, index, reward_cycle) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-reward-set-pox-address", + [Cl.uintCV(index), Cl.uintCV(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); + + it("should return correct get-stacking-minimum", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const testnet_stacking_threshold_25 = 8000; + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const stx_liq_supply = + pox_4_info.value.data["total-liquid-supply-ustx"]; + + assert(isClarityType(stx_liq_supply, ClarityType.UInt)); + const expected = Math.floor( + Number(stx_liq_supply.value) / testnet_stacking_threshold_25 + ); + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "get-stacking-minimum", + [], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return correct check-pox-addr-version", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 255 }), + (caller, version) => { + // Arrange + const expected = version > 6 ? false : true; + + // Act + let { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-addr-version", + [Cl.bufferCV(Uint8Array.from([version]))], + caller + ); + + // Assert + assert( + isClarityType( + actual, + expected ? ClarityType.BoolTrue : ClarityType.BoolFalse + ) + ); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return correct check-pox-lock-period", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycles) => { + // Arrange + const expected = + reward_cycles > 0 && reward_cycles <= 12 ? true : false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-lock-period", + [Cl.uintCV(reward_cycles)], + caller + ); + + // Assert + assert( + isClarityType( + actual, + expected ? ClarityType.BoolTrue : ClarityType.BoolFalse + ) + ); + expect(actual).toBeBool(expected); + } + ) + ), + { numRuns: 250 }; + }); + + it("should return correct can-stack-stx", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 255 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.bigInt({ min: 0n, max: 340282366920938463463374607431768211455n }), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const testnet_stacking_threshold_25 = 8000; + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const stacking_valid_amount = amount_ustx > 0; + const pox_lock_period_valid = num_cycles > 0 && num_cycles <= 12; + const pox_version_valid = version <= 6; + const pox_hashbytes_valid = + hashbytes.length === 20 || hashbytes.length === 32; + const stx_liq_supply = + pox_4_info.value.data["total-liquid-supply-ustx"]; + + assert(isClarityType(stx_liq_supply, ClarityType.UInt)); + const stacking_threshold_met = + amount_ustx >= + Math.floor( + Number(stx_liq_supply.value) / testnet_stacking_threshold_25 + ); + const expectedResponseErr = !stacking_threshold_met + ? 11 + : !stacking_valid_amount + ? 18 + : !pox_lock_period_valid + ? 2 + : !pox_version_valid + ? 13 + : !pox_hashbytes_valid + ? 13 + : 0; + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tupleCV({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uintCV(amount_ustx), + Cl.uintCV(first_rew_cycle), + Cl.uintCV(num_cycles), + ], + caller + ); + + // Assert + assert( + isClarityType( + actual, + stacking_threshold_met && + stacking_valid_amount && + pox_lock_period_valid && + pox_version_valid && + pox_hashbytes_valid + ? ClarityType.ResponseOk + : ClarityType.ResponseErr + ) + ); + + assert( + isClarityType( + actual.value, + stacking_threshold_met && + stacking_valid_amount && + pox_lock_period_valid && + pox_version_valid && + pox_hashbytes_valid + ? ClarityType.BoolTrue + : ClarityType.Int + ) + ); + if (expectedResponseErr === 0) { + expect(actual).toBeOk( + Cl.responseOkCV(Cl.boolCV(expectedResponseOk)) + ); + expect(actual.value).toBeBool(expectedResponseOk); + } else { + expect(actual).toBeErr(Cl.intCV(expectedResponseErr)); + expect(actual.value).toBeInt(expectedResponseErr); + } + } + ), + { numRuns: 300 } + ); + }); +}); From 2d8516eb3910b6617d7f2a81045eced4bc3a10a5 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Fri, 1 Mar 2024 20:46:36 +0200 Subject: [PATCH 13/24] rename get-stacker-info test --- contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 65dc88cc08..54d5f5dd22 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -94,7 +94,7 @@ describe("test pox-4 contract read only functions", () => { ); }); - it("should return none stacker-info", () => { + it("should return none get-stacker-info", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), From 1dfed13a71e61275f791abc7638ccb03ec51b7cd Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Mon, 4 Mar 2024 16:51:39 +0200 Subject: [PATCH 14/24] Split conditional tests --- .../tests/pox-4/pox-4.prop.test.ts | 332 ++++++++++++------ 1 file changed, 231 insertions(+), 101 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 54d5f5dd22..d084d7759d 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,9 +1,11 @@ -import Cl, { ClarityType, bufferCV, isClarityType } from "@stacks/transactions"; +import { Cl, ClarityType, bufferCV, isClarityType } from "@stacks/transactions"; import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; const POX_4 = "pox-4"; const GET_POX_INFO = "get-pox-info"; +const testnet_stacking_threshold_25 = 8000; +fc.configureGlobal({ numRuns: 250 }); describe("test pox-4 contract read only functions", () => { it("should return correct reward-cycle-to-burn-height", () => { @@ -31,7 +33,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "reward-cycle-to-burn-height", - [Cl.uintCV(reward_cycle)], + [Cl.uint(reward_cycle)], account ); @@ -45,8 +47,7 @@ describe("test pox-4 contract read only functions", () => { Number(reward_cycle_length.value) * reward_cycle; expect(actual).toBeUint(expected); } - ), - { numRuns: 300 } + ) ); }); @@ -75,7 +76,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "burn-height-to-reward-cycle", - [Cl.uintCV(burn_height)], + [Cl.uint(burn_height)], account ); @@ -89,8 +90,7 @@ describe("test pox-4 contract read only functions", () => { ); expect(actual).toBeUint(expected); } - ), - { numRuns: 300 } + ) ); }); @@ -106,7 +106,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "get-stacker-info", - [Cl.principalCV(stacker)], + [Cl.principal(stacker)], caller ); @@ -118,7 +118,7 @@ describe("test pox-4 contract read only functions", () => { ); }); - it("should return correct check-caller-allowed", () => { + it("should return true check-caller-allowed", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), @@ -154,7 +154,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "get-reward-set-size", - [Cl.uintCV(reward_cycle)], + [Cl.uint(reward_cycle)], caller ); @@ -179,7 +179,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "get-total-ustx-stacked", - [Cl.uintCV(reward_cycle)], + [Cl.uint(reward_cycle)], caller ); @@ -204,7 +204,7 @@ describe("test pox-4 contract read only functions", () => { const { result: actual } = simnet.callReadOnlyFn( POX_4, "get-reward-set-pox-address", - [Cl.uintCV(index), Cl.uintCV(reward_cycle)], + [Cl.uint(index), Cl.uint(reward_cycle)], caller ); @@ -222,7 +222,6 @@ describe("test pox-4 contract read only functions", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - const testnet_stacking_threshold_25 = 8000; const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, @@ -257,77 +256,206 @@ describe("test pox-4 contract read only functions", () => { ); }); - it("should return correct check-pox-addr-version", () => { + it("should return true check-pox-addr-version for version <= 6 ", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 255 }), + fc.nat({ max: 6 }), (caller, version) => { // Arrange - const expected = version > 6 ? false : true; + const expected = true; // Act let { result: actual } = simnet.callReadOnlyFn( POX_4, "check-pox-addr-version", - [Cl.bufferCV(Uint8Array.from([version]))], + [Cl.buffer(Uint8Array.from([version]))], caller ); // Assert - assert( - isClarityType( - actual, - expected ? ClarityType.BoolTrue : ClarityType.BoolFalse - ) + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-addr-version for version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 7, max: 255 }), + (caller, version) => { + // Arrange + const expected = false; + + // Act + let { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-addr-version", + [Cl.buffer(Uint8Array.from([version]))], + caller ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); } ) ); }); - it("should return correct check-pox-lock-period", () => { + it("should return true check-pox-lock-period for valid reward cycles number", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), + fc.integer({ min: 1, max: 12 }), (caller, reward_cycles) => { // Arrange - const expected = - reward_cycles > 0 && reward_cycles <= 12 ? true : false; + const expected = true; // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, "check-pox-lock-period", - [Cl.uintCV(reward_cycles)], + [Cl.uint(reward_cycles)], caller ); // Assert - assert( - isClarityType( - actual, - expected ? ClarityType.BoolTrue : ClarityType.BoolFalse - ) + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-lock-period for reward cycles number > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 13 }), + (caller, reward_cycles) => { + // Arrange + const expected = false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-lock-period", + [Cl.uint(reward_cycles)], + caller ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); } ) - ), - { numRuns: 250 }; + ); }); - it("should return correct can-stack-stx", () => { + it("should return false check-pox-lock-period for reward cycles number == 0", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 255 }), - fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), - fc.bigInt({ min: 0n, max: 340282366920938463463374607431768211455n }), + (caller) => { + // Arrange + const reward_cycles = 0; + const expected = false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "check-pox-lock-period", + [Cl.uint(reward_cycles)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), fc.nat(), + fc.integer({ min: 1, max: 12 }), ( caller, version, @@ -337,7 +465,6 @@ describe("test pox-4 contract read only functions", () => { num_cycles ) => { // Arrange - const testnet_stacking_threshold_25 = 8000; const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, @@ -348,31 +475,6 @@ describe("test pox-4 contract read only functions", () => { assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const stacking_valid_amount = amount_ustx > 0; - const pox_lock_period_valid = num_cycles > 0 && num_cycles <= 12; - const pox_version_valid = version <= 6; - const pox_hashbytes_valid = - hashbytes.length === 20 || hashbytes.length === 32; - const stx_liq_supply = - pox_4_info.value.data["total-liquid-supply-ustx"]; - - assert(isClarityType(stx_liq_supply, ClarityType.UInt)); - const stacking_threshold_met = - amount_ustx >= - Math.floor( - Number(stx_liq_supply.value) / testnet_stacking_threshold_25 - ); - const expectedResponseErr = !stacking_threshold_met - ? 11 - : !stacking_valid_amount - ? 18 - : !pox_lock_period_valid - ? 2 - : !pox_version_valid - ? 13 - : !pox_hashbytes_valid - ? 13 - : 0; const expectedResponseOk = true; // Act @@ -380,55 +482,83 @@ describe("test pox-4 contract read only functions", () => { POX_4, "can-stack-stx", [ - Cl.tupleCV({ + Cl.tuple({ version: bufferCV(Uint8Array.from([version])), hashbytes: bufferCV(Uint8Array.from(hashbytes)), }), - Cl.uintCV(amount_ustx), - Cl.uintCV(first_rew_cycle), - Cl.uintCV(num_cycles), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), ], caller ); // Assert - assert( - isClarityType( - actual, - stacking_threshold_met && - stacking_valid_amount && - pox_lock_period_valid && - pox_version_valid && - pox_hashbytes_valid - ? ClarityType.ResponseOk - : ClarityType.ResponseErr - ) + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = 13; - assert( - isClarityType( - actual.value, - stacking_threshold_met && - stacking_valid_amount && - pox_lock_period_valid && - pox_version_valid && - pox_hashbytes_valid - ? ClarityType.BoolTrue - : ClarityType.Int - ) + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller ); - if (expectedResponseErr === 0) { - expect(actual).toBeOk( - Cl.responseOkCV(Cl.boolCV(expectedResponseOk)) - ); - expect(actual.value).toBeBool(expectedResponseOk); - } else { - expect(actual).toBeErr(Cl.intCV(expectedResponseErr)); - expect(actual.value).toBeInt(expectedResponseErr); - } + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); } - ), - { numRuns: 300 } + ) ); }); }); From b1166b6268e2ff40aa17d970416c6116fbc09534 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Tue, 5 Mar 2024 16:49:33 +0200 Subject: [PATCH 15/24] Added tests for minimal-can-stack-stx --- .../tests/pox-4/pox-4.prop.test.ts | 786 +++++++++++++++++- 1 file changed, 782 insertions(+), 4 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index d084d7759d..a377fa9915 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,10 +1,25 @@ -import { Cl, ClarityType, bufferCV, isClarityType } from "@stacks/transactions"; +import { + Cl, + ClarityType, + bufferCV, + cvToJSON, + isClarityType, +} from "@stacks/transactions"; import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; +// contracts const POX_4 = "pox-4"; +// methods const GET_POX_INFO = "get-pox-info"; -const testnet_stacking_threshold_25 = 8000; +// contract consts +const TESTNET_STACKING_THRESHOLD_25 = 8000; +// error codes +const ERR_STACKING_INVALID_LOCK_PERIOD = 2; +const ERR_STACKING_THRESHOLD_NOT_MET = 11; +const ERR_STACKING_INVALID_POX_ADDRESS = 13; +const ERR_STACKING_INVALID_AMOUNT = 18; + fc.configureGlobal({ numRuns: 250 }); describe("test pox-4 contract read only functions", () => { @@ -237,7 +252,7 @@ describe("test pox-4 contract read only functions", () => { assert(isClarityType(stx_liq_supply, ClarityType.UInt)); const expected = Math.floor( - Number(stx_liq_supply.value) / testnet_stacking_threshold_25 + Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 ); // Act @@ -502,6 +517,69 @@ describe("test pox-4 contract read only functions", () => { ); }); + it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { fc.assert( fc.property( @@ -535,7 +613,182 @@ describe("test pox-4 contract read only functions", () => { assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = 13; + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 0n, + max: 124_999_999_999n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; // Act const { result: actual } = simnet.callReadOnlyFn( @@ -561,4 +814,529 @@ describe("test pox-4 contract read only functions", () => { ) ); }); + + it("should return (err 2) can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + // minimal can stack stx + it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 125_000_000_000n, + max: 340282366920938463463374607431768211455n, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer(), + fc.array(fc.nat({ max: 255 })), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + (caller, version, hashbytes, first_rew_cycle, num_cycles) => { + // Arrange + const amount_ustx = 0; + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: bufferCV(Uint8Array.from([version])), + hashbytes: bufferCV(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); }); From 895ba1c94c6a4101bdbbac3ddc0b1977ed0580b0 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Wed, 6 Mar 2024 19:04:20 +0200 Subject: [PATCH 16/24] added tests for read only functions - get-check-delegation - get-delegation-info - get-allowance-contract-callers - get-pox-info - minimal-can-stack-stx --- .../tests/pox-4/pox-4.prop.test.ts | 2843 +++++++++-------- 1 file changed, 1514 insertions(+), 1329 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index a377fa9915..506ebd2864 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,1342 +1,1527 @@ -import { - Cl, - ClarityType, - bufferCV, - cvToJSON, - isClarityType, -} from "@stacks/transactions"; +import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; -// contracts +// Contracts const POX_4 = "pox-4"; -// methods +// Methods const GET_POX_INFO = "get-pox-info"; -// contract consts +const GET_STACKER_INFO = "get-stacker-info"; +const REWARD_CYCLE_TO_BURN_HEIGHT = "reward-cycle-to-burn-height"; +const BURN_HEIGHT_TO_REWARD_CYCLE = "burn-height-to-reward-cycle"; +const CURRENT_POX_REWARD_CYCLE = "current-pox-reward-cycle"; +const CHECK_CALLER_ALLOWED = "check-caller-allowed"; +const GET_REWARD_SET_SIZE = "get-reward-set-size"; +const GET_REWARD_SET_POX_ADDRESS = "get-reward-set-pox-address"; +const GET_TOTAL_USTX_STACKED = "get-total-ustx-stacked"; +const CHECK_POX_ADDR_VERSION = "check-pox-addr-version"; +const CHECK_POX_LOCK_PERIOD = "check-pox-lock-period"; +const GET_STACKING_MINIMUM = "get-stacking-minimum"; +const CAN_STACK_STX = "can-stack-stx"; +const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; +const GET_CHECK_DELEGATION = "get-check-delegation"; +const GET_DELEGATION_INFO = "get-delegation-info"; +const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; +const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; +// Contract Consts const TESTNET_STACKING_THRESHOLD_25 = 8000; -// error codes +const TESTNET_REWARD_CYCLE_LENGTH = 1050; +const TESTNET_PREPARE_CYCLE_LENGTH = 50; +const INITIAL_TOTAL_LIQ_SUPPLY = 1_000_000_000_000_000; +const MIN_AMOUNT_USTX = 125_000_000_000n; +// Clarity Constraints +const MAX_CLAR_UINT = 340282366920938463463374607431768211455n; +// Error Codes const ERR_STACKING_INVALID_LOCK_PERIOD = 2; const ERR_STACKING_THRESHOLD_NOT_MET = 11; const ERR_STACKING_INVALID_POX_ADDRESS = 13; const ERR_STACKING_INVALID_AMOUNT = 18; -fc.configureGlobal({ numRuns: 250 }); - -describe("test pox-4 contract read only functions", () => { - it("should return correct reward-cycle-to-burn-height", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (account, reward_cycle) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - account - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const first_burn_block_height = - pox_4_info.value.data["first-burnchain-block-height"]; - const reward_cycle_length = - pox_4_info.value.data["reward-cycle-length"]; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "reward-cycle-to-burn-height", - [Cl.uint(reward_cycle)], - account - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - assert(isClarityType(first_burn_block_height, ClarityType.UInt)); - assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - - const expected = - Number(first_burn_block_height.value) + - Number(reward_cycle_length.value) * reward_cycle; - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return correct burn-height-to-reward-cycle", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (account, burn_height) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - account - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const first_burn_block_height = - pox_4_info.value.data["first-burnchain-block-height"]; - const reward_cycle_length = - pox_4_info.value.data["reward-cycle-length"]; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "burn-height-to-reward-cycle", - [Cl.uint(burn_height)], - account - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - assert(isClarityType(first_burn_block_height, ClarityType.UInt)); - assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - const expected = Math.floor( - (burn_height - Number(first_burn_block_height.value)) / - Number(reward_cycle_length.value) - ); - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return none get-stacker-info", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - (stacker, caller) => { - // Arrange - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-stacker-info", - [Cl.principal(stacker)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - expect(actual).toBeNone(); - } - ) - ); - }); - - it("should return true check-caller-allowed", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-caller-allowed", - [], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(true); - } - ) - ); - }); - - it("should return u0 get-reward-set-size", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-reward-set-size", - [Cl.uint(reward_cycle)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return u0 get-total-ustx-stacked", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-total-ustx-stacked", - [Cl.uint(reward_cycle)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return none get-reward-set-pox-address", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - fc.nat(), - (caller, index, reward_cycle) => { - // Arrange - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-reward-set-pox-address", - [Cl.uint(index), Cl.uint(reward_cycle)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - expect(actual).toBeNone(); - } - ) - ); - }); - - it("should return correct get-stacking-minimum", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const stx_liq_supply = - pox_4_info.value.data["total-liquid-supply-ustx"]; - - assert(isClarityType(stx_liq_supply, ClarityType.UInt)); - const expected = Math.floor( - Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 - ); - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "get-stacking-minimum", - [], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); - - it("should return true check-pox-addr-version for version <= 6 ", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 6 }), - (caller, version) => { - // Arrange - const expected = true; - - // Act - let { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-addr-version", - [Cl.buffer(Uint8Array.from([version]))], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return false check-pox-addr-version for version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 7, max: 255 }), - (caller, version) => { - // Arrange - const expected = false; - - // Act - let { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-addr-version", - [Cl.buffer(Uint8Array.from([version]))], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return true check-pox-lock-period for valid reward cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 1, max: 12 }), - (caller, reward_cycles) => { - // Arrange - const expected = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return false check-pox-lock-period for reward cycles number > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 13 }), - (caller, reward_cycles) => { - // Arrange - const expected = false; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return false check-pox-lock-period for reward cycles number == 0", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - const reward_cycles = 0; - const expected = false; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); - - it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 20, - maxLength: 20, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseOk = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); - - it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 5, max: 6 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseOk = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); - - it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ - min: 7, - max: 255, - }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 21, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 19, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 31, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: 0n, - max: 124_999_999_999n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 2) can-stack-stx for lock period > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 13 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - // minimal can stack stx - it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 20, - maxLength: 20, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseOk = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); - - it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 5, max: 6 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseOk = true; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); - - it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ - min: 7, - max: 255, - }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 21, - maxLength: 32, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 19, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 31, - }), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: 125_000_000_000n, - max: 340282366920938463463374607431768211455n, - }), - fc.nat(), - fc.integer({ min: 13 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); - - it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer(), - fc.array(fc.nat({ max: 255 })), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - (caller, version, hashbytes, first_rew_cycle, num_cycles) => { - // Arrange - const amount_ustx = 0; - - const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - - const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; - - // Act - const { result: actual } = simnet.callReadOnlyFn( - POX_4, - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: bufferCV(Uint8Array.from([version])), - hashbytes: bufferCV(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); +describe("test pox-4 contract", () => { + describe("test pox-4 contract read only functions", () => { + it("should return correct reward-cycle-to-burn-height", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, reward_cycle) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + REWARD_CYCLE_TO_BURN_HEIGHT, + [Cl.uint(reward_cycle)], + account + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + + const expected = + Number(first_burn_block_height.value) + + Number(reward_cycle_length.value) * reward_cycle; + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return correct burn-height-to-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, burn_height) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + BURN_HEIGHT_TO_REWARD_CYCLE, + [Cl.uint(burn_height)], + account + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + const expected = Math.floor( + (burn_height - Number(first_burn_block_height.value)) / + Number(reward_cycle_length.value) + ); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return u0 current-pox-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + let expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CURRENT_POX_REWARD_CYCLE, + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return none get-stacker-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (stacker, caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_STACKER_INFO, + [Cl.principal(stacker)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); + + it("should return true check-caller-allowed", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_CALLER_ALLOWED, + [], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(true); + } + ) + ); + }); + + it("should return u0 get-reward-set-size", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_REWARD_SET_SIZE, + [Cl.uint(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return u0 get-total-ustx-stacked", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_TOTAL_USTX_STACKED, + [Cl.uint(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return none get-reward-set-pox-address", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + fc.nat(), + (caller, index, reward_cycle) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_REWARD_SET_POX_ADDRESS, + [Cl.uint(index), Cl.uint(reward_cycle)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); + + it("should return correct get-stacking-minimum", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const stx_liq_supply = + pox_4_info.value.data["total-liquid-supply-ustx"]; + + assert(isClarityType(stx_liq_supply, ClarityType.UInt)); + const expected = Math.floor( + Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 + ); + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_STACKING_MINIMUM, + [], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return true check-pox-addr-version for version <= 6 ", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + (caller, version) => { + // Arrange + const expected = true; + + // Act + let { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_ADDR_VERSION, + [Cl.buffer(Uint8Array.from([version]))], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-addr-version for version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 7, max: 255 }), + (caller, version) => { + // Arrange + const expected = false; + + // Act + let { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_ADDR_VERSION, + [Cl.buffer(Uint8Array.from([version]))], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return true check-pox-lock-period for valid reward cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 1, max: 12 }), + (caller, reward_cycles) => { + // Arrange + const expected = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_LOCK_PERIOD, + [Cl.uint(reward_cycles)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-lock-period for reward cycles number > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 13 }), + (caller, reward_cycles) => { + // Arrange + const expected = false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_LOCK_PERIOD, + [Cl.uint(reward_cycles)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return false check-pox-lock-period for reward cycles number == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const reward_cycles = 0; + const expected = false; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CHECK_POX_LOCK_PERIOD, + [Cl.uint(reward_cycles)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); + + it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 0n, + max: 124_999_999_999n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 2) can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + // minimal can stack stx + it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseOk = true; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + (caller, version, hashbytes, first_rew_cycle, num_cycles) => { + // Arrange + const amount_ustx = 0; + + const { result: pox_4_info } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + + const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + MINIMAL_CAN_STACK_STX, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); + + it("should return none get-check-delegation", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_CHECK_DELEGATION, + [Cl.principal(caller)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + + it("should return none get-delegation-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_DELEGATION_INFO, + [Cl.principal(caller)], + caller + ); + + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + + it("should return correct get-pox-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const expected_reward_cycle_id = 0, + expected_first_burn_block_height = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_POX_INFO, + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual.value.data["first-burnchain-block-height"]).toBeUint( + expected_first_burn_block_height + ); + expect(actual.value.data["min-amount-ustx"]).toBeUint( + MIN_AMOUNT_USTX + ); + expect(actual.value.data["prepare-cycle-length"]).toBeUint( + TESTNET_PREPARE_CYCLE_LENGTH + ); + expect(actual.value.data["reward-cycle-id"]).toBeUint( + expected_reward_cycle_id + ); + expect(actual.value.data["reward-cycle-length"]).toBeUint( + TESTNET_REWARD_CYCLE_LENGTH + ); + expect(actual.value.data["total-liquid-supply-ustx"]).toBeUint( + INITIAL_TOTAL_LIQ_SUPPLY + ); + } + ) + ); + }); + + it("should return none get-allowance-contract-caller", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, sender, contract_caller) => { + // Arrange + + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_ALLOWANCE_CONTRACT_CALLERS, + [Cl.principal(sender), Cl.principal(contract_caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + + it("should return some get-allowance-contract-caller after allow-contract-caller", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, sender, contract_caller) => { + // Arrange + const { result: allow } = simnet.callPublicFn( + POX_4, + ALLOW_CONTRACT_CALLER, + [Cl.principal(contract_caller), Cl.none()], + sender + ); + + assert(isClarityType(allow, ClarityType.ResponseOk)); + assert(isClarityType(allow.value, ClarityType.BoolTrue)); + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_ALLOWANCE_CONTRACT_CALLERS, + [Cl.principal(sender), Cl.principal(contract_caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalSome)); + assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual.value).toBeTuple({ "until-burn-ht": Cl.none() }); + } + ) + ); + }); + + // get-signer-key-message-hash + // verify-signer-key-sig + // get-num-reward-set-pox-addresses + // get-partial-stacked-by-cycle }); }); From e891474e9cbd76d61a0f3d9efe3755f1ee37bd8b Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Wed, 6 Mar 2024 20:14:27 +0200 Subject: [PATCH 17/24] added tests for get-num-reward-set-pox-addresses, get-partial-stacked-by-cycle --- .../tests/pox-4/pox-4.prop.test.ts | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 506ebd2864..d16dd76f1a 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -22,6 +22,8 @@ const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; const GET_CHECK_DELEGATION = "get-check-delegation"; const GET_DELEGATION_INFO = "get-delegation-info"; const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; +const GET_NUM_REWARD_SET_POX_ADDRESSES = "get-num-reward-set-pox-addresses"; +const GET_PARTIAL_STACKED_BY_CYCLE = "get-partial-stacked-by-cycle"; const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; // Contract Consts const TESTNET_STACKING_THRESHOLD_25 = 8000; @@ -1486,7 +1488,7 @@ describe("test pox-4 contract", () => { ); }); - it("should return some get-allowance-contract-caller after allow-contract-caller", () => { + it("should return some(until-burn-ht: none) get-allowance-contract-caller after allow-contract-caller", () => { fc.assert( fc.property( fc.constantFrom(...simnet.getAccounts().values()), @@ -1519,9 +1521,61 @@ describe("test pox-4 contract", () => { ); }); + it("should return u0 get-num-reward-set-pox-addresses", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_NUM_REWARD_SET_POX_ADDRESSES, + [Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); + + it("should return none get-partial-stacked-by-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, version, hashbytes, reward_cycle, sender) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_PARTIAL_STACKED_BY_CYCLE, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.principal(sender), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + // get-signer-key-message-hash // verify-signer-key-sig - // get-num-reward-set-pox-addresses - // get-partial-stacked-by-cycle }); }); From cd82f1c7cfcad42f5bf2506a2846a88d0e6339d8 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Thu, 7 Mar 2024 14:09:12 +0200 Subject: [PATCH 18/24] added test for get-signer-key-message-hash and utils file --- .../tests/pox-4/pox-4-utils/utils.ts | 58 +++++++ .../tests/pox-4/pox-4.prop.test.ts | 164 +++++++----------- 2 files changed, 116 insertions(+), 106 deletions(-) create mode 100644 contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts new file mode 100644 index 0000000000..81164c3338 --- /dev/null +++ b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts @@ -0,0 +1,58 @@ +import { Cl, ClarityValue, serializeCV } from "@stacks/transactions"; +import { createHash } from "crypto"; + +function sha256(data: Buffer): Buffer { + return createHash("sha256").update(data).digest(); +} + +function structuredDataHash(structuredData: ClarityValue): Buffer { + return sha256(Buffer.from(serializeCV(structuredData))); +} + +const generateDomainHash = () => + Cl.tuple({ + name: Cl.stringAscii("pox-4-signer"), + version: Cl.stringAscii("1.0.0"), + "chain-id": Cl.uint(2147483648), + }); + +const generateMessageHash = ( + version: number, + hashbytes: number[], + reward_cycle: number, + topic: string, + period: number +) => + Cl.tuple({ + "pox-addr": Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + "reward-cycle": Cl.uint(reward_cycle), + topic: Cl.stringAscii(topic), + period: Cl.uint(period), + }); + +const generateMessagePrefixBuffer = (prefix: string) => + Buffer.from(prefix, "hex"); + +export const buildSignerKeyMessageHash = ( + version: number, + hashbytes: number[], + reward_cycle: number, + topic: string, + period: number +) => { + const sip018_msg_prefix = "534950303138"; + const domain_hash = structuredDataHash(generateDomainHash()); + const message_hash = structuredDataHash( + generateMessageHash(version, hashbytes, reward_cycle, topic, period) + ); + const structuredDataPrefix = generateMessagePrefixBuffer(sip018_msg_prefix); + + const signer_key_message_hash = sha256( + Buffer.concat([structuredDataPrefix, domain_hash, message_hash]) + ); + + return signer_key_message_hash; +}; diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index d16dd76f1a..b54eaafa5c 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,36 +1,39 @@ import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; +import { buildSignerKeyMessageHash } from "./pox-4-utils/utils"; // Contracts const POX_4 = "pox-4"; // Methods -const GET_POX_INFO = "get-pox-info"; -const GET_STACKER_INFO = "get-stacker-info"; -const REWARD_CYCLE_TO_BURN_HEIGHT = "reward-cycle-to-burn-height"; +const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; const BURN_HEIGHT_TO_REWARD_CYCLE = "burn-height-to-reward-cycle"; -const CURRENT_POX_REWARD_CYCLE = "current-pox-reward-cycle"; +const CAN_STACK_STX = "can-stack-stx"; const CHECK_CALLER_ALLOWED = "check-caller-allowed"; -const GET_REWARD_SET_SIZE = "get-reward-set-size"; -const GET_REWARD_SET_POX_ADDRESS = "get-reward-set-pox-address"; -const GET_TOTAL_USTX_STACKED = "get-total-ustx-stacked"; const CHECK_POX_ADDR_VERSION = "check-pox-addr-version"; const CHECK_POX_LOCK_PERIOD = "check-pox-lock-period"; -const GET_STACKING_MINIMUM = "get-stacking-minimum"; -const CAN_STACK_STX = "can-stack-stx"; -const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; +const CURRENT_POX_REWARD_CYCLE = "current-pox-reward-cycle"; +const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; const GET_CHECK_DELEGATION = "get-check-delegation"; const GET_DELEGATION_INFO = "get-delegation-info"; -const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; const GET_NUM_REWARD_SET_POX_ADDRESSES = "get-num-reward-set-pox-addresses"; const GET_PARTIAL_STACKED_BY_CYCLE = "get-partial-stacked-by-cycle"; -const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; +const GET_POX_INFO = "get-pox-info"; +const GET_REWARD_SET_POX_ADDRESS = "get-reward-set-pox-address"; +const GET_REWARD_SET_SIZE = "get-reward-set-size"; +const GET_SIGNER_KEY_MESSAGE_HASH = "get-signer-key-message-hash"; +const GET_STACKER_INFO = "get-stacker-info"; +const GET_STACKING_MINIMUM = "get-stacking-minimum"; +const GET_TOTAL_USTX_STACKED = "get-total-ustx-stacked"; +const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; +const REWARD_CYCLE_TO_BURN_HEIGHT = "reward-cycle-to-burn-height"; +const VERIFY_SIGNER_KEY_SIG = "verify-signer-key-sig"; // Contract Consts -const TESTNET_STACKING_THRESHOLD_25 = 8000; -const TESTNET_REWARD_CYCLE_LENGTH = 1050; -const TESTNET_PREPARE_CYCLE_LENGTH = 50; const INITIAL_TOTAL_LIQ_SUPPLY = 1_000_000_000_000_000; const MIN_AMOUNT_USTX = 125_000_000_000n; +const TESTNET_PREPARE_CYCLE_LENGTH = 50; +const TESTNET_REWARD_CYCLE_LENGTH = 1050; +const TESTNET_STACKING_THRESHOLD_25 = 8000; // Clarity Constraints const MAX_CLAR_UINT = 340282366920938463463374607431768211455n; // Error Codes @@ -56,12 +59,10 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const first_burn_block_height = pox_4_info.value.data["first-burnchain-block-height"]; const reward_cycle_length = pox_4_info.value.data["reward-cycle-length"]; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -69,12 +70,10 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycle)], account ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); assert(isClarityType(first_burn_block_height, ClarityType.UInt)); assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - const expected = Number(first_burn_block_height.value) + Number(reward_cycle_length.value) * reward_cycle; @@ -99,12 +98,10 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const first_burn_block_height = pox_4_info.value.data["first-burnchain-block-height"]; const reward_cycle_length = pox_4_info.value.data["reward-cycle-length"]; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -112,7 +109,6 @@ describe("test pox-4 contract", () => { [Cl.uint(burn_height)], account ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); assert(isClarityType(first_burn_block_height, ClarityType.UInt)); @@ -156,7 +152,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (stacker, caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -164,7 +159,6 @@ describe("test pox-4 contract", () => { [Cl.principal(stacker)], caller ); - // Assert assert(isClarityType(actual, ClarityType.OptionalNone)); expect(actual).toBeNone(); @@ -179,7 +173,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -187,7 +180,6 @@ describe("test pox-4 contract", () => { [], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolTrue)); expect(actual).toBeBool(true); @@ -204,7 +196,6 @@ describe("test pox-4 contract", () => { (caller, reward_cycle) => { // Arrange const expected = 0; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -212,7 +203,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycle)], caller ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); expect(actual).toBeUint(expected); @@ -229,7 +219,6 @@ describe("test pox-4 contract", () => { (caller, reward_cycle) => { // Arrange const expected = 0; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -237,7 +226,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycle)], caller ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); expect(actual).toBeUint(expected); @@ -254,7 +242,6 @@ describe("test pox-4 contract", () => { fc.nat(), (caller, index, reward_cycle) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -262,7 +249,6 @@ describe("test pox-4 contract", () => { [Cl.uint(index), Cl.uint(reward_cycle)], caller ); - // Assert assert(isClarityType(actual, ClarityType.OptionalNone)); expect(actual).toBeNone(); @@ -277,7 +263,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, GET_POX_INFO, @@ -286,15 +271,12 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const stx_liq_supply = pox_4_info.value.data["total-liquid-supply-ustx"]; - assert(isClarityType(stx_liq_supply, ClarityType.UInt)); const expected = Math.floor( Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 ); - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -302,7 +284,6 @@ describe("test pox-4 contract", () => { [], caller ); - // Assert assert(isClarityType(actual, ClarityType.UInt)); expect(actual).toBeUint(expected); @@ -319,7 +300,6 @@ describe("test pox-4 contract", () => { (caller, version) => { // Arrange const expected = true; - // Act let { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -327,7 +307,6 @@ describe("test pox-4 contract", () => { [Cl.buffer(Uint8Array.from([version]))], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolTrue)); expect(actual).toBeBool(expected); @@ -344,7 +323,6 @@ describe("test pox-4 contract", () => { (caller, version) => { // Arrange const expected = false; - // Act let { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -352,7 +330,6 @@ describe("test pox-4 contract", () => { [Cl.buffer(Uint8Array.from([version]))], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); @@ -369,7 +346,6 @@ describe("test pox-4 contract", () => { (caller, reward_cycles) => { // Arrange const expected = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -377,7 +353,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycles)], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolTrue)); expect(actual).toBeBool(expected); @@ -394,7 +369,6 @@ describe("test pox-4 contract", () => { (caller, reward_cycles) => { // Arrange const expected = false; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -402,7 +376,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycles)], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); @@ -419,7 +392,6 @@ describe("test pox-4 contract", () => { // Arrange const reward_cycles = 0; const expected = false; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -427,7 +399,6 @@ describe("test pox-4 contract", () => { [Cl.uint(reward_cycles)], caller ); - // Assert assert(isClarityType(actual, ClarityType.BoolFalse)); expect(actual).toBeBool(expected); @@ -468,9 +439,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -486,7 +455,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseOk)); assert(isClarityType(actual.value, ClarityType.BoolTrue)); @@ -520,7 +488,6 @@ describe("test pox-4 contract", () => { num_cycles ) => { // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, GET_POX_INFO, @@ -529,9 +496,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -547,7 +512,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseOk)); assert(isClarityType(actual.value, ClarityType.BoolTrue)); @@ -592,9 +556,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -610,7 +572,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -652,9 +613,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -670,7 +629,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -711,9 +669,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -729,7 +685,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -770,9 +725,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -788,7 +741,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -827,9 +779,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -845,7 +795,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -884,9 +833,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -902,7 +849,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -912,7 +858,6 @@ describe("test pox-4 contract", () => { ); }); - // minimal can stack stx it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { fc.assert( fc.property( @@ -945,9 +890,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -963,7 +906,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseOk)); assert(isClarityType(actual.value, ClarityType.BoolTrue)); @@ -997,7 +939,6 @@ describe("test pox-4 contract", () => { num_cycles ) => { // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, GET_POX_INFO, @@ -1006,9 +947,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1024,7 +963,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseOk)); assert(isClarityType(actual.value, ClarityType.BoolTrue)); @@ -1069,9 +1007,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1087,7 +1023,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1129,9 +1064,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1147,7 +1080,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1188,9 +1120,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1206,7 +1136,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1247,9 +1176,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1265,7 +1192,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1304,9 +1230,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1322,7 +1246,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1343,7 +1266,6 @@ describe("test pox-4 contract", () => { (caller, version, hashbytes, first_rew_cycle, num_cycles) => { // Arrange const amount_ustx = 0; - const { result: pox_4_info } = simnet.callReadOnlyFn( POX_4, GET_POX_INFO, @@ -1352,9 +1274,7 @@ describe("test pox-4 contract", () => { ); assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1370,7 +1290,6 @@ describe("test pox-4 contract", () => { ], caller ); - // Assert assert(isClarityType(actual, ClarityType.ResponseErr)); assert(isClarityType(actual.value, ClarityType.Int)); @@ -1386,7 +1305,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1394,7 +1312,6 @@ describe("test pox-4 contract", () => { [Cl.principal(caller)], caller ); - // Assert assert(isClarityType(actual, ClarityType.OptionalNone)); } @@ -1408,7 +1325,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1416,7 +1332,6 @@ describe("test pox-4 contract", () => { [Cl.principal(caller)], caller ); - // Assert assert(isClarityType(actual, ClarityType.OptionalNone)); } @@ -1473,7 +1388,6 @@ describe("test pox-4 contract", () => { fc.constantFrom(...simnet.getAccounts().values()), (caller, sender, contract_caller) => { // Arrange - // Act const { result: actual } = simnet.callReadOnlyFn( POX_4, @@ -1502,7 +1416,6 @@ describe("test pox-4 contract", () => { [Cl.principal(contract_caller), Cl.none()], sender ); - assert(isClarityType(allow, ClarityType.ResponseOk)); assert(isClarityType(allow.value, ClarityType.BoolTrue)); // Act @@ -1575,7 +1488,46 @@ describe("test pox-4 contract", () => { ); }); - // get-signer-key-message-hash + it("should return correct hash get-signer-key-message-hash", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + (caller, version, hashbytes, reward_cycle, period) => { + // Arrange + const topic = "test"; + const signer_key_message_hash = buildSignerKeyMessageHash( + version, + hashbytes, + reward_cycle, + topic, + period + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + POX_4, + GET_SIGNER_KEY_MESSAGE_HASH, + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii(topic), + Cl.uint(period), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.Buffer)); + expect(actual).toBeBuff(signer_key_message_hash); + } + ) + ); + }); // verify-signer-key-sig }); }); From 1218ddc956412aa5a79e16a545ecdc6447033ab4 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Thu, 7 Mar 2024 16:49:58 +0200 Subject: [PATCH 19/24] updated get-signer-key-message-hash test to match the new function structure --- .../tests/pox-4/pox-4-utils/utils.ts | 20 +++++++++++-- .../tests/pox-4/pox-4.prop.test.ts | 30 +++++++++++++++---- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts index 81164c3338..1f53c81a92 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts @@ -21,7 +21,9 @@ const generateMessageHash = ( hashbytes: number[], reward_cycle: number, topic: string, - period: number + period: number, + auth_id: number, + max_amount: number ) => Cl.tuple({ "pox-addr": Cl.tuple({ @@ -31,6 +33,8 @@ const generateMessageHash = ( "reward-cycle": Cl.uint(reward_cycle), topic: Cl.stringAscii(topic), period: Cl.uint(period), + "auth-id": Cl.uint(auth_id), + "max-amount": Cl.uint(max_amount), }); const generateMessagePrefixBuffer = (prefix: string) => @@ -41,12 +45,22 @@ export const buildSignerKeyMessageHash = ( hashbytes: number[], reward_cycle: number, topic: string, - period: number + period: number, + max_amount: number, + auth_id: number ) => { const sip018_msg_prefix = "534950303138"; const domain_hash = structuredDataHash(generateDomainHash()); const message_hash = structuredDataHash( - generateMessageHash(version, hashbytes, reward_cycle, topic, period) + generateMessageHash( + version, + hashbytes, + reward_cycle, + topic, + period, + auth_id, + max_amount + ) ); const structuredDataPrefix = generateMessagePrefixBuffer(sip018_msg_prefix); diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index b54eaafa5c..e1c1e04833 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,6 +1,6 @@ import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; -import { assert, describe, expect, it } from "vitest"; import fc from "fast-check"; +import { assert, describe, expect, it } from "vitest"; import { buildSignerKeyMessageHash } from "./pox-4-utils/utils"; // Contracts @@ -1496,15 +1496,31 @@ describe("test pox-4 contract", () => { fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), fc.nat(), fc.nat(), - (caller, version, hashbytes, reward_cycle, period) => { + // fc.asciiString({ maxLength: 10, minLength: 1 }), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + // topic, + max_amount, + auth_id + ) => { // Arrange - const topic = "test"; + // clarinet bug string: + // r;NT=" + const signer_key_message_hash = buildSignerKeyMessageHash( version, hashbytes, reward_cycle, - topic, - period + "topic", + period, + max_amount, + auth_id ); // Act const { result: actual } = simnet.callReadOnlyFn( @@ -1516,8 +1532,10 @@ describe("test pox-4 contract", () => { hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), }), Cl.uint(reward_cycle), - Cl.stringAscii(topic), + Cl.stringAscii("topic"), Cl.uint(period), + Cl.uint(max_amount), + Cl.uint(auth_id), ], caller ); From 3652f2fb497ff750b5a334e021f05781c09a0619 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Thu, 7 Mar 2024 20:21:11 +0200 Subject: [PATCH 20/24] Move utils to test file, inlined methods and contract name --- .../tests/pox-4/pox-4-utils/utils.ts | 72 ---- .../tests/pox-4/pox-4.prop.test.ts | 342 ++++++++++-------- 2 files changed, 198 insertions(+), 216 deletions(-) delete mode 100644 contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts b/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts deleted file mode 100644 index 1f53c81a92..0000000000 --- a/contrib/core-contract-tests/tests/pox-4/pox-4-utils/utils.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Cl, ClarityValue, serializeCV } from "@stacks/transactions"; -import { createHash } from "crypto"; - -function sha256(data: Buffer): Buffer { - return createHash("sha256").update(data).digest(); -} - -function structuredDataHash(structuredData: ClarityValue): Buffer { - return sha256(Buffer.from(serializeCV(structuredData))); -} - -const generateDomainHash = () => - Cl.tuple({ - name: Cl.stringAscii("pox-4-signer"), - version: Cl.stringAscii("1.0.0"), - "chain-id": Cl.uint(2147483648), - }); - -const generateMessageHash = ( - version: number, - hashbytes: number[], - reward_cycle: number, - topic: string, - period: number, - auth_id: number, - max_amount: number -) => - Cl.tuple({ - "pox-addr": Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - "reward-cycle": Cl.uint(reward_cycle), - topic: Cl.stringAscii(topic), - period: Cl.uint(period), - "auth-id": Cl.uint(auth_id), - "max-amount": Cl.uint(max_amount), - }); - -const generateMessagePrefixBuffer = (prefix: string) => - Buffer.from(prefix, "hex"); - -export const buildSignerKeyMessageHash = ( - version: number, - hashbytes: number[], - reward_cycle: number, - topic: string, - period: number, - max_amount: number, - auth_id: number -) => { - const sip018_msg_prefix = "534950303138"; - const domain_hash = structuredDataHash(generateDomainHash()); - const message_hash = structuredDataHash( - generateMessageHash( - version, - hashbytes, - reward_cycle, - topic, - period, - auth_id, - max_amount - ) - ); - const structuredDataPrefix = generateMessagePrefixBuffer(sip018_msg_prefix); - - const signer_key_message_hash = sha256( - Buffer.concat([structuredDataPrefix, domain_hash, message_hash]) - ); - - return signer_key_message_hash; -}; diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index e1c1e04833..1a56d314c2 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1,47 +1,101 @@ -import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; +import { + Cl, + ClarityType, + ClarityValue, + isClarityType, + serializeCV, +} from "@stacks/transactions"; import fc from "fast-check"; import { assert, describe, expect, it } from "vitest"; -import { buildSignerKeyMessageHash } from "./pox-4-utils/utils"; +import { createHash } from "crypto"; -// Contracts -const POX_4 = "pox-4"; -// Methods -const ALLOW_CONTRACT_CALLER = "allow-contract-caller"; -const BURN_HEIGHT_TO_REWARD_CYCLE = "burn-height-to-reward-cycle"; -const CAN_STACK_STX = "can-stack-stx"; -const CHECK_CALLER_ALLOWED = "check-caller-allowed"; -const CHECK_POX_ADDR_VERSION = "check-pox-addr-version"; -const CHECK_POX_LOCK_PERIOD = "check-pox-lock-period"; -const CURRENT_POX_REWARD_CYCLE = "current-pox-reward-cycle"; -const GET_ALLOWANCE_CONTRACT_CALLERS = "get-allowance-contract-callers"; -const GET_CHECK_DELEGATION = "get-check-delegation"; -const GET_DELEGATION_INFO = "get-delegation-info"; -const GET_NUM_REWARD_SET_POX_ADDRESSES = "get-num-reward-set-pox-addresses"; -const GET_PARTIAL_STACKED_BY_CYCLE = "get-partial-stacked-by-cycle"; -const GET_POX_INFO = "get-pox-info"; -const GET_REWARD_SET_POX_ADDRESS = "get-reward-set-pox-address"; -const GET_REWARD_SET_SIZE = "get-reward-set-size"; -const GET_SIGNER_KEY_MESSAGE_HASH = "get-signer-key-message-hash"; -const GET_STACKER_INFO = "get-stacker-info"; -const GET_STACKING_MINIMUM = "get-stacking-minimum"; -const GET_TOTAL_USTX_STACKED = "get-total-ustx-stacked"; -const MINIMAL_CAN_STACK_STX = "minimal-can-stack-stx"; -const REWARD_CYCLE_TO_BURN_HEIGHT = "reward-cycle-to-burn-height"; -const VERIFY_SIGNER_KEY_SIG = "verify-signer-key-sig"; // Contract Consts const INITIAL_TOTAL_LIQ_SUPPLY = 1_000_000_000_000_000; const MIN_AMOUNT_USTX = 125_000_000_000n; const TESTNET_PREPARE_CYCLE_LENGTH = 50; const TESTNET_REWARD_CYCLE_LENGTH = 1050; const TESTNET_STACKING_THRESHOLD_25 = 8000; -// Clarity Constraints +// Clarity const MAX_CLAR_UINT = 340282366920938463463374607431768211455n; +const TESTNET_CHAIN_ID = 2147483648; +const SIP_018_MESSAGE_PREFIX = "534950303138"; // Error Codes const ERR_STACKING_INVALID_LOCK_PERIOD = 2; const ERR_STACKING_THRESHOLD_NOT_MET = 11; const ERR_STACKING_INVALID_POX_ADDRESS = 13; const ERR_STACKING_INVALID_AMOUNT = 18; +function sha256(data: Buffer): Buffer { + return createHash("sha256").update(data).digest(); +} + +function structuredDataHash(structuredData: ClarityValue): Buffer { + return sha256(Buffer.from(serializeCV(structuredData))); +} + +const generateDomainHash = (): ClarityValue => + Cl.tuple({ + name: Cl.stringAscii("pox-4-signer"), + version: Cl.stringAscii("1.0.0"), + "chain-id": Cl.uint(TESTNET_CHAIN_ID), + }); + +const generateMessageHash = ( + version: number, + hashbytes: number[], + reward_cycle: number, + topic: string, + period: number, + auth_id: number, + max_amount: number +): ClarityValue => + Cl.tuple({ + "pox-addr": Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + "reward-cycle": Cl.uint(reward_cycle), + topic: Cl.stringAscii(topic), + period: Cl.uint(period), + "auth-id": Cl.uint(auth_id), + "max-amount": Cl.uint(max_amount), + }); + +const generateMessagePrefixBuffer = (prefix: string) => + Buffer.from(prefix, "hex"); + +export const buildSignerKeyMessageHash = ( + version: number, + hashbytes: number[], + reward_cycle: number, + topic: string, + period: number, + max_amount: number, + auth_id: number +) => { + const domain_hash = structuredDataHash(generateDomainHash()); + const message_hash = structuredDataHash( + generateMessageHash( + version, + hashbytes, + reward_cycle, + topic, + period, + auth_id, + max_amount + ) + ); + const structuredDataPrefix = generateMessagePrefixBuffer( + SIP_018_MESSAGE_PREFIX + ); + + const signer_key_message_hash = sha256( + Buffer.concat([structuredDataPrefix, domain_hash, message_hash]) + ); + + return signer_key_message_hash; +}; + describe("test pox-4 contract", () => { describe("test pox-4 contract read only functions", () => { it("should return correct reward-cycle-to-burn-height", () => { @@ -52,8 +106,8 @@ describe("test pox-4 contract", () => { (account, reward_cycle) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], account ); @@ -65,8 +119,8 @@ describe("test pox-4 contract", () => { pox_4_info.value.data["reward-cycle-length"]; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - REWARD_CYCLE_TO_BURN_HEIGHT, + "pox-4", + "reward-cycle-to-burn-height", [Cl.uint(reward_cycle)], account ); @@ -91,8 +145,8 @@ describe("test pox-4 contract", () => { (account, burn_height) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], account ); @@ -104,8 +158,8 @@ describe("test pox-4 contract", () => { pox_4_info.value.data["reward-cycle-length"]; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - BURN_HEIGHT_TO_REWARD_CYCLE, + "pox-4", + "burn-height-to-reward-cycle", [Cl.uint(burn_height)], account ); @@ -132,8 +186,8 @@ describe("test pox-4 contract", () => { let expected = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CURRENT_POX_REWARD_CYCLE, + "pox-4", + "current-pox-reward-cycle", [], caller ); @@ -154,8 +208,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_STACKER_INFO, + "pox-4", + "get-stacker-info", [Cl.principal(stacker)], caller ); @@ -175,8 +229,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_CALLER_ALLOWED, + "pox-4", + "check-caller-allowed", [], caller ); @@ -198,8 +252,8 @@ describe("test pox-4 contract", () => { const expected = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_REWARD_SET_SIZE, + "pox-4", + "get-reward-set-size", [Cl.uint(reward_cycle)], caller ); @@ -221,8 +275,8 @@ describe("test pox-4 contract", () => { const expected = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_TOTAL_USTX_STACKED, + "pox-4", + "get-total-ustx-stacked", [Cl.uint(reward_cycle)], caller ); @@ -244,8 +298,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_REWARD_SET_POX_ADDRESS, + "pox-4", + "get-reward-set-pox-address", [Cl.uint(index), Cl.uint(reward_cycle)], caller ); @@ -264,8 +318,8 @@ describe("test pox-4 contract", () => { (caller) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -279,8 +333,8 @@ describe("test pox-4 contract", () => { ); // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_STACKING_MINIMUM, + "pox-4", + "get-stacking-minimum", [], caller ); @@ -302,8 +356,8 @@ describe("test pox-4 contract", () => { const expected = true; // Act let { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_ADDR_VERSION, + "pox-4", + "check-pox-addr-version", [Cl.buffer(Uint8Array.from([version]))], caller ); @@ -325,8 +379,8 @@ describe("test pox-4 contract", () => { const expected = false; // Act let { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_ADDR_VERSION, + "pox-4", + "check-pox-addr-version", [Cl.buffer(Uint8Array.from([version]))], caller ); @@ -348,8 +402,8 @@ describe("test pox-4 contract", () => { const expected = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_LOCK_PERIOD, + "pox-4", + "check-pox-lock-period", [Cl.uint(reward_cycles)], caller ); @@ -371,8 +425,8 @@ describe("test pox-4 contract", () => { const expected = false; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_LOCK_PERIOD, + "pox-4", + "check-pox-lock-period", [Cl.uint(reward_cycles)], caller ); @@ -394,8 +448,8 @@ describe("test pox-4 contract", () => { const expected = false; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CHECK_POX_LOCK_PERIOD, + "pox-4", + "check-pox-lock-period", [Cl.uint(reward_cycles)], caller ); @@ -432,8 +486,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -442,8 +496,8 @@ describe("test pox-4 contract", () => { const expectedResponseOk = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -489,8 +543,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -499,8 +553,8 @@ describe("test pox-4 contract", () => { const expectedResponseOk = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -549,8 +603,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -559,8 +613,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -606,8 +660,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -616,8 +670,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -662,8 +716,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -672,8 +726,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -718,8 +772,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -728,8 +782,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -772,8 +826,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -782,8 +836,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -826,8 +880,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -836,8 +890,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - CAN_STACK_STX, + "pox-4", + "can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -883,8 +937,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -893,8 +947,8 @@ describe("test pox-4 contract", () => { const expectedResponseOk = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -940,8 +994,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -950,8 +1004,8 @@ describe("test pox-4 contract", () => { const expectedResponseOk = true; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1000,8 +1054,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1010,8 +1064,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1057,8 +1111,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1067,8 +1121,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1113,8 +1167,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1123,8 +1177,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1169,8 +1223,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1179,8 +1233,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1223,8 +1277,8 @@ describe("test pox-4 contract", () => { ) => { // Arrange const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1233,8 +1287,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1267,8 +1321,8 @@ describe("test pox-4 contract", () => { // Arrange const amount_ustx = 0; const { result: pox_4_info } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1277,8 +1331,8 @@ describe("test pox-4 contract", () => { const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - MINIMAL_CAN_STACK_STX, + "pox-4", + "minimal-can-stack-stx", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1307,8 +1361,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_CHECK_DELEGATION, + "pox-4", + "get-check-delegation", [Cl.principal(caller)], caller ); @@ -1327,8 +1381,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_DELEGATION_INFO, + "pox-4", + "get-delegation-info", [Cl.principal(caller)], caller ); @@ -1349,8 +1403,8 @@ describe("test pox-4 contract", () => { expected_first_burn_block_height = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_POX_INFO, + "pox-4", + "get-pox-info", [], caller ); @@ -1390,8 +1444,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_ALLOWANCE_CONTRACT_CALLERS, + "pox-4", + "get-allowance-contract-callers", [Cl.principal(sender), Cl.principal(contract_caller)], caller ); @@ -1411,8 +1465,8 @@ describe("test pox-4 contract", () => { (caller, sender, contract_caller) => { // Arrange const { result: allow } = simnet.callPublicFn( - POX_4, - ALLOW_CONTRACT_CALLER, + "pox-4", + "allow-contract-caller", [Cl.principal(contract_caller), Cl.none()], sender ); @@ -1420,8 +1474,8 @@ describe("test pox-4 contract", () => { assert(isClarityType(allow.value, ClarityType.BoolTrue)); // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_ALLOWANCE_CONTRACT_CALLERS, + "pox-4", + "get-allowance-contract-callers", [Cl.principal(sender), Cl.principal(contract_caller)], caller ); @@ -1444,8 +1498,8 @@ describe("test pox-4 contract", () => { const expected = 0; // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_NUM_REWARD_SET_POX_ADDRESSES, + "pox-4", + "get-num-reward-set-pox-addresses", [Cl.uint(reward_cycle)], caller ); @@ -1469,8 +1523,8 @@ describe("test pox-4 contract", () => { // Arrange // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_PARTIAL_STACKED_BY_CYCLE, + "pox-4", + "get-partial-stacked-by-cycle", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), @@ -1524,8 +1578,8 @@ describe("test pox-4 contract", () => { ); // Act const { result: actual } = simnet.callReadOnlyFn( - POX_4, - GET_SIGNER_KEY_MESSAGE_HASH, + "pox-4", + "get-signer-key-message-hash", [ Cl.tuple({ version: Cl.buffer(Uint8Array.from([version])), From b77be1009055221f8c2c6312cde570b2d2fc9b96 Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Fri, 8 Mar 2024 13:10:10 +0200 Subject: [PATCH 21/24] Update according to comments --- .../tests/pox-4/pox-4.prop.test.ts | 2916 ++++++++--------- 1 file changed, 1454 insertions(+), 1462 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 1a56d314c2..b82d212477 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -96,1510 +96,1502 @@ export const buildSignerKeyMessageHash = ( return signer_key_message_hash; }; -describe("test pox-4 contract", () => { - describe("test pox-4 contract read only functions", () => { - it("should return correct reward-cycle-to-burn-height", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (account, reward_cycle) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - account - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const first_burn_block_height = - pox_4_info.value.data["first-burnchain-block-height"]; - const reward_cycle_length = - pox_4_info.value.data["reward-cycle-length"]; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "reward-cycle-to-burn-height", - [Cl.uint(reward_cycle)], - account - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - assert(isClarityType(first_burn_block_height, ClarityType.UInt)); - assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - const expected = - Number(first_burn_block_height.value) + - Number(reward_cycle_length.value) * reward_cycle; - expect(actual).toBeUint(expected); - } - ) - ); - }); +describe("test pox-4 contract read only functions", () => { + it("should return correct reward-cycle-to-burn-height", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, reward_cycle) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "reward-cycle-to-burn-height", + [Cl.uint(reward_cycle)], + account + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + const expected = + Number(first_burn_block_height.value) + + Number(reward_cycle_length.value) * reward_cycle; + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return correct burn-height-to-reward-cycle", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (account, burn_height) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - account - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const first_burn_block_height = - pox_4_info.value.data["first-burnchain-block-height"]; - const reward_cycle_length = - pox_4_info.value.data["reward-cycle-length"]; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "burn-height-to-reward-cycle", - [Cl.uint(burn_height)], - account - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - assert(isClarityType(first_burn_block_height, ClarityType.UInt)); - assert(isClarityType(reward_cycle_length, ClarityType.UInt)); - const expected = Math.floor( - (burn_height - Number(first_burn_block_height.value)) / - Number(reward_cycle_length.value) - ); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return correct burn-height-to-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account, burn_height) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + account + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const first_burn_block_height = + pox_4_info.value.data["first-burnchain-block-height"]; + const reward_cycle_length = + pox_4_info.value.data["reward-cycle-length"]; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "burn-height-to-reward-cycle", + [Cl.uint(burn_height)], + account + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + assert(isClarityType(first_burn_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + const expected = Math.floor( + (burn_height - Number(first_burn_block_height.value)) / + Number(reward_cycle_length.value) + ); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return u0 current-pox-reward-cycle", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - let expected = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "current-pox-reward-cycle", - [], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return u0 current-pox-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + let expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "current-pox-reward-cycle", + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return none get-stacker-info", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - (stacker, caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-stacker-info", - [Cl.principal(stacker)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - expect(actual).toBeNone(); - } - ) - ); - }); + it("should return none get-stacker-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (stacker, caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-stacker-info", + [Cl.principal(stacker)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); - it("should return true check-caller-allowed", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-caller-allowed", - [], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(true); - } - ) - ); - }); + it("should return true check-caller-allowed", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-caller-allowed", + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(true); + } + ) + ); + }); - it("should return u0 get-reward-set-size", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-reward-set-size", - [Cl.uint(reward_cycle)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return u0 get-reward-set-size", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-reward-set-size", + [Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return u0 get-total-ustx-stacked", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-total-ustx-stacked", - [Cl.uint(reward_cycle)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return u0 get-total-ustx-stacked", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-total-ustx-stacked", + [Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return none get-reward-set-pox-address", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - fc.nat(), - (caller, index, reward_cycle) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-reward-set-pox-address", - [Cl.uint(index), Cl.uint(reward_cycle)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - expect(actual).toBeNone(); - } - ) - ); - }); + it("should return none get-reward-set-pox-address", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + fc.nat(), + (caller, index, reward_cycle) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-reward-set-pox-address", + [Cl.uint(index), Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + expect(actual).toBeNone(); + } + ) + ); + }); - it("should return correct get-stacking-minimum", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const stx_liq_supply = - pox_4_info.value.data["total-liquid-supply-ustx"]; - assert(isClarityType(stx_liq_supply, ClarityType.UInt)); - const expected = Math.floor( - Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 - ); - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-stacking-minimum", - [], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return correct get-stacking-minimum", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const stx_liq_supply = + pox_4_info.value.data["total-liquid-supply-ustx"]; + assert(isClarityType(stx_liq_supply, ClarityType.UInt)); + const expected = Math.floor( + Number(stx_liq_supply.value) / TESTNET_STACKING_THRESHOLD_25 + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-stacking-minimum", + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return true check-pox-addr-version for version <= 6 ", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 6 }), - (caller, version) => { - // Arrange - const expected = true; - // Act - let { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-addr-version", - [Cl.buffer(Uint8Array.from([version]))], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return true check-pox-addr-version for version <= 6 ", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + (caller, version) => { + // Arrange + const expected = true; + // Act + let { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-addr-version", + [Cl.buffer(Uint8Array.from([version]))], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return false check-pox-addr-version for version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 7, max: 255 }), - (caller, version) => { - // Arrange - const expected = false; - // Act - let { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-addr-version", - [Cl.buffer(Uint8Array.from([version]))], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return false check-pox-addr-version for version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 7, max: 255 }), + (caller, version) => { + // Arrange + const expected = false; + // Act + let { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-addr-version", + [Cl.buffer(Uint8Array.from([version]))], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return true check-pox-lock-period for valid reward cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 1, max: 12 }), - (caller, reward_cycles) => { - // Arrange - const expected = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolTrue)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return true check-pox-lock-period for valid reward cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 1, max: 12 }), + (caller, valid_reward_cycles) => { + // Arrange + const expected = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-lock-period", + [Cl.uint(valid_reward_cycles)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolTrue)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return false check-pox-lock-period for reward cycles number > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 13 }), - (caller, reward_cycles) => { - // Arrange - const expected = false; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return false check-pox-lock-period for reward cycles number > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 13 }), + (caller, invalid_reward_cycles) => { + // Arrange + const expected = false; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-lock-period", + [Cl.uint(invalid_reward_cycles)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return false check-pox-lock-period for reward cycles number == 0", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - const reward_cycles = 0; - const expected = false; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "check-pox-lock-period", - [Cl.uint(reward_cycles)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.BoolFalse)); - expect(actual).toBeBool(expected); - } - ) - ); - }); + it("should return false check-pox-lock-period for reward cycles number == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const invalid_reward_cycles = 0; + const expected = false; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "check-pox-lock-period", + [Cl.uint(invalid_reward_cycles)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.BoolFalse)); + expect(actual).toBeBool(expected); + } + ) + ); + }); - it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 20, - maxLength: 20, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); + it("should return (ok true) can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseOk = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); - it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 5, max: 6 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); + it("should return (ok true) can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseOk = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); - it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ - min: 7, - max: 255, - }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 21, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 19, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 31, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: 0n, - max: 124_999_999_999n, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 11) can-stack-stx for unmet stacking threshold", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: 0n, + max: 124_999_999_999n, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_THRESHOLD_NOT_MET; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 2) can-stack-stx for lock period > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 13 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 2) can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 20, - maxLength: 20, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); + it("should return (ok true) minimal-can-stack-stx for versions 0-4 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 20, + maxLength: 20, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseOk = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); - it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 5, max: 6 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseOk = true; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.BoolTrue)); - expect(actual).toBeOk(Cl.bool(expectedResponseOk)); - } - ) - ); - }); + it("should return (ok true) minimal-can-stack-stx for versions 5/6 valid pox addresses, hashbytes, amount, cycles number", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 5, max: 6 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 32, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseOk = true; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(expectedResponseOk)); + } + ) + ); + }); - it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ - min: 7, - max: 255, - }), - fc.array(fc.nat({ max: 255 }), { - minLength: 32, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) minimal-can-stack-stx for pox addresses having version > 6", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ + min: 7, + max: 255, + }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - minLength: 21, - maxLength: 32, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes longer than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + minLength: 21, + maxLength: 32, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 19, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) minimal-can-stack-stx for versions 0-4 pox addresses having hasbytes shorter than 20", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 19, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 4 }), - fc.array(fc.nat({ max: 255 }), { - maxLength: 31, - }), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 13) minimal-can-stack-stx for versions 5/6 pox addresses having hashbytes shorter than 32", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 4 }), + fc.array(fc.nat({ max: 255 }), { + maxLength: 31, + }), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_POX_ADDRESS; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 })), - fc.bigInt({ - min: MIN_AMOUNT_USTX, - max: MAX_CLAR_UINT, - }), - fc.nat(), - fc.integer({ min: 13 }), - ( - caller, - version, - hashbytes, - amount_ustx, - first_rew_cycle, - num_cycles - ) => { - // Arrange - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 2) minimal-can-stack-stx for lock period > 12", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 })), + fc.bigInt({ + min: MIN_AMOUNT_USTX, + max: MAX_CLAR_UINT, + }), + fc.nat(), + fc.integer({ min: 13 }), + ( + caller, + version, + hashbytes, + amount_ustx, + first_rew_cycle, + num_cycles + ) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_LOCK_PERIOD; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.integer({ min: 0, max: 6 }), - fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), - fc.nat(), - fc.integer({ min: 1, max: 12 }), - (caller, version, hashbytes, first_rew_cycle, num_cycles) => { - // Arrange - const amount_ustx = 0; - const { result: pox_4_info } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); - assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); - const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "minimal-can-stack-stx", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(amount_ustx), - Cl.uint(first_rew_cycle), - Cl.uint(num_cycles), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseErr)); - assert(isClarityType(actual.value, ClarityType.Int)); - expect(actual).toBeErr(Cl.int(expectedResponseErr)); - } - ) - ); - }); + it("should return (err 18) minimal-can-stack-stx for amount == 0", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.integer({ min: 0, max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.integer({ min: 1, max: 12 }), + (caller, version, hashbytes, first_rew_cycle, num_cycles) => { + // Arrange + const amount_ustx = 0; + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); + const expectedResponseErr = ERR_STACKING_INVALID_AMOUNT; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "minimal-can-stack-stx", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(amount_ustx), + Cl.uint(first_rew_cycle), + Cl.uint(num_cycles), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + } + ) + ); + }); - it("should return none get-check-delegation", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-check-delegation", - [Cl.principal(caller)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - } - ) - ); - }); + it("should return none get-check-delegation", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-check-delegation", + [Cl.principal(caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); - it("should return none get-delegation-info", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-delegation-info", - [Cl.principal(caller)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - } - ) - ); - }); + it("should return none get-delegation-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-delegation-info", + [Cl.principal(caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); + + it("should return correct get-pox-info", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + (caller) => { + // Arrange + const expected_reward_cycle_id = 0, + expected_first_burn_block_height = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual.value.data["first-burnchain-block-height"]).toBeUint( + expected_first_burn_block_height + ); + expect(actual.value.data["min-amount-ustx"]).toBeUint( + MIN_AMOUNT_USTX + ); + expect(actual.value.data["prepare-cycle-length"]).toBeUint( + TESTNET_PREPARE_CYCLE_LENGTH + ); + expect(actual.value.data["reward-cycle-id"]).toBeUint( + expected_reward_cycle_id + ); + expect(actual.value.data["reward-cycle-length"]).toBeUint( + TESTNET_REWARD_CYCLE_LENGTH + ); + expect(actual.value.data["total-liquid-supply-ustx"]).toBeUint( + INITIAL_TOTAL_LIQ_SUPPLY + ); + } + ) + ); + }); - it("should return correct get-pox-info", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - (caller) => { - // Arrange - const expected_reward_cycle_id = 0, - expected_first_burn_block_height = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-pox-info", - [], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.ResponseOk)); - assert(isClarityType(actual.value, ClarityType.Tuple)); - expect(actual.value.data["first-burnchain-block-height"]).toBeUint( - expected_first_burn_block_height - ); - expect(actual.value.data["min-amount-ustx"]).toBeUint( - MIN_AMOUNT_USTX - ); - expect(actual.value.data["prepare-cycle-length"]).toBeUint( - TESTNET_PREPARE_CYCLE_LENGTH - ); - expect(actual.value.data["reward-cycle-id"]).toBeUint( - expected_reward_cycle_id - ); - expect(actual.value.data["reward-cycle-length"]).toBeUint( - TESTNET_REWARD_CYCLE_LENGTH - ); - expect(actual.value.data["total-liquid-supply-ustx"]).toBeUint( - INITIAL_TOTAL_LIQ_SUPPLY - ); - } - ) - ); - }); + it("should return none get-allowance-contract-caller", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, sender, contract_caller) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-allowance-contract-callers", + [Cl.principal(sender), Cl.principal(contract_caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); - it("should return none get-allowance-contract-caller", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - (caller, sender, contract_caller) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-allowance-contract-callers", - [Cl.principal(sender), Cl.principal(contract_caller)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - } - ) - ); - }); + it("should return some(until-burn-ht: none) get-allowance-contract-caller after allow-contract-caller", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, sender, contract_caller) => { + // Arrange + const { result: allow } = simnet.callPublicFn( + "pox-4", + "allow-contract-caller", + [Cl.principal(contract_caller), Cl.none()], + sender + ); + assert(isClarityType(allow, ClarityType.ResponseOk)); + assert(isClarityType(allow.value, ClarityType.BoolTrue)); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-allowance-contract-callers", + [Cl.principal(sender), Cl.principal(contract_caller)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalSome)); + assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual.value).toBeTuple({ "until-burn-ht": Cl.none() }); + } + ) + ); + }); - it("should return some(until-burn-ht: none) get-allowance-contract-caller after allow-contract-caller", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - fc.constantFrom(...simnet.getAccounts().values()), - (caller, sender, contract_caller) => { - // Arrange - const { result: allow } = simnet.callPublicFn( - "pox-4", - "allow-contract-caller", - [Cl.principal(contract_caller), Cl.none()], - sender - ); - assert(isClarityType(allow, ClarityType.ResponseOk)); - assert(isClarityType(allow.value, ClarityType.BoolTrue)); - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-allowance-contract-callers", - [Cl.principal(sender), Cl.principal(contract_caller)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalSome)); - assert(isClarityType(actual.value, ClarityType.Tuple)); - expect(actual.value).toBeTuple({ "until-burn-ht": Cl.none() }); - } - ) - ); - }); + it("should return u0 get-num-reward-set-pox-addresses", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (caller, reward_cycle) => { + // Arrange + const expected = 0; + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-num-reward-set-pox-addresses", + [Cl.uint(reward_cycle)], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.UInt)); + expect(actual).toBeUint(expected); + } + ) + ); + }); - it("should return u0 get-num-reward-set-pox-addresses", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat(), - (caller, reward_cycle) => { - // Arrange - const expected = 0; - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-num-reward-set-pox-addresses", - [Cl.uint(reward_cycle)], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.UInt)); - expect(actual).toBeUint(expected); - } - ) - ); - }); + it("should return none get-partial-stacked-by-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.constantFrom(...simnet.getAccounts().values()), + (caller, version, hashbytes, reward_cycle, sender) => { + // Arrange + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-partial-stacked-by-cycle", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.principal(sender), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.OptionalNone)); + } + ) + ); + }); - it("should return none get-partial-stacked-by-cycle", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 6 }), - fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), - fc.nat(), - fc.constantFrom(...simnet.getAccounts().values()), - (caller, version, hashbytes, reward_cycle, sender) => { - // Arrange - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-partial-stacked-by-cycle", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(reward_cycle), - Cl.principal(sender), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.OptionalNone)); - } - ) - ); - }); + it("should return correct hash get-signer-key-message-hash", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + max_amount, + auth_id + ) => { + // Arrange - it("should return correct hash get-signer-key-message-hash", () => { - fc.assert( - fc.property( - fc.constantFrom(...simnet.getAccounts().values()), - fc.nat({ max: 6 }), - fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), - fc.nat(), - fc.nat(), - // fc.asciiString({ maxLength: 10, minLength: 1 }), - fc.nat(), - fc.nat(), - ( - caller, + const signer_key_message_hash = buildSignerKeyMessageHash( version, hashbytes, reward_cycle, + "topic", period, - // topic, max_amount, auth_id - ) => { - // Arrange - // clarinet bug string: - // r;NT=" - - const signer_key_message_hash = buildSignerKeyMessageHash( - version, - hashbytes, - reward_cycle, - "topic", - period, - max_amount, - auth_id - ); - // Act - const { result: actual } = simnet.callReadOnlyFn( - "pox-4", - "get-signer-key-message-hash", - [ - Cl.tuple({ - version: Cl.buffer(Uint8Array.from([version])), - hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), - }), - Cl.uint(reward_cycle), - Cl.stringAscii("topic"), - Cl.uint(period), - Cl.uint(max_amount), - Cl.uint(auth_id), - ], - caller - ); - // Assert - assert(isClarityType(actual, ClarityType.Buffer)); - expect(actual).toBeBuff(signer_key_message_hash); - } - ) - ); - }); - // verify-signer-key-sig + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "get-signer-key-message-hash", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii("topic"), + Cl.uint(period), + Cl.uint(max_amount), + Cl.uint(auth_id), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.Buffer)); + expect(actual).toBeBuff(signer_key_message_hash); + } + ) + ); }); + // verify-signer-key-sig }); From 27d68f48ec960d7df78f14f0b22e3a854c0bcb5a Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Fri, 8 Mar 2024 18:53:36 +0200 Subject: [PATCH 22/24] added tests for verify-signer-key-sig --- .../tests/pox-4/pox-4.prop.test.ts | 257 +++++++++++++++++- 1 file changed, 249 insertions(+), 8 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index b82d212477..485d42eebd 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -2,8 +2,11 @@ import { Cl, ClarityType, ClarityValue, + createStacksPrivateKey, isClarityType, + pubKeyfromPrivKey, serializeCV, + signWithKey, } from "@stacks/transactions"; import fc from "fast-check"; import { assert, describe, expect, it } from "vitest"; @@ -24,14 +27,39 @@ const ERR_STACKING_INVALID_LOCK_PERIOD = 2; const ERR_STACKING_THRESHOLD_NOT_MET = 11; const ERR_STACKING_INVALID_POX_ADDRESS = 13; const ERR_STACKING_INVALID_AMOUNT = 18; +const ERR_INVALID_SIGNATURE_PUBKEY = 35; +const ERR_SIGNER_AUTH_AMOUNT_TOO_HIGH = 38; +// Private Keys +const privateKeyMapping: { + [key: string]: string; +} = { + ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM: + "753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601", + ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5: + "7287ba251d44a4d3fd9276c88ce34c5c52a038955511cccaf77e61068649c17801", + ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG: + "530d9f61984c888536871c6573073bdfc0058896dc1adfe9a6a10dfacadc209101", + ST2JHG361ZXG51QTKY2NQCVBPPRRE2KZB1HR05NNC: + "d655b2523bcd65e34889725c73064feb17ceb796831c0e111ba1a552b0f31b3901", + ST2NEB84ASENDXKYGJPQW86YXQCEFEX2ZQPG87ND: + "f9d7206a47f14d2870c163ebab4bf3e70d18f5d14ce1031f3902fbbc894fe4c701", + ST2REHHS5J3CERCRBEPMGH7921Q6PYKAADT7JP2VB: + "3eccc5dac8056590432db6a35d52b9896876a3d5cbdea53b72400bc9c2099fe801", + ST3AM1A56AK2C1XAFJ4115ZSV26EB49BVQ10MGCS0: + "7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01", + ST3PF13W7Z0RRM42A8VZRVFQ75SV1K26RXEP8YGKJ: + "b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401", + ST3NBRSFKX28FQ2ZJ1MAKX58HKHSDGNV5N7R21XCP: + "6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01", + STNHKEPYEPJ8ET55ZZ0M5A34J0R3N5FM2CMMMAZ6: + "de433bdfa14ec43aa1098d5be594c8ffb20a31485ff9de2923b2689471c401b801", +}; -function sha256(data: Buffer): Buffer { - return createHash("sha256").update(data).digest(); -} +const sha256 = (data: Buffer): Buffer => + createHash("sha256").update(data).digest(); -function structuredDataHash(structuredData: ClarityValue): Buffer { - return sha256(Buffer.from(serializeCV(structuredData))); -} +const structuredDataHash = (structuredData: ClarityValue): Buffer => + sha256(Buffer.from(serializeCV(structuredData))); const generateDomainHash = (): ClarityValue => Cl.tuple({ @@ -64,7 +92,7 @@ const generateMessageHash = ( const generateMessagePrefixBuffer = (prefix: string) => Buffer.from(prefix, "hex"); -export const buildSignerKeyMessageHash = ( +const buildSignerKeyMessageHash = ( version: number, hashbytes: number[], reward_cycle: number, @@ -96,6 +124,14 @@ export const buildSignerKeyMessageHash = ( return signer_key_message_hash; }; +const signMessageHash = (privateKey: string, messageHash: Buffer) => { + const data = signWithKey( + createStacksPrivateKey(privateKey), + messageHash.toString("hex") + ).data; + return Buffer.from(data.slice(2) + data.slice(0, 2), "hex"); +}; + describe("test pox-4 contract read only functions", () => { it("should return correct reward-cycle-to-burn-height", () => { fc.assert( @@ -1593,5 +1629,210 @@ describe("test pox-4 contract read only functions", () => { ) ); }); - // verify-signer-key-sig + + it("should return (ok true) verify-signer-key-sig called with correct data", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + amount, + max_amount, + auth_id + ) => { + // Arrange + fc.pre(amount <= max_amount); + const signer_private_key = privateKeyMapping[caller] ?? ""; + const signer_key_message_hash = buildSignerKeyMessageHash( + version, + hashbytes, + reward_cycle, + "topic", + period, + max_amount, + auth_id + ); + const signer_sig = signMessageHash( + signer_private_key, + signer_key_message_hash + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "verify-signer-key-sig", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii("topic"), + Cl.uint(period), + Cl.some(Cl.buffer(signer_sig)), + Cl.buffer(pubKeyfromPrivKey(signer_private_key).data), + Cl.uint(amount), + Cl.uint(max_amount), + Cl.uint(auth_id), + ], + caller + ); + assert(isClarityType(actual, ClarityType.ResponseOk)); + assert(isClarityType(actual.value, ClarityType.BoolTrue)); + expect(actual).toBeOk(Cl.bool(true)); + expect(actual.value).toBeBool(true); + } + ) + ); + }); + + it("should return (err 35) verify-signer-key-sig called with wrong public key", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + fc.constantFrom(...simnet.getAccounts().values()), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + amount, + max_amount, + auth_id, + wrong_address + ) => { + // Arrange + fc.pre(amount <= max_amount); + fc.pre(wrong_address !== caller); + const expectedResponseErr = ERR_INVALID_SIGNATURE_PUBKEY; + const signer_private_key = privateKeyMapping[caller]; + const wrong_private_key = privateKeyMapping[wrong_address]; + const signer_key_message_hash = buildSignerKeyMessageHash( + version, + hashbytes, + reward_cycle, + "topic", + period, + max_amount, + auth_id + ); + const signer_sig = signMessageHash( + signer_private_key, + signer_key_message_hash + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "verify-signer-key-sig", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii("topic"), + Cl.uint(period), + Cl.some(Cl.buffer(signer_sig)), + Cl.buffer(pubKeyfromPrivKey(wrong_private_key).data), + Cl.uint(amount), + Cl.uint(max_amount), + Cl.uint(auth_id), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + expect(actual.value).toBeInt(expectedResponseErr); + } + ) + ); + }); + + it("should return (err 38) verify-signer-key-sig called with wrong public key", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat({ max: 6 }), + fc.array(fc.nat({ max: 255 }), { maxLength: 32 }), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + fc.nat(), + ( + caller, + version, + hashbytes, + reward_cycle, + period, + amount, + max_amount, + auth_id + ) => { + // Arrange + fc.pre(amount > max_amount); + const expectedResponseErr = ERR_SIGNER_AUTH_AMOUNT_TOO_HIGH; + const signer_private_key = privateKeyMapping[caller]; + const signer_key_message_hash = buildSignerKeyMessageHash( + version, + hashbytes, + reward_cycle, + "topic", + period, + max_amount, + auth_id + ); + const signer_sig = signMessageHash( + signer_private_key, + signer_key_message_hash + ); + // Act + const { result: actual } = simnet.callReadOnlyFn( + "pox-4", + "verify-signer-key-sig", + [ + Cl.tuple({ + version: Cl.buffer(Uint8Array.from([version])), + hashbytes: Cl.buffer(Uint8Array.from(hashbytes)), + }), + Cl.uint(reward_cycle), + Cl.stringAscii("topic"), + Cl.uint(period), + Cl.some(Cl.buffer(signer_sig)), + Cl.buffer(pubKeyfromPrivKey(signer_private_key).data), + Cl.uint(amount), + Cl.uint(max_amount), + Cl.uint(auth_id), + ], + caller + ); + // Assert + assert(isClarityType(actual, ClarityType.ResponseErr)); + assert(isClarityType(actual.value, ClarityType.Int)); + expect(actual).toBeErr(Cl.int(expectedResponseErr)); + expect(actual.value).toBeInt(expectedResponseErr); + } + ) + ); + }); }); From ec2364b46c27900213bc2b644cc0d1a9ae03901b Mon Sep 17 00:00:00 2001 From: BowTiedRadone Date: Mon, 11 Mar 2024 00:11:05 +0200 Subject: [PATCH 23/24] Add assertion to CI failing test --- contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 485d42eebd..4eb0c1e27b 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1515,6 +1515,7 @@ describe("test pox-4 contract read only functions", () => { // Assert assert(isClarityType(actual, ClarityType.OptionalSome)); assert(isClarityType(actual.value, ClarityType.Tuple)); + expect(actual).toBeSome(Cl.tuple({ "until-burn-ht": Cl.none() })); expect(actual.value).toBeTuple({ "until-burn-ht": Cl.none() }); } ) From 912acb886851c3d9f5dd4aac729189023cb0e659 Mon Sep 17 00:00:00 2001 From: BowTiedRadone <92028479+BowTiedRadone@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:00:25 +0200 Subject: [PATCH 24/24] Remove assertion that causes Typescript error Co-authored-by: Nikos Baxevanis --- contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts index 4eb0c1e27b..454480c41f 100644 --- a/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/pox-4.prop.test.ts @@ -1516,7 +1516,6 @@ describe("test pox-4 contract read only functions", () => { assert(isClarityType(actual, ClarityType.OptionalSome)); assert(isClarityType(actual.value, ClarityType.Tuple)); expect(actual).toBeSome(Cl.tuple({ "until-burn-ht": Cl.none() })); - expect(actual.value).toBeTuple({ "until-burn-ht": Cl.none() }); } ) );