Skip to content

Commit

Permalink
test(pox-4): Add RevokeDelegateStxCommand
Browse files Browse the repository at this point in the history
  • Loading branch information
BowTiedRadone authored and moodmosaic committed Mar 23, 2024
1 parent d6047eb commit 1166268
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 0 deletions.
Expand Up @@ -67,6 +67,7 @@ describe("PoX-4 invariant tests", () => {
hasPoolMembers: [],
delegatedTo: "",
delegatedMaxAmount: 0,
delegatedUntilBurnHt: 0,
amountLocked: 0,
amountUnlocked: initialUstxBalance,
unlockHeight: 0,
Expand Down
Expand Up @@ -28,6 +28,7 @@ export type Wallet = {
hasPoolMembers: StxAddress[];
delegatedTo: StxAddress;
delegatedMaxAmount: number;
delegatedUntilBurnHt: number;
amountLocked: number;
amountUnlocked: number;
unlockHeight: number;
Expand Down
19 changes: 19 additions & 0 deletions contrib/core-contract-tests/tests/pox-4/pox_Commands.ts
Expand Up @@ -7,6 +7,7 @@ import { DelegateStxCommand } from "./pox_DelegateStxCommand";
import { DelegateStackStxCommand } from "./pox_DelegateStackStxCommand";
import { Simnet } from "@hirosystems/clarinet-sdk";
import { Cl, cvToValue } from "@stacks/transactions";
import { RevokeDelegateStxCommand } from "./pox_RevokeDelegateStxCommand";

export function PoxCommands(
wallets: Map<StxAddress, Wallet>, network: Simnet,
Expand Down Expand Up @@ -66,6 +67,24 @@ export function PoxCommands(
r.amount,
)
),
// RevokeDelegateStxCommand
fc.record({
wallet: fc.constantFrom(...wallets.values()),
delegateTo: fc.constantFrom(...wallets.values()),
untilBurnHt: fc.integer({ min: 1 }),
amount: fc.bigInt({ min:0n, max: 100_000_000_000_000n }),
}).map((
r: {
wallet: Wallet;
delegateTo: Wallet;
untilBurnHt: number;
amount: bigint;
},
) =>
new RevokeDelegateStxCommand(
r.wallet
)
),
// DelegateStackStxCommand
fc.record({
operator: fc.constantFrom(...wallets.values()),
Expand Down
Expand Up @@ -83,6 +83,7 @@ export class DelegateStxCommand implements PoxCommand {
wallet.hasDelegated = true;
wallet.delegatedTo = this.delegateTo.stxAddress;
wallet.delegatedMaxAmount = amountUstx;
wallet.delegatedUntilBurnHt = this.untilBurnHt

delegatedWallet.hasPoolMembers.push(wallet.stxAddress);
// Log to console for debugging purposes. This is not necessary for the
Expand Down
@@ -0,0 +1,96 @@
import { PoxCommand, Real, Stub, Wallet } from "./pox_CommandModel.ts";
import { poxAddressToTuple } from "@stacks/stacking";
import { expect } from "vitest";
import { Cl, someCV, tupleCV } from "@stacks/transactions";

/**
* The `RevokeDelegateStxCommand` revokes the delegation for stacking within PoX-4.
*
* Constraints for running this command include:
* - The `Stacker` has to currently be delegating.
*/
export class RevokeDelegateStxCommand implements PoxCommand {
readonly wallet: Wallet;

/**
* Constructs a RevokeDelegateStxCommand to revoke delegate uSTX for stacking.
*
* @param wallet - Represents the Stacker's wallet.
*/
constructor(wallet: Wallet) {
this.wallet = wallet;
}

check(model: Readonly<Stub>): boolean {
// Constraints for running this command include:
// - The Stacker has to currently be delegating.
return (
model.stackingMinimum > 0 &&
model.wallets.get(this.wallet.stxAddress)!.hasDelegated === true
);
}

run(model: Stub, real: Real): void {
// Get the Operator's wallet
const operatorWallet = model.wallets.get(this.wallet.delegatedTo)!;

// Act
const revokeDelegateStx = real.network.callPublicFn(
"ST000000000000000000002AMW42H.pox-4",
"revoke-delegate-stx",
[],
this.wallet.stxAddress,
);

// Assert
expect(revokeDelegateStx.result).toBeOk(
someCV(
tupleCV({
"amount-ustx": Cl.uint(this.wallet.delegatedMaxAmount),
"delegated-to": Cl.principal(
operatorWallet.stxAddress || "",
),
"pox-addr": Cl.some(
poxAddressToTuple(operatorWallet.btcAddress || ""),
),
"until-burn-ht": Cl.some(Cl.uint(this.wallet.delegatedUntilBurnHt)),
}),
),
);

// Get the Stacker's wallet from the model and update the two wallets involved with the new state.
const wallet = model.wallets.get(this.wallet.stxAddress)!;
// Update model so that we know this wallet is not delegating anymore.
// This is important in order to prevent the test from revoking the delegation
// multiple times with the same address.
wallet.hasDelegated = false;
wallet.delegatedTo = "";
wallet.delegatedUntilBurnHt = 0;
wallet.delegatedMaxAmount = 0;

// Remove the Stacker from the Pool Operator's pool members list
let walletIndexInDelegatorsList = operatorWallet.hasPoolMembers.indexOf(
wallet.stxAddress,
);
expect(walletIndexInDelegatorsList).toBeGreaterThan(-1);
operatorWallet.hasPoolMembers.splice(walletIndexInDelegatorsList, 1);

// Log to console for debugging purposes. This is not necessary for the
// test to pass but it is useful for debugging and eyeballing the test.
console.info(
`✓ ${
this.wallet.label.padStart(
8,
" ",
)
} ${"revoke-delegate-stx".padStart(34, " ")}`,
);
}

toString() {
// fast-check will call toString() in case of errors, e.g. property failed.
// It will then make a minimal counterexample, a process called 'shrinking'
// https://github.com/dubzzz/fast-check/issues/2864#issuecomment-1098002642
return `${this.wallet.stxAddress} revoke-delegate-stx`;
}
}

0 comments on commit 1166268

Please sign in to comment.