mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #13177 from ethereum/check-overflow-after-mul-operation
Check overflow after multiplication operation.
This commit is contained in:
commit
e27cb025c2
@ -7,6 +7,7 @@ Language Features:
|
||||
|
||||
|
||||
Compiler Features:
|
||||
* Code Generator: More efficient overflow checks for multiplication.
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
@ -684,28 +684,46 @@ string YulUtilFunctions::overflowCheckedIntMulFunction(IntegerType const& _type)
|
||||
function <functionName>(x, y) -> product {
|
||||
x := <cleanupFunction>(x)
|
||||
y := <cleanupFunction>(y)
|
||||
let product_raw := mul(x, y)
|
||||
product := <cleanupFunction>(product_raw)
|
||||
<?signed>
|
||||
// overflow, if x > 0, y > 0 and x > (maxValue / y)
|
||||
if and(and(sgt(x, 0), sgt(y, 0)), gt(x, div(<maxValue>, y))) { <panic>() }
|
||||
// underflow, if x > 0, y < 0 and y < (minValue / x)
|
||||
if and(and(sgt(x, 0), slt(y, 0)), slt(y, sdiv(<minValue>, x))) { <panic>() }
|
||||
// underflow, if x < 0, y > 0 and x < (minValue / y)
|
||||
if and(and(slt(x, 0), sgt(y, 0)), slt(x, sdiv(<minValue>, y))) { <panic>() }
|
||||
// overflow, if x < 0, y < 0 and x < (maxValue / y)
|
||||
if and(and(slt(x, 0), slt(y, 0)), slt(x, sdiv(<maxValue>, y))) { <panic>() }
|
||||
<?gt128bit>
|
||||
<?256bit>
|
||||
// special case
|
||||
if and(slt(x, 0), eq(y, <minValue>)) { <panic>() }
|
||||
</256bit>
|
||||
// overflow, if x != 0 and y != product/x
|
||||
if iszero(
|
||||
or(
|
||||
iszero(x),
|
||||
eq(y, sdiv(product, x))
|
||||
)
|
||||
) { <panic>() }
|
||||
<!gt128bit>
|
||||
if iszero(eq(product, product_raw)) { <panic>() }
|
||||
</gt128bit>
|
||||
<!signed>
|
||||
// overflow, if x != 0 and y > (maxValue / x)
|
||||
if and(iszero(iszero(x)), gt(y, div(<maxValue>, x))) { <panic>() }
|
||||
<?gt128bit>
|
||||
// overflow, if x != 0 and y != product/x
|
||||
if iszero(
|
||||
or(
|
||||
iszero(x),
|
||||
eq(y, div(product, x))
|
||||
)
|
||||
) { <panic>() }
|
||||
<!gt128bit>
|
||||
if iszero(eq(product, product_raw)) { <panic>() }
|
||||
</gt128bit>
|
||||
</signed>
|
||||
product := mul(x, y)
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("signed", _type.isSigned())
|
||||
("maxValue", toCompactHexWithPrefix(u256(_type.maxValue())))
|
||||
("minValue", toCompactHexWithPrefix(u256(_type.minValue())))
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
("minValue", toCompactHexWithPrefix(u256(_type.minValue())))
|
||||
("256bit", _type.numBits() == 256)
|
||||
("gt128bit", _type.numBits() > 128)
|
||||
.render();
|
||||
});
|
||||
}
|
||||
|
46
test/formal/checked_int_mul_12.py
Normal file
46
test/formal/checked_int_mul_12.py
Normal file
@ -0,0 +1,46 @@
|
||||
from opcodes import AND, SDIV, MUL, EQ, ISZERO, OR, SLT
|
||||
from rule import Rule
|
||||
from util import BVSignedUpCast, BVSignedMin, BVSignedCleanupFunction
|
||||
from z3 import BVMulNoOverflow, BVMulNoUnderflow, BitVec, Not, Or
|
||||
|
||||
"""
|
||||
Overflow checked signed integer multiplication.
|
||||
"""
|
||||
|
||||
# Approximation with 16-bit base types.
|
||||
n_bits = 12
|
||||
|
||||
for type_bits in [4, 6, 8, 12]:
|
||||
|
||||
rule = Rule()
|
||||
|
||||
# Input vars
|
||||
X_short = BitVec('X', type_bits)
|
||||
Y_short = BitVec('Y', type_bits)
|
||||
|
||||
# Z3's overflow and underflow conditions
|
||||
actual_overflow = Not(BVMulNoOverflow(X_short, Y_short, True))
|
||||
actual_underflow = Not(BVMulNoUnderflow(X_short, Y_short))
|
||||
|
||||
# cast to full n_bits values
|
||||
X = BVSignedUpCast(X_short, n_bits)
|
||||
Y = BVSignedUpCast(Y_short, n_bits)
|
||||
product_raw = MUL(X, Y)
|
||||
#remove any overflown bits
|
||||
product = BVSignedCleanupFunction(product_raw, type_bits)
|
||||
|
||||
# Constants
|
||||
min_value = BVSignedMin(type_bits, n_bits)
|
||||
|
||||
# Overflow and underflow checks in YulUtilFunction::overflowCheckedIntMulFunction
|
||||
if type_bits > n_bits / 2:
|
||||
sol_overflow_check_1 = ISZERO(OR(ISZERO(X), EQ(Y, SDIV(product, X))))
|
||||
if type_bits == n_bits:
|
||||
sol_overflow_check_2 = AND(SLT(X, 0), EQ(Y, min_value))
|
||||
sol_overflow_check = Or(sol_overflow_check_1 != 0, sol_overflow_check_2 != 0)
|
||||
else:
|
||||
sol_overflow_check = (sol_overflow_check_1 != 0)
|
||||
else:
|
||||
sol_overflow_check = (ISZERO(EQ(product, product_raw)) != 0)
|
||||
|
||||
rule.check(Or(actual_overflow, actual_underflow), sol_overflow_check)
|
@ -1,43 +0,0 @@
|
||||
from opcodes import AND, DIV, GT, SDIV, SGT, SLT
|
||||
from rule import Rule
|
||||
from util import BVSignedMax, BVSignedMin, BVSignedUpCast
|
||||
from z3 import BVMulNoOverflow, BVMulNoUnderflow, BitVec, Not, Or
|
||||
|
||||
"""
|
||||
Overflow checked signed integer multiplication.
|
||||
"""
|
||||
|
||||
# Approximation with 16-bit base types.
|
||||
n_bits = 16
|
||||
type_bits = 8
|
||||
|
||||
while type_bits <= n_bits:
|
||||
|
||||
rule = Rule()
|
||||
|
||||
# Input vars
|
||||
X_short = BitVec('X', type_bits)
|
||||
Y_short = BitVec('Y', type_bits)
|
||||
|
||||
# Z3's overflow and underflow conditions
|
||||
actual_overflow = Not(BVMulNoOverflow(X_short, Y_short, True))
|
||||
actual_underflow = Not(BVMulNoUnderflow(X_short, Y_short))
|
||||
|
||||
# cast to full n_bits values
|
||||
X = BVSignedUpCast(X_short, n_bits)
|
||||
Y = BVSignedUpCast(Y_short, n_bits)
|
||||
|
||||
# Constants
|
||||
maxValue = BVSignedMax(type_bits, n_bits)
|
||||
minValue = BVSignedMin(type_bits, n_bits)
|
||||
|
||||
# Overflow and underflow checks in YulUtilFunction::overflowCheckedIntMulFunction
|
||||
overflow_check_1 = AND(AND(SGT(X, 0), SGT(Y, 0)), GT(X, DIV(maxValue, Y)))
|
||||
underflow_check_1 = AND(AND(SGT(X, 0), SLT(Y, 0)), SLT(Y, SDIV(minValue, X)))
|
||||
underflow_check_2 = AND(AND(SLT(X, 0), SGT(Y, 0)), SLT(X, SDIV(minValue, Y)))
|
||||
overflow_check_2 = AND(AND(SLT(X, 0), SLT(Y, 0)), SLT(X, SDIV(maxValue, Y)))
|
||||
|
||||
rule.check(actual_overflow, Or(overflow_check_1 != 0, overflow_check_2 != 0))
|
||||
rule.check(actual_underflow, Or(underflow_check_1 != 0, underflow_check_2 != 0))
|
||||
|
||||
type_bits *= 2
|
@ -1,6 +1,6 @@
|
||||
from opcodes import AND, ISZERO, GT, DIV
|
||||
from opcodes import ISZERO, DIV, MUL, EQ, OR
|
||||
from rule import Rule
|
||||
from util import BVUnsignedUpCast, BVUnsignedMax
|
||||
from util import BVUnsignedUpCast, BVUnsignedCleanupFunction
|
||||
from z3 import BitVec, Not, BVMulNoOverflow
|
||||
|
||||
"""
|
||||
@ -8,10 +8,9 @@ Overflow checked unsigned integer multiplication.
|
||||
"""
|
||||
|
||||
# Approximation with 16-bit base types.
|
||||
n_bits = 16
|
||||
type_bits = 8
|
||||
n_bits = 12
|
||||
|
||||
while type_bits <= n_bits:
|
||||
for type_bits in [4, 6, 8, 12]:
|
||||
|
||||
rule = Rule()
|
||||
|
||||
@ -25,13 +24,14 @@ while type_bits <= n_bits:
|
||||
# cast to full n_bits values
|
||||
X = BVUnsignedUpCast(X_short, n_bits)
|
||||
Y = BVUnsignedUpCast(Y_short, n_bits)
|
||||
product_raw = MUL(X, Y)
|
||||
#remove any overflown bits
|
||||
product = BVUnsignedCleanupFunction(product_raw, type_bits)
|
||||
|
||||
# Constants
|
||||
maxValue = BVUnsignedMax(type_bits, n_bits)
|
||||
|
||||
# Overflow check in YulUtilFunction::overflowCheckedIntMulFunction
|
||||
overflow_check = AND(ISZERO(ISZERO(X)), GT(Y, DIV(maxValue, X)))
|
||||
# Overflow check in YulUtilFunction::overflowCheckedIntMulFunctions
|
||||
if type_bits > n_bits / 2:
|
||||
overflow_check = ISZERO(OR(ISZERO(X), EQ(Y, DIV(product, X))))
|
||||
else:
|
||||
overflow_check = ISZERO(EQ(product, product_raw))
|
||||
|
||||
rule.check(overflow_check != 0, actual_overflow)
|
||||
|
||||
type_bits *= 2
|
41
test/formal/signed_integer_cleanup_function.py
Normal file
41
test/formal/signed_integer_cleanup_function.py
Normal file
@ -0,0 +1,41 @@
|
||||
from opcodes import SIGNEXTEND
|
||||
from rule import Rule
|
||||
from util import BVSignedCleanupFunction, BVSignedUpCast
|
||||
from z3 import BitVec, BitVecVal, Concat
|
||||
|
||||
"""
|
||||
Overflow checked signed integer multiplication.
|
||||
"""
|
||||
|
||||
n_bits = 256
|
||||
|
||||
# Check that YulUtilFunction::cleanupFunction cleanup matches BVSignedCleanupFunction
|
||||
for type_bits in range(8,256,8):
|
||||
|
||||
rule = Rule()
|
||||
|
||||
# Input vars
|
||||
X = BitVec('X', n_bits)
|
||||
arg = BitVecVal(type_bits / 8 - 1, n_bits)
|
||||
|
||||
cleaned_reference = BVSignedCleanupFunction(X, type_bits)
|
||||
cleaned = SIGNEXTEND(arg, X)
|
||||
|
||||
rule.check(cleaned, cleaned_reference)
|
||||
|
||||
|
||||
# Check that BVSignedCleanupFunction properly cleans up values.
|
||||
for type_bits in range(8,256,8):
|
||||
|
||||
rule = Rule()
|
||||
|
||||
# Input vars
|
||||
X_short = BitVec('X', type_bits)
|
||||
dirt = BitVec('dirt', n_bits - type_bits)
|
||||
|
||||
X = BVSignedUpCast(X_short, n_bits)
|
||||
X_dirty = Concat(dirt, X_short)
|
||||
X_cleaned = BVSignedCleanupFunction(X_dirty, type_bits)
|
||||
|
||||
|
||||
rule.check(X, X_cleaned)
|
40
test/formal/unsigned_integer_cleanup_function.py
Normal file
40
test/formal/unsigned_integer_cleanup_function.py
Normal file
@ -0,0 +1,40 @@
|
||||
from opcodes import AND
|
||||
from rule import Rule
|
||||
from util import BVUnsignedCleanupFunction, BVUnsignedUpCast
|
||||
from z3 import BitVec, BitVecVal, Concat
|
||||
|
||||
"""
|
||||
Overflow checked unsigned integer multiplication.
|
||||
"""
|
||||
|
||||
n_bits = 256
|
||||
|
||||
# Check that YulUtilFunction::cleanupFunction cleanup matches BVUnsignedCleanupFunction
|
||||
for type_bits in range(8,256,8):
|
||||
|
||||
rule = Rule()
|
||||
|
||||
# Input vars
|
||||
X = BitVec('X', n_bits)
|
||||
mask = BitVecVal((1 << type_bits) - 1, n_bits)
|
||||
|
||||
cleaned_reference = BVUnsignedCleanupFunction(X, type_bits)
|
||||
cleaned = AND(X, mask)
|
||||
|
||||
rule.check(cleaned, cleaned_reference)
|
||||
|
||||
# Check that BVUnsignedCleanupFunction properly cleans up values.
|
||||
for type_bits in range(8,256,8):
|
||||
|
||||
rule = Rule()
|
||||
|
||||
# Input vars
|
||||
X_short = BitVec('X', type_bits)
|
||||
dirt = BitVec('dirt', n_bits - type_bits)
|
||||
|
||||
X = BVUnsignedUpCast(X_short, n_bits)
|
||||
X_dirty = Concat(dirt, X_short)
|
||||
X_cleaned = BVUnsignedCleanupFunction(X_dirty, type_bits)
|
||||
|
||||
|
||||
rule.check(X, X_cleaned)
|
@ -25,3 +25,18 @@ def BVSignedMax(type_bits, n_bits):
|
||||
def BVSignedMin(type_bits, n_bits):
|
||||
assert type_bits <= n_bits
|
||||
return BitVecVal(-(1 << (type_bits - 1)), n_bits)
|
||||
|
||||
def BVSignedCleanupFunction(x, type_bits):
|
||||
assert x.size() >= type_bits
|
||||
sign_mask = BitVecVal(1, x.size()) << (type_bits - 1)
|
||||
bit_mask = (BitVecVal(1, x.size()) << type_bits) - 1
|
||||
return If(
|
||||
x & sign_mask == 0,
|
||||
x & bit_mask,
|
||||
x | ~bit_mask
|
||||
)
|
||||
|
||||
def BVUnsignedCleanupFunction(x, type_bits):
|
||||
assert x.size() >= type_bits
|
||||
bit_mask = (BitVecVal(1, x.size()) << type_bits) - 1
|
||||
return x & bit_mask
|
||||
|
@ -18,10 +18,10 @@ contract C {
|
||||
// EVMVersion: >homestead
|
||||
// ----
|
||||
// h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324
|
||||
// gas irOptimized: 180726
|
||||
// gas irOptimized: 180829
|
||||
// gas legacy: 184921
|
||||
// gas legacyOptimized: 181506
|
||||
// i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224
|
||||
// gas irOptimized: 112453
|
||||
// gas irOptimized: 112464
|
||||
// gas legacy: 115460
|
||||
// gas legacyOptimized: 112990
|
||||
|
@ -35,12 +35,12 @@ contract c {
|
||||
}
|
||||
// ----
|
||||
// test() -> 0x02000202
|
||||
// gas irOptimized: 4649903
|
||||
// gas legacy: 4578320
|
||||
// gas legacyOptimized: 4548312
|
||||
// gas irOptimized: 4649835
|
||||
// gas legacy: 4578446
|
||||
// gas legacyOptimized: 4548309
|
||||
// storageEmpty -> 1
|
||||
// clear() -> 0, 0
|
||||
// gas irOptimized: 4477229
|
||||
// gas irOptimized: 4477223
|
||||
// gas legacy: 4410748
|
||||
// gas legacyOptimized: 4382489
|
||||
// storageEmpty -> 1
|
||||
|
@ -13,6 +13,6 @@ contract c {
|
||||
|
||||
// ----
|
||||
// test(uint256[2][]): 32, 3, 7, 8, 9, 10, 11, 12 -> 10
|
||||
// gas irOptimized: 689768
|
||||
// gas irOptimized: 689759
|
||||
// gas legacy: 686268
|
||||
// gas legacyOptimized: 685688
|
||||
|
@ -17,7 +17,7 @@ contract c {
|
||||
}
|
||||
// ----
|
||||
// test() -> 4, 5
|
||||
// gas irOptimized: 238692
|
||||
// gas irOptimized: 238623
|
||||
// gas legacy: 238736
|
||||
// gas legacyOptimized: 237159
|
||||
// storageEmpty -> 1
|
||||
|
@ -19,6 +19,6 @@ contract c {
|
||||
// compileToEwasm: also
|
||||
// ----
|
||||
// test() -> 0xffffffff, 0x0000000000000000000000000a00090008000700060005000400030002000100, 0x0000000000000000000000000000000000000000000000000000000000000000
|
||||
// gas irOptimized: 124817
|
||||
// gas legacy: 186028
|
||||
// gas legacyOptimized: 165692
|
||||
// gas irOptimized: 124910
|
||||
// gas legacy: 187414
|
||||
// gas legacyOptimized: 165659
|
||||
|
@ -42,6 +42,6 @@ contract c {
|
||||
// test2(uint256[][2]): 0x20, 0x40, 0x40, 2, 23, 42 -> 2, 65
|
||||
// gas irOptimized: 157567
|
||||
// test3(uint256[2][]): 0x20, 2, 23, 42, 23, 42 -> 2, 65
|
||||
// gas irOptimized: 134633
|
||||
// gas irOptimized: 134644
|
||||
// test4(uint256[2][2]): 23, 42, 23, 42 -> 65
|
||||
// gas irOptimized: 111271
|
||||
|
@ -17,4 +17,4 @@ contract C {
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// f((uint128,uint64,uint128)[]): 0x20, 3, 0, 0, 12, 0, 11, 0, 10, 0, 0 -> 10, 11, 12
|
||||
// gas irOptimized: 119740
|
||||
// gas irOptimized: 119737
|
||||
|
@ -33,9 +33,9 @@ contract test {
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// constructor()
|
||||
// gas irOptimized: 441142
|
||||
// gas legacy: 755907
|
||||
// gas legacyOptimized: 538354
|
||||
// gas irOptimized: 438352
|
||||
// gas legacy: 750723
|
||||
// gas legacyOptimized: 536620
|
||||
// encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0
|
||||
// encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg=="
|
||||
// encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8="
|
||||
@ -51,10 +51,10 @@ contract test {
|
||||
// encode_no_asm(bytes): 0x20, 5, "fooba" -> 0x20, 8, "Zm9vYmE="
|
||||
// encode_no_asm(bytes): 0x20, 6, "foobar" -> 0x20, 8, "Zm9vYmFy"
|
||||
// encode_inline_asm_large()
|
||||
// gas irOptimized: 1382042
|
||||
// gas legacy: 1646033
|
||||
// gas legacyOptimized: 1206033
|
||||
// gas irOptimized: 1387042
|
||||
// gas legacy: 1688033
|
||||
// gas legacyOptimized: 1205033
|
||||
// encode_no_asm_large()
|
||||
// gas irOptimized: 3311099
|
||||
// gas legacy: 4723077
|
||||
// gas legacyOptimized: 2909077
|
||||
// gas irOptimized: 3316099
|
||||
// gas legacy: 4765077
|
||||
// gas legacyOptimized: 2908077
|
||||
|
@ -33,10 +33,10 @@ contract test {
|
||||
}
|
||||
// ----
|
||||
// constructor()
|
||||
// gas irOptimized: 422763
|
||||
// gas legacy: 654526
|
||||
// gas legacyOptimized: 474842
|
||||
// gas irOptimized: 430305
|
||||
// gas legacy: 649335
|
||||
// gas legacyOptimized: 473132
|
||||
// prb_pi() -> 3141592656369545286
|
||||
// gas irOptimized: 57478
|
||||
// gas legacy: 98903
|
||||
// gas legacy: 103112
|
||||
// gas legacyOptimized: 75735
|
||||
|
@ -297,5 +297,5 @@ contract Test {
|
||||
// verifyTx() -> true
|
||||
// ~ emit Verified(string): 0x20, 0x16, "Successfully verified."
|
||||
// gas irOptimized: 95261
|
||||
// gas legacy: 113239
|
||||
// gas legacy: 116473
|
||||
// gas legacyOptimized: 83670
|
||||
|
@ -49,9 +49,9 @@ contract test {
|
||||
}
|
||||
// ----
|
||||
// constructor()
|
||||
// gas irOptimized: 675980
|
||||
// gas legacy: 1101298
|
||||
// gas legacyOptimized: 743666
|
||||
// gas irOptimized: 670586
|
||||
// gas legacy: 1096108
|
||||
// gas legacyOptimized: 741962
|
||||
// toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0
|
||||
// gas irOptimized: 22660
|
||||
// gas legacy: 23190
|
||||
@ -69,6 +69,6 @@ contract test {
|
||||
// gas legacy: 31621
|
||||
// gas legacyOptimized: 27914
|
||||
// benchmark(string,bytes32): 0x40, 0x0842021, 8, "solidity" -> 0x2020
|
||||
// gas irOptimized: 2017767
|
||||
// gas legacy: 4294510
|
||||
// gas legacyOptimized: 2327982
|
||||
// gas irOptimized: 2017770
|
||||
// gas legacy: 4294552
|
||||
// gas legacyOptimized: 2327981
|
||||
|
@ -21,6 +21,6 @@ contract A {
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// f(), 10 ether -> 3007, 3008, 3009
|
||||
// gas irOptimized: 268645
|
||||
// gas legacy: 402016
|
||||
// gas legacyOptimized: 288087
|
||||
// gas irOptimized: 255997
|
||||
// gas legacy: 387712
|
||||
// gas legacyOptimized: 283266
|
||||
|
@ -5,6 +5,9 @@ contract C {
|
||||
function g(int8 a, int8 b) public pure returns (int8 x) {
|
||||
x = a * b;
|
||||
}
|
||||
function h(int160 a, int160 b) public pure returns (int160 x) {
|
||||
x = a * b;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileToEwasm: also
|
||||
@ -15,6 +18,9 @@ contract C {
|
||||
// f(int256,int256): 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 2 -> 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
|
||||
// f(int256,int256): 0x4000000000000000000000000000000000000000000000000000000000000000, 2 -> FAILURE, hex"4e487b71", 0x11
|
||||
// f(int256,int256): 2, 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
|
||||
// f(int256,int256): 2, 0x4000000000000000000000000000000000000000000000000000000000000000 -> FAILURE, hex"4e487b71", 0x11
|
||||
// f(int256,int256): -1, 0x8000000000000000000000000000000000000000000000000000000000000000 -> FAILURE, hex"4e487b71", 0x11
|
||||
// f(int256,int256): 0x8000000000000000000000000000000000000000000000000000000000000000, -1 -> FAILURE, hex"4e487b71", 0x11
|
||||
// f(int256,int256): 2, 0x4000000000000000000000000000000000000000000000000000000000000000 -> FAILURE, hex"4e487b71", 0x11 # positive, negative #
|
||||
// f(int256,int256): 2, 0x4000000000000000000000000000000000000000000000000000000000000000 -> FAILURE, hex"4e487b71", 0x11 # positive, negative #
|
||||
// f(int256,int256): 2, 0x4000000000000000000000000000000000000000000000000000000000000000 -> FAILURE, hex"4e487b71", 0x11 # positive, negative #
|
||||
@ -61,3 +67,18 @@ contract C {
|
||||
// g(int8,int8): -64, -2 -> FAILURE, hex"4e487b71", 0x11
|
||||
// g(int8,int8): -2, -63 -> 126
|
||||
// g(int8,int8): -2, -64 -> FAILURE, hex"4e487b71", 0x11
|
||||
// h(int160,int160): -1, 1 -> -1
|
||||
// h(int160,int160): 1, -1 -> -1
|
||||
// h(int160,int160): -1, 2 -> -2
|
||||
// h(int160,int160): 2, -1 -> -2
|
||||
// h(int160,int160): -1, 0xFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000 -> FAILURE, hex"4e487b71", 0x11
|
||||
// h(int160,int160): -1, 0xFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000 -> FAILURE, hex"4e487b71", 0x11
|
||||
// h(int160,int160): 0xFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000, -1 -> FAILURE, hex"4e487b71", 0x11
|
||||
// h(int160,int160): 0x0000000000000000000000004000000000000000000000000000000000000000, -2 -> 0xFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000
|
||||
// h(int160,int160): -2, 0x0000000000000000000000004000000000000000000000000000000000000000 -> 0xFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000
|
||||
// h(int160,int160): -2, 0x0000000000000000000000004000000000000000000000000000000000000001 -> FAILURE, hex"4e487b71", 0x11
|
||||
// h(int160,int160): 0x0000000000000000000000004000000000000000000000000000000000000001, -2 -> FAILURE, hex"4e487b71", 0x11
|
||||
// h(int160,int160): 0x0000000000000000000000004000000000000000000000000000000000000001, 2 -> FAILURE, hex"4e487b71", 0x11
|
||||
// h(int160,int160): 2, 0x0000000000000000000000004000000000000000000000000000000000000001 -> FAILURE, hex"4e487b71", 0x11
|
||||
// h(int160,int160): 0x0000000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 2 -> 0x0000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
|
||||
// h(int160,int160): 2, 0x0000000000000000000000004000000000000000000000000000000000000001 -> FAILURE, hex"4e487b71", 0x11
|
||||
|
Loading…
Reference in New Issue
Block a user