Skip to content

Commit de7e4fe

Browse files
committed
test(bonds): anchor auctionDiscountBps assertions to the specific guard
Both arkanaai (O1) and CodeRabbit's review of #38 flagged the same test-quality issue on tests/repayment_pool_test.rs:276-281 (and the parallel rollIn assertion at 694-698): the original assert!(gte >= 1, ...) on OP_GREATERTHANOREQUAL64 was too loose. issue() emits five other asset-amount `>=` checks (output.assets.lookup(...) >= N), so deleting the `auctionDiscountBps >= 0` guard would drop GTE64 from 6 to 5 — still >= 1, still passing. Replaced both sites with a targeted 3-token window check: contains_window_3(output, fn_name, "<auctionDiscountBps>", "OP_GREATERTHANOREQUAL", "0") plus the symmetric `< 10000` check contains_window_3(output, fn_name, "<auctionDiscountBps>", "OP_LESSTHAN", "10000") The helper accepts any permutation of the three tokens within a 3-token sliding window (the emitter's display order for the discount comparison is `<auctionDiscountBps> OP_GREATERTHANOREQUAL 0`, which is not strict postfix; the set-equality test is robust to that emitter quirk and to future reordering). Verified by regression injection: deleting `require(auctionDiscountBps >= 0, ...)` from issue() makes test_issue_enforces_deployment_invariants fail with the message "issue must carry the `auctionDiscountBps >= 0` deployment guard (expected window of <auctionDiscountBps>, OP_GREATERTHANOREQUAL, 0 within 3 consecutive ASM tokens of `issue`)" restoring the guard makes the test pass. Same behaviour for rollIn. Tests: 256/256 (unchanged total — the asserts changed shape but not count). cargo fmt --check clean.
1 parent e6f4aea commit de7e4fe

1 file changed

Lines changed: 84 additions & 15 deletions

File tree

tests/repayment_pool_test.rs

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -267,20 +267,67 @@ fn test_issue_enforces_deployment_invariants() {
267267
`> 0` value guards, found {gt})"
268268
);
269269

270-
// OP_GREATERTHANOREQUAL64 for auctionDiscountBps >= 0 — exactly one
271-
// site in the deployment-safety block. (asset-amount `>=` checks like
272-
// `output.assets.lookup(...) >= N` use the same opcode, but those fire
273-
// AFTER the deployment checks and aren't counted as deployment guards.
274-
// Floor at 1 captures the deployment check without coupling to the
275-
// exact count of asset-amount checks.)
276-
let gte = opcode_count(&output, "issue", "OP_GREATERTHANOREQUAL64");
277-
assert!(
278-
gte >= 1,
279-
"issue must carry auctionDiscountBps >= 0 (OP_GREATERTHANOREQUAL64, \
280-
found {gte} total — at least one must be the discount-bound check)"
270+
// Targeted check for `auctionDiscountBps >= 0` — must anchor to the
271+
// specific guard's tokens, not just count any `>=` opcode. arkanaai O1
272+
// and CodeRabbit's review both flagged that a bare `gte >= 1` floor on
273+
// OP_GREATERTHANOREQUAL64 would still pass if the discount guard were
274+
// deleted, because issue() emits many asset-amount `>=` checks
275+
// (`output.assets.lookup(...) >= N`) that satisfy that floor.
276+
//
277+
// The compiler emits the comparison block with `<auctionDiscountBps>`,
278+
// `OP_GREATERTHANOREQUAL`, and `0` clustered within a 3-token window
279+
// (display order is `<auctionDiscountBps> OP_GREATERTHANOREQUAL 0` in
280+
// the current emitter — execution order may differ; we accept any
281+
// permutation to stay robust to that).
282+
assert!(
283+
contains_window_3(
284+
&output,
285+
"issue",
286+
"<auctionDiscountBps>",
287+
"OP_GREATERTHANOREQUAL",
288+
"0"
289+
),
290+
"issue must carry the `auctionDiscountBps >= 0` deployment guard \
291+
(expected window of <auctionDiscountBps>, OP_GREATERTHANOREQUAL, 0 \
292+
within 3 consecutive ASM tokens of `issue`)"
293+
);
294+
assert!(
295+
contains_window_3(
296+
&output,
297+
"issue",
298+
"<auctionDiscountBps>",
299+
"OP_LESSTHAN",
300+
"10000"
301+
),
302+
"issue must carry the `auctionDiscountBps < 10000` deployment guard \
303+
(expected window of <auctionDiscountBps>, OP_LESSTHAN, 10000 within \
304+
3 consecutive ASM tokens of `issue`)"
281305
);
282306
}
283307

308+
/// True iff the function `name`'s server-variant ASM contains three given
309+
/// tokens in any order within a 3-token sliding window. Used for targeted
310+
/// regression checks where the compiler may emit a comparison's operands
311+
/// and opcode in a non-postfix display order — what matters is adjacency,
312+
/// not exact sequence.
313+
fn contains_window_3(
314+
output: &arkade_compiler::models::ContractJson,
315+
name: &str,
316+
a: &str,
317+
b: &str,
318+
c: &str,
319+
) -> bool {
320+
let tokens = asm_tokens(output, name);
321+
if tokens.len() < 3 {
322+
return false;
323+
}
324+
let target: std::collections::BTreeSet<&str> = [a, b, c].into_iter().collect();
325+
tokens.windows(3).any(|w| {
326+
let s: std::collections::BTreeSet<&str> = w.iter().map(|t| t.as_str()).collect();
327+
s == target
328+
})
329+
}
330+
284331
#[test]
285332
fn test_issue_uses_ceiling_division_on_required_collateral() {
286333
// Dust-issuance defence: the required-collateral floor is computed via
@@ -691,10 +738,32 @@ fn test_roll_pair_enforces_all_deployment_invariants() {
691738
gt, 6,
692739
"rollIn must replicate issue's invariants (expected 6 OP_GREATERTHAN, found {gt})"
693740
);
694-
let gte = opcode_count(&output, "rollIn", "OP_GREATERTHANOREQUAL64");
695-
assert!(
696-
gte >= 1,
697-
"rollIn must carry auctionDiscountBps >= 0 (found {gte} OP_GREATERTHANOREQUAL64)"
741+
// Targeted check for `auctionDiscountBps >= 0` AND `< 10000` — see
742+
// the parallel test in `test_issue_enforces_deployment_invariants` for
743+
// the rationale (arkanaai O1 / CodeRabbit review).
744+
assert!(
745+
contains_window_3(
746+
&output,
747+
"rollIn",
748+
"<auctionDiscountBps>",
749+
"OP_GREATERTHANOREQUAL",
750+
"0"
751+
),
752+
"rollIn must carry the `auctionDiscountBps >= 0` deployment guard \
753+
(expected window of <auctionDiscountBps>, OP_GREATERTHANOREQUAL, 0 \
754+
within 3 consecutive ASM tokens of `rollIn`)"
755+
);
756+
assert!(
757+
contains_window_3(
758+
&output,
759+
"rollIn",
760+
"<auctionDiscountBps>",
761+
"OP_LESSTHAN",
762+
"10000"
763+
),
764+
"rollIn must carry the `auctionDiscountBps < 10000` deployment guard \
765+
(expected window of <auctionDiscountBps>, OP_LESSTHAN, 10000 within \
766+
3 consecutive ASM tokens of `rollIn`)"
698767
);
699768
}
700769

0 commit comments

Comments
 (0)