@@ -2060,10 +2060,197 @@ tests = testGroup "hevm"
2060
2060
}
2061
2061
}
2062
2062
|]
2063
- let sig = Just (Sig " checkval(uint256,uint256 )" [AbiUIntType 256 , AbiUIntType 256 ])
2063
+ let sig = Just (Sig " checkval(uint8 )" [AbiUIntType 8 ])
2064
2064
(res, [Qed _]) <- withDefaultSolver $ \ s ->
2065
2065
checkAssert s defaultPanicCodes c sig [] defaultVeriOpts
2066
2066
putStrLnM $ " successfully explored: " <> show (Expr. numBranches res) <> " paths"
2067
+ , test " staticcall-check-orig" $ do
2068
+ Just c <- solcRuntime " C"
2069
+ [i |
2070
+ contract Target {
2071
+ function add(uint256 x, uint256 y) external pure returns (uint256) {
2072
+ unchecked {
2073
+ return x + y;
2074
+ }
2075
+ }
2076
+ }
2077
+
2078
+ contract C {
2079
+ function checkval(uint256 x, uint256 y) public {
2080
+ Target t = new Target();
2081
+ address realAddr = address(t);
2082
+ bytes memory data = abi.encodeWithSignature("add(uint256,uint256)", x, y);
2083
+ (bool success, bytes memory returnData) = realAddr.staticcall(data);
2084
+ assert(success);
2085
+
2086
+ uint result = abi.decode(returnData, (uint256));
2087
+ uint expected;
2088
+ unchecked {
2089
+ expected = x + y;
2090
+ }
2091
+ assert(result == expected);
2092
+ }
2093
+ }
2094
+ |]
2095
+ let sig = Just (Sig " checkval(uint256,uint256)" [AbiAddressType , AbiUIntType 256 , AbiUIntType 256 ])
2096
+ (res, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig [] defaultVeriOpts
2097
+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches res) <> " paths"
2098
+ let numCexes = sum $ map (fromEnum . isCex) ret
2099
+ let numErrs = sum $ map (fromEnum . isError) ret
2100
+ let numQeds = sum $ map (fromEnum . isQed) ret
2101
+ assertEqualM " number of counterexamples" 0 numCexes
2102
+ assertEqualM " number of errors" 0 numErrs
2103
+ assertEqualM " number of qed-s" 1 numQeds
2104
+ , test " staticcall-check-orig2" $ do
2105
+ Just c <- solcRuntime " C"
2106
+ [i |
2107
+ contract Target {
2108
+ function add(uint256 x, uint256 y) external pure returns (uint256) {
2109
+ assert(1 == 0);
2110
+ }
2111
+ }
2112
+ contract C {
2113
+ function checkval(uint256 x, uint256 y) public {
2114
+ Target t = new Target();
2115
+ address realAddr = address(t);
2116
+ bytes memory data = abi.encodeWithSignature("add(uint256,uint256)", x, y);
2117
+ (bool success, bytes memory returnData) = realAddr.staticcall(data);
2118
+ assert(success);
2119
+ }
2120
+ }
2121
+ |]
2122
+ let sig = Just (Sig " checkval(uint256,uint256)" [AbiAddressType , AbiUIntType 256 , AbiUIntType 256 ])
2123
+ (res, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig [] defaultVeriOpts
2124
+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches res) <> " paths"
2125
+ -- let cexesExt = map (snd . fromJust . extractCex) ret
2126
+ -- putStrLnM $ "Cexes: \n" <> (unlines $ map ("-> " ++) (map show cexesExt))
2127
+ let numCexes = sum $ map (fromEnum . isCex) ret
2128
+ let numErrs = sum $ map (fromEnum . isError) ret
2129
+ let numQeds = sum $ map (fromEnum . isQed) ret
2130
+ assertEqualM " number of counterexamples" 1 numCexes
2131
+ assertEqualM " number of errors" 0 numErrs
2132
+ assertEqualM " number of qed-s" 0 numQeds
2133
+ , test " staticcall-check-symbolic1" $ do
2134
+ Just c <- solcRuntime " C"
2135
+ [i |
2136
+ contract C {
2137
+ function checkval(address inputAddr, uint256 x, uint256 y) public {
2138
+ bytes memory data = abi.encodeWithSignature("add(uint256,uint256)", x, y);
2139
+ (bool success, bytes memory returnData) = inputAddr.staticcall(data);
2140
+ assert(success);
2141
+ }
2142
+ }
2143
+ |]
2144
+ let sig = Just (Sig " checkval(address,uint256,uint256)" [AbiAddressType , AbiUIntType 256 , AbiUIntType 256 ])
2145
+ (res, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig [] defaultVeriOpts
2146
+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches res) <> " paths"
2147
+ let numCexes = sum $ map (fromEnum . isCex) ret
2148
+ let numErrs = sum $ map (fromEnum . isError) ret
2149
+ let numQeds = sum $ map (fromEnum . isQed) ret
2150
+ -- There are 2 CEX-es, in contrast to the above (staticcall-check-orig2).
2151
+ -- This is because with one CEX, the return DATA
2152
+ -- is empty, and in the other, the return data is non-empty (but symbolic)
2153
+ assertEqualM " number of counterexamples" 2 numCexes
2154
+ assertEqualM " number of errors" 0 numErrs
2155
+ assertEqualM " number of qed-s" 0 numQeds
2156
+ -- This checks that calling a symbolic address with staticcall will ALWAYS return 0/1
2157
+ -- which is the semantic of the EVM. We insert a constraint over the return value
2158
+ -- even when overapproximation is used, as below.
2159
+ , test " staticcall-check-symbolic-yul" $ do
2160
+ Just c <- solcRuntime " C"
2161
+ [i |
2162
+ contract C {
2163
+ function checkval(address inputAddr, uint256 x, uint256 y) public {
2164
+ uint success;
2165
+ assembly {
2166
+ // Allocate memory for the call data
2167
+ let callData := mload(0x40)
2168
+
2169
+ // Function signature for "add(uint256,uint256)" is "0x771602f7"
2170
+ mstore(callData, 0x771602f700000000000000000000000000000000000000000000000000000000)
2171
+
2172
+ // Store the parameters x and y
2173
+ mstore(add(callData, 4), x)
2174
+ mstore(add(callData, 36), y)
2175
+
2176
+ // Perform the static call
2177
+ success := staticcall(
2178
+ gas(), // Forward all available gas
2179
+ inputAddr, // Address to call
2180
+ callData, // Input data location
2181
+ 68, // Input data size (4 bytes for function signature + 32 bytes each for x and y)
2182
+ 0, // Output data location (0 means we don't care about the output)
2183
+ 0 // Output data size
2184
+ )
2185
+ }
2186
+ assert(success <= 1);
2187
+ }
2188
+ }
2189
+ |]
2190
+ let sig = Just (Sig " checkval(address,uint256,uint256)" [AbiAddressType , AbiUIntType 256 , AbiUIntType 256 ])
2191
+ (res, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig [] defaultVeriOpts
2192
+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches res) <> " paths"
2193
+ let numCexes = sum $ map (fromEnum . isCex) ret
2194
+ let numErrs = sum $ map (fromEnum . isError) ret
2195
+ let numQeds = sum $ map (fromEnum . isQed) ret
2196
+ assertEqualM " number of counterexamples" 0 numCexes -- no counterexamples, because it is always 0/1
2197
+ assertEqualM " number of errors" 0 numErrs
2198
+ assertEqualM " number of qed-s" 1 numQeds
2199
+ , test " staticcall-check-symbolic2" $ do
2200
+ Just c <- solcRuntime " C"
2201
+ [i |
2202
+ contract C {
2203
+ function checkval(address inputAddr, uint256 x, uint256 y) public {
2204
+ bytes memory data = abi.encodeWithSignature("add(uint256,uint256)", x, y);
2205
+ (bool success, bytes memory returnData) = inputAddr.staticcall(data);
2206
+ assert(success);
2207
+
2208
+ uint result = abi.decode(returnData, (uint256));
2209
+ uint expected;
2210
+ unchecked {
2211
+ expected = x + y;
2212
+ }
2213
+ assert(result == expected);
2214
+ }
2215
+ }
2216
+ |]
2217
+ let sig = Just (Sig " checkval(address,uint256,uint256)" [AbiAddressType , AbiUIntType 256 , AbiUIntType 256 ])
2218
+ (res, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig [] defaultVeriOpts
2219
+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches res) <> " paths"
2220
+ let numCexes = sum $ map (fromEnum . isCex) ret
2221
+ let numErrs = sum $ map (fromEnum . isError) ret
2222
+ let numQeds = sum $ map (fromEnum . isQed) ret
2223
+ assertEqualM " number of counterexamples" 2 numCexes
2224
+ assertEqualM " number of errors" 1 numErrs
2225
+ assertEqualM " number of qed-s" 0 numQeds
2226
+ , test " jump-symbolic" $ do
2227
+ Just c <- solcRuntime " C"
2228
+ [i |
2229
+ // Target contract with a view function
2230
+ contract Target {
2231
+ }
2232
+
2233
+ // Caller contract using staticcall
2234
+ contract C {
2235
+ function checkval(address inputAddr, uint256 x, uint256 y) public {
2236
+ Target t = new Target();
2237
+ address realAddr = address(t);
2238
+
2239
+ bytes memory data = abi.encodeWithSignature("add(uint256,uint256)", x, y);
2240
+ (bool success, bytes memory returnData) = inputAddr.staticcall(data);
2241
+ assert(success == true);
2242
+ }
2243
+ }
2244
+ |]
2245
+ let sig = Just (Sig " checkval(address,uint256,uint256)" [AbiAddressType , AbiUIntType 256 , AbiUIntType 256 ])
2246
+ (res, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig [] defaultVeriOpts
2247
+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches res) <> " paths"
2248
+ let numCexes = sum $ map (fromEnum . isCex) ret
2249
+ let numErrs = sum $ map (fromEnum . isError) ret
2250
+ let numQeds = sum $ map (fromEnum . isQed) ret
2251
+ assertEqualM " number of counterexamples" numCexes 2
2252
+ assertEqualM " number of symbolic copy errors" numErrs 0
2253
+ assertEqualM " number of qed-s" numQeds 0
2067
2254
,
2068
2255
test " opcode-mul-assoc" $ do
2069
2256
Just c <- solcRuntime " MyContract"
0 commit comments