diff --git a/test/FixedPointMathLib.k.sol b/test/FixedPointMathLib.k.sol index 4ed260c8..74794028 100644 --- a/test/FixedPointMathLib.k.sol +++ b/test/FixedPointMathLib.k.sol @@ -10,7 +10,7 @@ contract FixedPointMathLibVerification is Test, KontrolCheats { // Constants uint256 constant WAD = 1e18; - // Public wrapper for mulWad since Kontrol doesn't support vm.expectRevert + // Public wrapper for mulWad since Kontrol doesn't support vm.expectRevert // for internal calls, and FixedPointMathLib.mulWad is internal function mulWad(uint x, uint y) public pure returns (uint256) { return FixedPointMathLib.mulWad(x, y); @@ -30,7 +30,7 @@ contract FixedPointMathLibVerification is Test, KontrolCheats { assert(zImpl == zSpec); } else { - vm.expectRevert(FixedPointMathLib.MulWadFailed.selector); // FixedPointMathLib.MulWadFailed.selector + vm.expectRevert(FixedPointMathLib.MulWadFailed.selector); this.mulWad(x, y); } @@ -44,8 +44,60 @@ contract FixedPointMathLibVerification is Test, KontrolCheats { assert(zImpl == zSpec); } else { - vm.expectRevert(FixedPointMathLib.MulWadFailed.selector); // FixedPointMathLib.MulWadFailed.selector + vm.expectRevert(FixedPointMathLib.MulWadFailed.selector); this.mulWadUp(x, y); } } + + //function log2(uint256 x) internal pure returns (uint256 r) { + // /// @solidity memory-safe-assembly + // assembly { + // r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) + // r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) + // r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) + // r := or(r, shl(4, lt(0xffff, shr(r, x)))) + // r := or(r, shl(3, lt(0xff, shr(r, x)))) + // r := or(r, shl(2, lt(0xf, shr(r, x)))) + // r := or(r, byte(shr(r, x), hex"00000101020202020303030303030303")) + // } + //} + + //function testMyLog2(uint256 x) public { + // uint256 r = log2(x); + // if(x > 0) + // assertLe(2**r, x); + // else + // assertEq(r,0); + //} + + function testLog2(uint256 x) public pure { + + unchecked { + uint256 y = x; uint256 z = 0; + if (2 ** 128 - 1 < y) { y = y >> 128; } else { } + if (2 ** 64 - 1 < y) { y = y >> 64; } else { } + if (2 ** 32 - 1 < y) { y = y >> 32; } else { } + if (2 ** 16 - 1 < y) { y = y >> 16; } else { } + if (2 ** 8 - 1 < y) { y = y >> 8; } else { } + if (2 ** 4 - 1 < y) { y = y >> 4; } else { } + + if (2 ** 3 - 1 < y) z = 4; else + if (2 ** 2 - 1 < y) z = 3; else + if (2 ** 1 - 1 < y) z = 2; else + if (2 ** 0 - 1 < y) z = 1; + } + + uint256 r = FixedPointMathLib.log2(x); + + if(x > 0){ + assertLe(2**r, x); + if (r < 255) { + assertLt(x, 2**(r+1)); + } else { + assertEq(r, 255); + } + } + else + assertEq(r,0); + } } diff --git a/test/run-kevm.sh b/test/run-kevm.sh index 4fdd7f30..c0c996e3 100755 --- a/test/run-kevm.sh +++ b/test/run-kevm.sh @@ -7,14 +7,15 @@ forge_build() { } kontrol_kompile() { - kontrol build \ - --verbose \ - --require ${lemmas} \ - --module-import ${module} \ + GHCRTS='' kontrol build \ + --verbose \ + --require ${lemmas} \ + --module-import ${module} \ ${rekompile} } kontrol_prove() { + export GHCRTS='-N6' kontrol prove \ --max-depth ${max_depth} \ --max-iterations ${max_iterations} \ @@ -29,7 +30,8 @@ kontrol_prove() { ${break_every_step} \ ${break_on_calls} \ ${tests} \ - ${use_booster} + --max-frontier-parallel 6 \ + --kore-rpc-command 'kore-rpc-booster --equation-max-recursion 10' } kontrol_claim() { @@ -51,7 +53,7 @@ smt_timeout=100000 # Number of processes run by the prover in parallel # Should be at most (M - 8) / 8 in a machine with M GB of RAM -workers=12 +workers=3 # Switch the options below to turn them on or off rekompile=--rekompile @@ -89,9 +91,10 @@ use_booster=--use-booster tests="" tests+="--match-test FixedPointMathLibVerification.testMulWad(uint256,uint256) " tests+="--match-test FixedPointMathLibVerification.testMulWadUp " +tests+="--match-test FixedPointMathLibVerification.testLog2 " # Name of the claim to execute -claim=mulWadUp-first-roadblock +claim=log2-06 # Comment these lines as needed pkill kore-rpc || true diff --git a/test/solady-lemmas.k b/test/solady-lemmas.k index d3f301a5..49dcfe4b 100644 --- a/test/solady-lemmas.k +++ b/test/solady-lemmas.k @@ -20,7 +20,6 @@ module SOLADY-LEMMAS rule runLemma(T) => doneLemma(T) ... - // // Bool // @@ -28,28 +27,180 @@ module SOLADY-LEMMAS rule bool2Word ( X ) => 1 requires X [simplification] rule bool2Word ( X ) => 0 requires notBool X [simplification] + rule chop ( bool2Word ( X ) < bool2Word ( X ) < 1 <>Int B:Int ) >>Int C:Int => A >>Int ( B +Int C ) [simplification] + + rule A =/=Int B => notBool ( A ==Int B ) + [simplification, comm] + + rule #Ceil ( byte (X:Int, Y:Int) ) => #Top + requires 0 <=Int X andBool X {true #Equals X } #And { true #Equals Y } [simplification] + rule A >>Int B ==Int 0 => log2Int ( A ) <=Int B + [simplification, comm, concrete(A)] - // - // Arithmetic - // + rule 0 <=Int A >>Int B => true + requires 0 <=Int A andBool 0 <=Int B + [simplification] + + rule A >>Int B <=Int C => A <=Int ( C <>Int B => ( C < maxUInt256 -Int X requires #rangeUInt ( 256 , X ) [simplification] + // + // Comparisons + // + + // Concrete to the left of comparisons, prioritising <=Int and =Int Y => Y <=Int X [simplification, concrete(Y)] + rule X >Int Y => Y Y Y <=Int X [simplification] + rule notBool X >Int Y => X <=Int Y [simplification] + rule notBool X >=Int Y => X { true #Equals Y { true #Equals Y <=Int X } [simplification] + rule { true #Equals ( notBool X >Int Y ) } => { true #Equals X <=Int Y } [simplification] + rule { true #Equals ( notBool X >=Int Y ) } => { true #Equals X { true #Equals Y { true #Equals Y <=Int X } [simplification] + rule { ( notBool X >Int Y ) #Equals true } => { true #Equals X <=Int Y } [simplification] + rule { ( notBool X >=Int Y ) #Equals true } => { true #Equals X A + requires 0 <=Int A andBool A A A /Int C <=Int B + requires A modInt C ==Int 0 + [simplification, concrete(A, C)] + + rule A <=Int B -Int C => C <=Int B -Int A + [simplification, concrete(A, B)] + + // + // Specialised + // + + syntax Int ::= "cachedBytesConstant" [alias] + rule cachedBytesConstant => 6928917744019834342450304135053993530982274426945361611473370484834304 + + rule ( cachedBytesConstant >>Int ( ( maxUInt5 -Int Y ) *Int 8 ) ) modInt 256 => 0 + requires 0 <=Int Y andBool Y =Int 16 ) + [simplification] + + rule ( cachedBytesConstant >>Int ( ( maxUInt5 -Int Y ) *Int 8 ) ) modInt 256 => 1 + requires 0 <=Int Y andBool Y >Int ( ( maxUInt5 -Int Y ) *Int 8 ) ) modInt 256 => 2 + requires 0 <=Int Y andBool Y >Int ( ( maxUInt5 -Int Y ) *Int 8 ) ) modInt 256 => 3 + requires 0 <=Int Y andBool Y >Int Y:Int , cachedBytesConstant ) => 3 + requires 0 <=Int X andBool 0 <=Int Y + andBool X <=Int ( 2 ^Int ( Y +Int 4 ) -Int 1 ) + andBool 7 >Int Y + [simplification, concrete(Y)] + + rule byte ( X:Int >>Int Y:Int , cachedBytesConstant ) => 2 + requires 0 <=Int X andBool 0 <=Int Y + andBool X <=Int ( 2 ^Int ( Y +Int 4 ) -Int 1 ) + andBool notBool 7 >Int Y + andBool 3 >Int Y + [simplification, concrete(Y)] + + rule byte ( X:Int >>Int Y:Int , cachedBytesConstant ) => 1 + requires 0 <=Int X andBool 0 <=Int Y + andBool X <=Int ( 2 ^Int ( Y +Int 4 ) -Int 1 ) + andBool notBool 3 >Int Y + andBool 1 >Int Y + [simplification, concrete(Y)] + + rule byte ( X:Int >>Int Y:Int , cachedBytesConstant ) => 0 + requires 0 <=Int X andBool 0 <=Int Y + andBool X <=Int ( 2 ^Int ( Y +Int 4 ) -Int 1 ) + andBool notBool 1 >Int Y + andBool 0 >Int Y + [simplification, concrete(Y)] + endmodule module SOLADY-LEMMAS-SPEC imports SOLADY-LEMMAS - claim [first-roadblock]: runLemma(bool2Word( notBool ( notBool ( ( notBool X:Int ==Int 0 ) andBool maxUInt256 /Word X:Int doneLemma(0) ... - claim [mulWad-first-roadblock]: runLemma(bool2Word( notBool ( notBool ( ( notBool X:Int ==Int 0 ) andBool maxUInt256 /Word X:Int doneLemma(0) ... - requires 0 <=Int X + //claim [log2-01]: runLemma(chop (bool2Word ( X:Bool ) < doneLemma(128) ... + // requires X:Bool + + //claim [log2-02]: runLemma(chop (bool2Word ( X:Bool ) < doneLemma(0) ... + // requires notBool X:Bool + + //claim [log2-03]: runLemma(1 < doneLemma(pow128) ... + // requires X:Bool + + //claim [log2-04]: runLemma(bool2Word ( X:Bool ) < doneLemma(128) ... + // requires X:Bool + + //claim [log2-05]: runLemma( maxUInt8 doneLemma(false) ... + + //claim [log2-06]: runLemma (maxUInt8 >Int bool2Word ( maxUInt128 doneLemma(false) ... + + // claim [log2-07]: runLemma (1 <>Int bool2Word ( maxUInt128 doneLemma(maxUInt128 + + claim [arith-01]: + + runLemma ( + notBool ( maxUInt8 <=Int ( 4 |Int ( ( cachedBytesConstant >>Int ( ( maxUInt5 -Int ( VV0_x_114b9705:Int >>Int 4 ) ) *Int 8 ) ) modInt 256 ) ) ) + andBool VV0_x_114b9705 >>Int 4 doneLemma ( + true + ) + + requires 0 <=Int VV0_x_114b9705:Int + andBool VV0_x_114b9705:Int >>Int 4 <=Int 1 + + claim [arith-02]: + + runLemma ( maxUInt64 >Int 128 ) => doneLemma ( false ) + + requires VV0_x_114b9705 <=Int maxUInt192 claim [mulWadUp-second-roadblock]: runLemma( notBool ( ( notBool X:Int ==Int 0 ) andBool maxUInt256 /Word X:Int doneLemma(false) ... requires ( notBool ( notBool ( ( notBool X:Int ==Int 0 ) andBool maxUInt256 /Word X:Int