|
@@ -0,0 +1,366 @@
|
|
|
+import "helpers.spec"
|
|
|
+
|
|
|
+methods {
|
|
|
+ pushFront(bytes32) envfree
|
|
|
+ pushBack(bytes32) envfree
|
|
|
+ popFront() returns (bytes32) envfree
|
|
|
+ popBack() returns (bytes32) envfree
|
|
|
+ clear() envfree
|
|
|
+
|
|
|
+ // exposed for FV
|
|
|
+ begin() returns (int128) envfree
|
|
|
+ end() returns (int128) envfree
|
|
|
+
|
|
|
+ // view
|
|
|
+ length() returns (uint256) envfree
|
|
|
+ empty() returns (bool) envfree
|
|
|
+ front() returns (bytes32) envfree
|
|
|
+ back() returns (bytes32) envfree
|
|
|
+ at_(uint256) returns (bytes32) envfree // at is a reserved word
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Helpers โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+
|
|
|
+function min_int128() returns mathint {
|
|
|
+ return -(1 << 127);
|
|
|
+}
|
|
|
+
|
|
|
+function max_int128() returns mathint {
|
|
|
+ return (1 << 127) - 1;
|
|
|
+}
|
|
|
+
|
|
|
+// Could be broken in theory, but not in practice
|
|
|
+function boundedQueue() returns bool {
|
|
|
+ return
|
|
|
+ max_int128() > to_mathint(end()) &&
|
|
|
+ min_int128() < to_mathint(begin());
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Invariant: end is larger or equal than begin โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+invariant boundariesConsistency()
|
|
|
+ end() >= begin()
|
|
|
+ filtered { f -> !f.isView }
|
|
|
+ { preserved { require boundedQueue(); } }
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Invariant: length is end minus begin โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+invariant lengthConsistency()
|
|
|
+ length() == to_mathint(end()) - to_mathint(begin())
|
|
|
+ filtered { f -> !f.isView }
|
|
|
+ { preserved { require boundedQueue(); } }
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Invariant: empty() is length 0 and no element exists โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+invariant emptiness()
|
|
|
+ empty() <=> length() == 0
|
|
|
+ filtered { f -> !f.isView }
|
|
|
+ { preserved { require boundedQueue(); } }
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Invariant: front points to the first index and back points to the last one โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+invariant queueEndings()
|
|
|
+ at_(length() - 1) == back() && at_(0) == front()
|
|
|
+ filtered { f -> !f.isView }
|
|
|
+ {
|
|
|
+ preserved {
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Function correctness: pushFront adds an element at the beginning of the queue โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule pushFront(bytes32 value) {
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ uint256 lengthBefore = length();
|
|
|
+
|
|
|
+ pushFront@withrevert(value);
|
|
|
+
|
|
|
+ // liveness
|
|
|
+ assert !lastReverted, "never reverts";
|
|
|
+
|
|
|
+ // effect
|
|
|
+ assert front() == value, "front set to value";
|
|
|
+ assert length() == lengthBefore + 1, "queue extended";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Rule: pushFront preserves the previous values in the queue with a +1 offset โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule pushFrontConsistency(uint256 index) {
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ bytes32 beforeAt = at_(index);
|
|
|
+
|
|
|
+ bytes32 value;
|
|
|
+ pushFront(value);
|
|
|
+
|
|
|
+ // try to read value
|
|
|
+ bytes32 afterAt = at_@withrevert(index + 1);
|
|
|
+
|
|
|
+ assert !lastReverted, "value still there";
|
|
|
+ assert afterAt == beforeAt, "data is preserved";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Function correctness: pushBack adds an element at the end of the queue โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule pushBack(bytes32 value) {
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ uint256 lengthBefore = length();
|
|
|
+
|
|
|
+ pushBack@withrevert(value);
|
|
|
+
|
|
|
+ // liveness
|
|
|
+ assert !lastReverted, "never reverts";
|
|
|
+
|
|
|
+ // effect
|
|
|
+ assert back() == value, "back set to value";
|
|
|
+ assert length() == lengthBefore + 1, "queue increased";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Rule: pushBack preserves the previous values in the queue โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule pushBackConsistency(uint256 index) {
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ bytes32 beforeAt = at_(index);
|
|
|
+
|
|
|
+ bytes32 value;
|
|
|
+ pushBack(value);
|
|
|
+
|
|
|
+ // try to read value
|
|
|
+ bytes32 afterAt = at_@withrevert(index);
|
|
|
+
|
|
|
+ assert !lastReverted, "value still there";
|
|
|
+ assert afterAt == beforeAt, "data is preserved";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Function correctness: popFront removes an element from the beginning of the queue โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule popFront {
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ uint256 lengthBefore = length();
|
|
|
+ bytes32 frontBefore = front@withrevert();
|
|
|
+
|
|
|
+ bytes32 popped = popFront@withrevert();
|
|
|
+ bool success = !lastReverted;
|
|
|
+
|
|
|
+ // liveness
|
|
|
+ assert success <=> lengthBefore != 0, "never reverts if not previously empty";
|
|
|
+
|
|
|
+ // effect
|
|
|
+ assert success => frontBefore == popped, "previous front is returned";
|
|
|
+ assert success => length() == lengthBefore - 1, "queue decreased";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Rule: at(x) is preserved and offset to at(x - 1) after calling popFront |
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule popFrontConsistency(uint256 index) {
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ // Read (any) value that is not the front (this asserts the value exists / the queue is long enough)
|
|
|
+ require index > 1;
|
|
|
+ bytes32 before = at_(index);
|
|
|
+
|
|
|
+ popFront();
|
|
|
+
|
|
|
+ // try to read value
|
|
|
+ bytes32 after = at_@withrevert(index - 1);
|
|
|
+
|
|
|
+ assert !lastReverted, "value still exists in the queue";
|
|
|
+ assert before == after, "values are offset and not modified";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Function correctness: popBack removes an element from the end of the queue โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule popBack {
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ uint256 lengthBefore = length();
|
|
|
+ bytes32 backBefore = back@withrevert();
|
|
|
+
|
|
|
+ bytes32 popped = popBack@withrevert();
|
|
|
+ bool success = !lastReverted;
|
|
|
+
|
|
|
+ // liveness
|
|
|
+ assert success <=> lengthBefore != 0, "never reverts if not previously empty";
|
|
|
+
|
|
|
+ // effect
|
|
|
+ assert success => backBefore == popped, "previous back is returned";
|
|
|
+ assert success => length() == lengthBefore - 1, "queue decreased";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Rule: at(x) is preserved after calling popBack |
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule popBackConsistency(uint256 index) {
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ // Read (any) value that is not the back (this asserts the value exists / the queue is long enough)
|
|
|
+ require index < length() - 1;
|
|
|
+ bytes32 before = at_(index);
|
|
|
+
|
|
|
+ popBack();
|
|
|
+
|
|
|
+ // try to read value
|
|
|
+ bytes32 after = at_@withrevert(index);
|
|
|
+
|
|
|
+ assert !lastReverted, "value still exists in the queue";
|
|
|
+ assert before == after, "values are offset and not modified";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Function correctness: clear sets length to 0 โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule clear {
|
|
|
+ clear@withrevert();
|
|
|
+
|
|
|
+ // liveness
|
|
|
+ assert !lastReverted, "never reverts";
|
|
|
+
|
|
|
+ // effect
|
|
|
+ assert length() == 0, "sets length to 0";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Rule: front/back access reverts only if the queue is empty or querying out of bounds โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule onlyEmptyRevert(env e) {
|
|
|
+ require nonpayable(e);
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ method f;
|
|
|
+ calldataarg args;
|
|
|
+
|
|
|
+ bool emptyBefore = empty();
|
|
|
+
|
|
|
+ f@withrevert(e, args);
|
|
|
+
|
|
|
+ assert lastReverted => (
|
|
|
+ (f.selector == front().selector && emptyBefore) ||
|
|
|
+ (f.selector == back().selector && emptyBefore) ||
|
|
|
+ (f.selector == popFront().selector && emptyBefore) ||
|
|
|
+ (f.selector == popBack().selector && emptyBefore) ||
|
|
|
+ f.selector == at_(uint256).selector // revert conditions are verified in onlyOutOfBoundsRevert
|
|
|
+ ), "only revert if empty or out of bounds";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Rule: at(index) only reverts if index is out of bounds |
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule onlyOutOfBoundsRevert(uint256 index) {
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ at_@withrevert(index);
|
|
|
+
|
|
|
+ assert lastReverted <=> index >= length(), "only reverts if index is out of bounds";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Rule: only clear/push/pop operations can change the length of the queue โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule noLengthChange(env e) {
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ method f;
|
|
|
+ calldataarg args;
|
|
|
+
|
|
|
+ uint256 lengthBefore = length();
|
|
|
+ f(e, args);
|
|
|
+ uint256 lengthAfter = length();
|
|
|
+
|
|
|
+ assert lengthAfter != lengthBefore => (
|
|
|
+ (f.selector == pushFront(bytes32).selector && lengthAfter == lengthBefore + 1) ||
|
|
|
+ (f.selector == pushBack(bytes32).selector && lengthAfter == lengthBefore + 1) ||
|
|
|
+ (f.selector == popBack().selector && lengthAfter == lengthBefore - 1) ||
|
|
|
+ (f.selector == popFront().selector && lengthAfter == lengthBefore - 1) ||
|
|
|
+ (f.selector == clear().selector && lengthAfter == 0)
|
|
|
+ ), "length is only affected by clear/pop/push operations";
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+โ Rule: only push/pop can change values bounded in the queue (outside values aren't cleared) โ
|
|
|
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+*/
|
|
|
+rule noDataChange(env e) {
|
|
|
+ requireInvariant boundariesConsistency();
|
|
|
+ require boundedQueue();
|
|
|
+
|
|
|
+ method f;
|
|
|
+ calldataarg args;
|
|
|
+
|
|
|
+ uint256 index;
|
|
|
+ bytes32 atBefore = at_(index);
|
|
|
+ f(e, args);
|
|
|
+ bytes32 atAfter = at_@withrevert(index);
|
|
|
+ bool atAfterSuccess = !lastReverted;
|
|
|
+
|
|
|
+ assert !atAfterSuccess <=> (
|
|
|
+ f.selector == clear().selector ||
|
|
|
+ (f.selector == popBack().selector && index == length()) ||
|
|
|
+ (f.selector == popFront().selector && index == length())
|
|
|
+ ), "indexes of the queue are only removed by clear or pop";
|
|
|
+
|
|
|
+ assert atAfterSuccess && atAfter != atBefore => (
|
|
|
+ f.selector == popFront().selector ||
|
|
|
+ f.selector == pushFront(bytes32).selector
|
|
|
+ ), "values of the queue are only changed by popFront or pushFront";
|
|
|
+}
|