Merge pull request #8464 from aarlt/end-to-end-verified

[test] Extraction of 292 tests from SolidityEndToEndTest.cpp
This commit is contained in:
chriseth 2020-03-19 14:42:04 +01:00 committed by GitHub
commit 8834b1acaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
296 changed files with 6441 additions and 6362 deletions

View File

@ -0,0 +1,22 @@
BASE_PATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 || exit ; pwd -P )"
mkdir -p build
cd build || exit
cmake ../../../
make soltest
cd test/ || exit
echo "running soltest on 'semanticTests/extracted'..."
./soltest --color_output=false --log_level=test_suite -t semanticTests/extracted/ -- --testpath ${BASE_PATH}/../../test --no-smt --evmonepath /Users/alex/evmone/lib/libevmone.dylib --show-messages --show-metadata > ${BASE_PATH}/extracted-tests.trace
echo "running soltest on 'semanticTests/extracted'... done"
cd $BASE_PATH || exit
git clone git@github.com:ethereum/solidity.git solidity-develop
cd solidity-develop || exit
mkdir -p build
cd build || exit
cmake ..
make soltest
cd test/ || exit
echo "running soltest on 'SolidityEndToEndTest'..."
./soltest --color_output=false --log_level=test_suite -t SolidityEndToEndTest/ -- --testpath ${BASE_PATH}/solidity-develop/test --no-smt --evmonepath /Users/alex/evmone/lib/libevmone.dylib --show-messages --show-metadata > ${BASE_PATH}/endToEndExtraction-tests.trace
echo "running soltest on 'SolidityEndToEndTest'... done"

View File

@ -0,0 +1,183 @@
#!/usr/bin/env python3
# pylint: disable=consider-using-enumerate, import-error
import re
import os
import sys
import getopt
import tempfile
from getkey import getkey
def parse_call(call):
function = ''
arguments = ""
results = ""
search = re.search(r'// (.*):(.*)\s->\s(.*)', call, re.MULTILINE | re.DOTALL)
if search:
function = search.group(1)
arguments = search.group(2)
results = search.group(3)
if results.find("#") != -1:
results = results[:results.find("#")]
else:
search = re.search(r'// (.*)(.*)\s->\s(.*)', call, re.MULTILINE | re.DOTALL)
if search:
function = search.group(1)
arguments = search.group(2)
results = search.group(3)
if results.find("#") != -1:
results = results[:results.find("#")]
if function.find("wei") >= 0:
function = function[:function.find(",")]
return function.strip(), arguments.strip(), results.strip()
def colorize(left, right, id):
red = "\x1b[31m"
yellow = "\x1b[33m"
reset = "\x1b[0m"
colors = [red, yellow]
color = colors[id % len(colors)]
function, arguments, results = parse_call(right)
left = left.replace("compileAndRun", color + "compileAndRun" + reset)
right = right.replace("constructor", color + "constructor" + reset)
if function:
left = left.replace(function, color + function + reset)
right = right.replace(function, color + function + reset)
if left.find(function):
bottom = " " * (left.find(function) - 4) + right
else:
bottom = " " + right
return " " + left + "\n" + bottom # " {:<90} {:<90}\n{}".format(left, right, bottom)
def get_checks(content, sol_file_path):
constructors = []
checks = []
for line in content.split("\n"):
line = line.strip()
if line.startswith("compileAndRun"):
constructors.append(line)
if line.startswith("ABI_CHECK") or line.startswith("BOOST_REQUIRE"):
checks.append(line)
sol_file = open(sol_file_path, "r")
sol_constructors = []
sol_checks = []
inside_expectations = False
for line in sol_file.readlines():
if line.startswith("// constructor()"):
sol_constructors.append(line)
elif inside_expectations and line.startswith("// "):
sol_checks.append(line)
if line.startswith("// ----"):
inside_expectations = True
sol_file.close()
if len(constructors) == len(sol_constructors) == 1:
checks.insert(0, constructors[0])
sol_checks.insert(0, sol_constructors[0])
return checks, sol_checks
def show_test(name, content, sol_file_path, current_test, test_count):
cpp_file = tempfile.NamedTemporaryFile(delete=False)
cpp_file.write(content.encode())
cpp_file.close()
os.system("clear")
print(str(current_test) + " / " + str(test_count) + " - " + name + "\n")
diff_env = os.getenv('DIFF', "/usr/local/bin/colordiff -a -d -w -y -W 200 ")
os.system(diff_env + " " + cpp_file.name + " " + sol_file_path)
os.unlink(cpp_file.name)
print("\n")
checks, sol_checks = get_checks(content, sol_file_path)
if len(checks) == len(sol_checks):
for i in range(0, len(checks)):
print(colorize(checks[i].strip(), sol_checks[i].strip(), i))
else:
print("warning: check count not matching. this should not happen!")
what = ""
print("\nContinue? (ENTER) Abort? (ANY OTHER KEY)")
while what != '\n':
what = getkey()
if what != '\n':
sys.exit(0)
print()
def get_tests(e2e_path):
tests = []
for f in os.listdir(e2e_path):
if f.endswith(".sol"):
tests.append(f.replace(".sol", ""))
return tests
def process_input_file(e2e_path, input_file, interactive):
tests = get_tests(e2e_path)
cpp_file = open(input_file, "r")
inside_test = False
test_name = ""
inside_extracted_test = False
new_lines = 0
count = 0
test_content = ""
for line in cpp_file.readlines():
test = re.search(r'BOOST_AUTO_TEST_CASE\((.*)\)', line, re.M | re.I)
if test:
test_name = test.group(1)
inside_test = True
inside_extracted_test = inside_test & (test_name in tests)
if inside_extracted_test:
count = count + 1
if interactive and inside_extracted_test:
test_content = test_content + line
if not inside_extracted_test:
if line == "\n":
new_lines = new_lines + 1
else:
new_lines = 0
if not interactive and new_lines <= 1:
sys.stdout.write(line)
if line == "}\n":
if interactive and inside_extracted_test:
show_test(test_name, test_content.strip(), e2e_path + "/" + test_name + ".sol", count, len(tests))
test_content = ""
inside_test = False
cpp_file.close()
sys.stdout.flush()
def main(argv):
interactive = False
input_file = None
try:
opts, args = getopt.getopt(argv, "if:")
except getopt.GetoptError:
print("./remove-testcases.py [-i] [-f <full path to SolidityEndToEndTest.cpp>]")
sys.exit(1)
for opt, arg in opts:
if opt == '-i':
interactive = True
elif opt in '-f':
input_file = arg
base_path = os.path.dirname(__file__)
if not input_file:
input_file = base_path + "/../../test/libsolidity/SolidityEndToEndTest.cpp"
e2e_path = base_path + "/../../test/libsolidity/semanticTests/extracted"
process_input_file(e2e_path, input_file, interactive)
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,215 @@
#!/usr/bin/env python3
#
# - SolidityEndToEndTest.trace was created with soltest with the following command on
# ./soltest --color_output=false --log_level=test_suite -t SolidityEndToEndTest/ -- --no-smt
# --evmonepath /Users/alex/evmone/lib/libevmone.dylib --show-messages > SolidityEndToEndTest.trace
# - a trace of the semantic tests can be created by using
# ./soltest --color_output=false --log_level=test_suite -t semanticTests/extracted/ -- --no-smt
# --evmonepath /Users/alex/evmone/lib/libevmone.dylib --show-messages > semanticTests.trace
#
# verify-testcases.py will compare both traces. If these traces are identical, the extracted tests where
# identical with the tests specified in SolidityEndToEndTest.cpp.
#
# pylint: disable=too-many-instance-attributes
import re
import os
import sys
import getopt
import json
class Trace:
def __init__(self, kind, parameter):
self.kind = kind
self.parameter = parameter
self._input = ""
self._output = ""
self.value = ""
self.result = ""
self.gas = ""
def get_input(self):
return self._input
def set_input(self, input):
if self.kind == "create":
# remove cbor encoded metadata from bytecode
length = int(input[-4:], 16) * 2
self._input = input[:len(input) - length - 4]
def get_output(self):
return self._output
def set_output(self, output):
if self.kind == "create":
# remove cbor encoded metadata from bytecode
length = int(output[-4:], 16) * 2
self._output = output[:len(output) - length - 4]
def __str__(self):
# we ignore the used gas
result = str(
"kind='" + self.kind + "' parameter='" + self.parameter + "' input='" + self._input +
"' output='" + self._output + "' value='" + self.value + "' result='" + self.result + "'"
)
return result
class TestCase:
def __init__(self, name):
self.name = name
self.metadata = None
self.traces = []
def add_trace(self, kind, parameter):
trace = Trace(kind, parameter)
self.traces.append(trace)
return trace
class TraceAnalyser:
def __init__(self, file):
self.file = file
self.tests = {}
self.ready = False
def analyse(self):
trace_file = open(self.file, "r")
trace = None
test_case = None
for line in trace_file.readlines():
test = re.search(r'Entering test case "(.*)"', line, re.M | re.I)
if test:
test_name = test.group(1)
test_case = TestCase(test_name)
self.tests[test_name] = test_case
metadata = re.search(r'\s*metadata:\s*(.*)$', line, re.M | re.I)
if metadata:
test_case.metadata = json.loads(metadata.group(1))
del test_case.metadata["sources"]
del test_case.metadata["compiler"]["version"]
create = re.search(r'CREATE\s*([a-fA-F0-9]*):', line, re.M | re.I)
if create:
trace = test_case.add_trace("create", create.group(1))
call = re.search(r'CALL\s*([a-fA-F0-9]*)\s*->\s*([a-fA-F0-9]*):', line, re.M | re.I)
if call:
trace = test_case.add_trace("call", call.group(1)) # + "->" + call.group(2))
if not create and not call:
self.parse_parameters(line, trace)
trace_file.close()
print(self.file + ":", len(self.tests), "test-cases.")
self.ready = True
@staticmethod
def parse_parameters(line, trace):
input = re.search(r'\s*in:\s*([a-fA-F0-9]*)', line, re.M | re.I)
if input:
trace.input = input.group(1)
output = re.search(r'\s*out:\s*([a-fA-F0-9]*)', line, re.M | re.I)
if output:
trace.output = output.group(1)
result = re.search(r'\s*result:\s*([a-fA-F0-9]*)', line, re.M | re.I)
if result:
trace.result = result.group(1)
gas_used = re.search(r'\s*gas\sused:\s*([a-fA-F0-9]*)', line, re.M | re.I)
if gas_used:
trace.gas = gas_used.group(1)
value = re.search(r'\s*value:\s*([a-fA-F0-9]*)', line, re.M | re.I)
if value:
trace.value = value.group(1)
def diff(self, analyser):
if not self.ready:
self.analyse()
if not analyser.ready:
analyser.analyse()
intersection = set(self.tests.keys()) & set(analyser.tests.keys())
mismatches = set()
for test_name in intersection:
left = self.tests[test_name]
right = analyser.tests[test_name]
if json.dumps(left.metadata) != json.dumps(right.metadata):
mismatches.add(
(test_name, "metadata where different: " + json.dumps(left.metadata) + " != " + json.dumps(
right.metadata)))
if len(left.traces) != len(right.traces):
mismatches.add((test_name, "trace count are different: " + str(len(left.traces)) +
" != " + str(len(right.traces))))
else:
self.check_traces(test_name, left, right, mismatches)
for mismatch in mismatches:
print(mismatch[0])
print(mismatch[1])
print(len(intersection), "test-cases - ", len(mismatches), " mismatche(s)")
def check_traces(self, test_name, left, right, mismatches):
for trace_id in range(0, len(left.traces)):
left_trace = left.traces[trace_id]
right_trace = right.traces[trace_id]
assert (left_trace.kind == right_trace.kind)
if str(left_trace) != str(right_trace):
mismatch_info = " " + str(left_trace) + "\n"
mismatch_info += " " + str(right_trace) + "\n"
mismatch_info += " "
for ch in range(0, len(str(left_trace))):
if ch < len(str(left_trace)) and ch < len(str(right_trace)):
if str(left_trace)[ch] != str(right_trace)[ch]:
mismatch_info += "|"
else:
mismatch_info += " "
else:
mismatch_info += "|"
mismatch_info += "\n"
mismatches.add((test_name, mismatch_info))
def main(argv):
extracted_tests_trace_file = None
end_to_end_trace_file = None
try:
opts, args = getopt.getopt(argv, "s:e:")
except getopt.GetoptError:
print("verify-testcases.py [-s <path to semantic-trace>] [-e <path to endToEndExtraction-trace>]")
sys.exit(2)
for opt, arg in opts:
if opt in '-s':
extracted_tests_trace_file = arg
elif opt in '-e':
end_to_end_trace_file = arg
base_path = os.path.dirname(__file__)
if not extracted_tests_trace_file:
extracted_tests_trace_file = base_path + "/extracted-tests.trace"
if not end_to_end_trace_file:
end_to_end_trace_file = base_path + "/endToEndExtraction-tests.trace"
for f in [extracted_tests_trace_file, end_to_end_trace_file]:
if not os.path.isfile(f):
print("trace file '" + f + "' not found. aborting.")
sys.exit(1)
if not os.path.isfile(extracted_tests_trace_file):
print("semantic trace file '" + extracted_tests_trace_file + "' not found. aborting.")
sys.exit(1)
semantic_trace = TraceAnalyser(extracted_tests_trace_file)
end_to_end_trace = TraceAnalyser(end_to_end_trace_file)
semantic_trace.diff(end_to_end_trace)
if __name__ == "__main__":
main(sys.argv[1:])

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
contract C {
function f(bytes calldata data) external pure returns (uint256[] memory) {
return abi.decode(data, (uint256[]));
}
}
// ----
// f(bytes): 0x20, 0xc0, 0x20, 0x4, 0x3, 0x4, 0x5, 0x6 -> 0x20, 0x4, 0x3, 0x4, 0x5, 0x6

View File

@ -0,0 +1,12 @@
contract C {
function f(bytes calldata data)
external
pure
returns (uint256[2][3] memory)
{
return abi.decode(data, (uint256[2][3]));
}
}
// ----
// f(bytes): 0x20, 0xc0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 -> 1, 2, 3, 4, 5, 6

View File

@ -0,0 +1,15 @@
pragma experimental ABIEncoderV2;
contract C {
function f(bytes calldata data)
external
pure
returns (uint256[2][3] memory)
{
return abi.decode(data, (uint256[2][3]));
}
}
// ----
// f(bytes): 0x20, 0xc0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 -> 1, 2, 3, 4, 5, 6

View File

@ -0,0 +1,8 @@
contract C {
function f(bytes memory data) public pure returns (uint256) {
return abi.decode(data, (uint256));
}
}
// ----
// f(bytes): 0x20, 0x20, 0x21 -> 33

View File

@ -0,0 +1,22 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256[] b;
}
function f() public pure returns (S memory) {
S memory s;
s.a = 8;
s.b = new uint256[](3);
s.b[0] = 9;
s.b[1] = 10;
s.b[2] = 11;
return abi.decode(abi.encode(s), (S));
}
}
// ----
// f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb

View File

@ -0,0 +1,16 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256[] b;
}
function f(bytes calldata data) external pure returns (S memory) {
return abi.decode(data, (S));
}
}
// ----
// f(bytes): 0x20, 0xe0, 0x20, 0x21, 0x40, 0x3, 0xa, 0xb, 0xc -> 0x20, 0x21, 0x40, 0x3, 0xa, 0xb, 0xc

View File

@ -0,0 +1,24 @@
pragma experimental ABIEncoderV2;
contract C {
bytes data;
struct S {
uint256 a;
uint256[] b;
}
function f() public returns (S memory) {
S memory s;
s.a = 8;
s.b = new uint256[](3);
s.b[0] = 9;
s.b[1] = 10;
s.b[2] = 11;
data = abi.encode(s);
return abi.decode(data, (S));
}
}
// ----
// f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb

View File

@ -0,0 +1,36 @@
contract C {
function f0() public returns (bytes memory) {
return abi.encode();
}
function f1() public returns (bytes memory) {
return abi.encode(1, 2);
}
function f2() public returns (bytes memory) {
string memory x = "abc";
return abi.encode(1, x, 2);
}
function f3() public returns (bytes memory r) {
// test that memory is properly allocated
string memory x = "abc";
r = abi.encode(1, x, 2);
bytes memory y = "def";
require(y[0] == "d");
y[0] = "e";
require(y[0] == "e");
}
function f4() public returns (bytes memory) {
bytes4 x = "abcd";
return abi.encode(bytes2(x));
}
}
// ----
// f0() -> 0x20, 0x0
// f1() -> 0x20, 0x40, 0x1, 0x2
// f2() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc"
// f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc"
// f4() -> 0x20, 0x20, "ab"

View File

@ -0,0 +1,26 @@
contract C {
bool x;
function c(uint256 a, uint256[] memory b) public {
require(a == 5);
require(b.length == 2);
require(b[0] == 6);
require(b[1] == 7);
x = true;
}
function f() public returns (bool) {
uint256 a = 5;
uint256[] memory b = new uint256[](2);
b[0] = 6;
b[1] = 7;
(bool success, ) = address(this).call(
abi.encodeWithSignature("c(uint256,uint256[])", a, b)
);
require(success);
return x;
}
}
// ----
// f() -> true

View File

@ -0,0 +1,9 @@
contract C {
function f() public pure returns (uint256, bytes memory) {
bytes memory arg = "abcdefg";
return abi.decode(abi.encode(uint256(33), arg), (uint256, bytes));
}
}
// ----
// f() -> 0x21, 0x40, 0x7, "abcdefg"

View File

@ -0,0 +1,13 @@
// Tests that this will not end up using a "bytes0" type
// (which would assert)
pragma experimental ABIEncoderV2;
contract C {
function f() public pure returns (bytes memory, bytes memory) {
return (abi.encode(""), abi.encodePacked(""));
}
}
// ----
// f() -> 0x40, 0xa0, 0x40, 0x20, 0x0, 0x0

View File

@ -0,0 +1,9 @@
// Tests that rational numbers (even negative ones) are encoded properly.
contract C {
function f() public pure returns (bytes memory) {
return abi.encode(1, -2);
}
}
// ----
// f() -> 0x20, 0x40, 0x1, -2

View File

@ -0,0 +1,12 @@
// Tests that rational numbers (even negative ones) are encoded properly.
pragma experimental ABIEncoderV2;
contract C {
function f() public pure returns (bytes memory) {
return abi.encode(1, -2);
}
}
// ----
// f() -> 0x20, 0x40, 0x1, -2

View File

@ -0,0 +1,53 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256[] b;
}
function f0() public pure returns (bytes memory) {
return abi.encode();
}
function f1() public pure returns (bytes memory) {
return abi.encode(1, 2);
}
function f2() public pure returns (bytes memory) {
string memory x = "abc";
return abi.encode(1, x, 2);
}
function f3() public pure returns (bytes memory r) {
// test that memory is properly allocated
string memory x = "abc";
r = abi.encode(1, x, 2);
bytes memory y = "def";
require(y[0] == "d");
y[0] = "e";
require(y[0] == "e");
}
S s;
function f4() public returns (bytes memory r) {
string memory x = "abc";
s.a = 7;
s.b.push(2);
s.b.push(3);
r = abi.encode(1, x, s, 2);
bytes memory y = "def";
require(y[0] == "d");
y[0] = "e";
require(y[0] == "e");
}
}
// ----
// f0() -> 0x20, 0x0
// f1() -> 0x20, 0x40, 0x1, 0x2
// f2() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc"
// f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc"
// f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3

View File

@ -0,0 +1,30 @@
contract Base {
uint256 dataBase;
function getViaBase() public returns (uint256 i) {
return dataBase;
}
}
contract Derived is Base {
uint256 dataDerived;
function setData(uint256 base, uint256 derived) public returns (bool r) {
dataBase = base;
dataDerived = derived;
return true;
}
function getViaDerived() public returns (uint256 base, uint256 derived) {
base = dataBase;
derived = dataDerived;
}
}
// ====
// compileViaYul: also
// ----
// setData(uint256,uint256): 1, 2 -> true
// getViaBase() -> 1
// getViaDerived() -> 1, 2

View File

@ -0,0 +1,6 @@
contract Lotto {
uint256 public constant ticketPrice = 555;
}
// ----
// ticketPrice() -> 555

View File

@ -0,0 +1,8 @@
contract Lotto {
uint256 public ticketPrice = 500;
}
// ====
// compileViaYul: also
// ----
// ticketPrice() -> 500

View File

@ -0,0 +1,12 @@
contract C {
function test() public returns (uint256) {
// Note that this only works because computation on literals is done using
// unbounded integers.
if ((2**255 + 2**255) % 7 != addmod(2**255, 2**255, 7)) return 1;
if ((2**255 + 2**255) % 7 != addmod(2**255, 2**255, 7)) return 2;
return 0;
}
}
// ----
// test() -> 0

View File

@ -0,0 +1,24 @@
contract C {
function f(uint256 d) public pure returns (uint256) {
addmod(1, 2, d);
return 2;
}
function g(uint256 d) public pure returns (uint256) {
mulmod(1, 2, d);
return 2;
}
function h() public pure returns (uint256) {
mulmod(0, 1, 2);
mulmod(1, 0, 2);
addmod(0, 1, 2);
addmod(1, 0, 2);
return 2;
}
}
// ----
// f(uint256): 0 -> FAILURE
// g(uint256): 0 -> FAILURE
// h() -> 2

View File

@ -0,0 +1,24 @@
contract C {
function balance() public returns (uint256) {
return 1;
}
function transfer(uint256 amount) public returns (uint256) {
return amount;
}
}
contract D {
function f() public returns (uint256) {
return (new C()).balance();
}
function g() public returns (uint256) {
return (new C()).transfer(5);
}
}
// ----
// f() -> 1
// g() -> 5

View File

@ -0,0 +1,21 @@
contract c {
bytes8[] data1; // 4 per slot
bytes10[] data2; // 3 per slot
function test()
public
returns (bytes10 a, bytes10 b, bytes10 c, bytes10 d, bytes10 e)
{
data1 = new bytes8[](9);
for (uint256 i = 0; i < data1.length; ++i) data1[i] = bytes8(uint64(i));
data2 = data1;
a = data2[1];
b = data2[2];
c = data2[3];
d = data2[4];
e = data2[5];
}
}
// ----
// test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x05000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,15 @@
contract c {
uint256[4][] a;
uint256[10][] b;
uint256[][] c;
function test(uint256[2][] calldata d) external returns (uint256) {
a = d;
b = a;
c = b;
return c[1][1] | c[1][2] | c[1][3] | c[1][4];
}
}
// ----
// test(uint256[2][]): 32, 3, 7, 8, 9, 10, 11, 12 -> 10

View File

@ -0,0 +1,20 @@
// NOTE: This does not really test copying from storage to ABI directly,
// because it will always copy to memory first.
contract c {
int16[] x;
function test() public returns (int16[] memory) {
x.push(int16(-1));
x.push(int16(-1));
x.push(int16(8));
x.push(int16(-16));
x.push(int16(-2));
x.push(int16(6));
x.push(int16(8));
x.push(int16(-1));
return x;
}
}
// ----
// test() -> 0x20, 0x8, -1, -1, 8, -16, -2, 6, 8, -1

View File

@ -0,0 +1,14 @@
contract c {
uint256[9] data1;
uint256[] data2;
function test() public returns (uint256 x, uint256 y) {
data1[8] = 4;
data2 = data1;
x = data2.length;
y = data2[8];
}
}
// ----
// test() -> 9, 4

View File

@ -0,0 +1,17 @@
contract c {
uint256[40] data1;
uint256[20] data2;
function test() public returns (uint256 x, uint256 y) {
data1[30] = 4;
data1[2] = 7;
data1[3] = 9;
data2[3] = 8;
data1 = data2;
x = data1[3];
y = data1[30]; // should be cleared
}
}
// ----
// test() -> 8, 0

View File

@ -0,0 +1,22 @@
// since the copy always copies whole slots, we have to make sure that the source size maxes
// out a whole slot and at the same time there are still elements left in the target at that point
contract c {
bytes8[4] data1; // fits into one slot
bytes10[6] data2; // 4 elements need two slots
function test() public returns (bytes10 r1, bytes10 r2, bytes10 r3) {
data1[0] = bytes8(uint64(1));
data1[1] = bytes8(uint64(2));
data1[2] = bytes8(uint64(3));
data1[3] = bytes8(uint64(4));
for (uint256 i = 0; i < data2.length; ++i)
data2[i] = bytes10(uint80(0xffff00 | (1 + i)));
data2 = data1;
r1 = data2[3];
r2 = data2[4];
r3 = data2[5];
}
}
// ----
// test() -> 0x04000000000000000000000000000000000000000000000000, 0x0, 0x0

View File

@ -0,0 +1,21 @@
contract c {
bytes8[9] data1; // 4 per slot
bytes17[10] data2; // 1 per slot, no offset counter
function test()
public
returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e)
{
for (uint256 i = 0; i < data1.length; ++i) data1[i] = bytes8(uint64(i));
data2[8] = data2[9] = bytes8(uint64(2));
data2 = data1;
a = data2[1];
b = data2[2];
c = data2[3];
d = data2[4];
e = data2[9];
}
}
// ----
// test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x0

View File

@ -0,0 +1,16 @@
contract c {
uint256[] data;
function test() public returns (uint256 x, uint256 l) {
data.push(7);
data.push(3);
x = data.length;
data.pop();
x = data.length;
data.pop();
l = data.length;
}
}
// ----
// test() -> 1, 0

View File

@ -0,0 +1,11 @@
contract c {
uint256[] data;
function test() public returns (bool) {
data.pop();
return true;
}
}
// ----
// test() -> FAILURE

View File

@ -0,0 +1,13 @@
// This tests that the compiler knows the correct size of the function on the stack.
contract c {
uint256[] data;
function test() public returns (uint256 x) {
x = 2;
data.pop;
x = 3;
}
}
// ----
// test() -> 3

View File

@ -0,0 +1,19 @@
contract c {
uint256[] data;
function test()
public
returns (uint256 x, uint256 y, uint256 z, uint256 l)
{
data.push(5);
x = data[0];
data.push(4);
y = data[1];
data.push(3);
l = data.length;
z = data[2];
}
}
// ----
// test() -> 5, 4, 3, 3

View File

@ -0,0 +1,16 @@
contract c {
uint80[] x;
function test() public returns (uint80, uint80, uint80, uint80) {
x.push(1);
x.push(2);
x.push(3);
x.push(4);
x.push(5);
x.pop();
return (x[0], x[1], x[2], x[3]);
}
}
// ----
// test() -> 1, 2, 3, 4

View File

@ -0,0 +1,23 @@
contract c {
struct S {
uint16 a;
uint16 b;
uint16[3] c;
uint16[] d;
}
S[] data;
function test() public returns (uint16, uint16, uint16, uint16) {
S memory s;
s.a = 2;
s.b = 3;
s.c[2] = 4;
s.d = new uint16[](4);
s.d[2] = 5;
data.push(s);
return (data[0].a, data[0].b, data[0].c[2], data[0].d[2]);
}
}
// ----
// test() -> 2, 3, 4, 5

View File

@ -0,0 +1,24 @@
contract C {
function f() public {
assert(false);
}
function g(bool val) public returns (bool) {
assert(val == true);
return true;
}
function h(bool val) public returns (bool) {
require(val);
return true;
}
}
// ====
// compileViaYul: also
// ----
// f() -> FAILURE
// g(bool): false -> FAILURE
// g(bool): true -> true
// h(bool): false -> FAILURE
// h(bool): true -> true

View File

@ -0,0 +1,10 @@
contract C {
uint256 constant x = 0x123 + 0x456;
function f() public returns (uint256) {
return x + 1;
}
}
// ----
// f() -> 0x57a

View File

@ -0,0 +1,13 @@
contract test {
constructor() public payable {}
function getBalance() public returns (uint256 balance) {
return address(this).balance;
}
}
// ====
// compileViaYul: also
// ----
// constructor(), 23 wei ->
// getBalance() -> 23

View File

@ -0,0 +1,21 @@
contract C {
function() returns (uint256) internal x;
function set() public {
C.x = g;
}
function g() public pure returns (uint256) {
return 2;
}
function h() public returns (uint256) {
return C.x();
}
}
// ----
// g() -> 2
// h() -> FAILURE
// set() ->
// h() -> 2

View File

@ -0,0 +1,24 @@
contract BaseBase {
uint256 m_a;
constructor(uint256 a) public {
m_a = a;
}
}
contract Base is BaseBase(7) {
constructor() public {
m_a *= m_a;
}
}
contract Derived is Base {
function getA() public returns (uint256 r) {
return m_a;
}
}
// ----
// getA() -> 49

View File

@ -0,0 +1,20 @@
contract C {
uint256 public x;
modifier run() {
for (uint256 i = 0; i < 10; i++) {
_;
break;
}
}
function f() public run {
uint256 k = x;
uint256 t = k + 1;
x = t;
}
}
// ----
// x() -> 0
// f() ->
// x() -> 1

View File

@ -0,0 +1,17 @@
contract c {
bytes data;
function test() public returns (uint256 x, uint256 y, uint256 l) {
data.push(0x07);
data.push(0x03);
x = data.length;
data.pop();
data.pop();
data.push(0x02);
y = data.length;
l = data.length;
}
}
// ----
// test() -> 2, 1, 1

View File

@ -0,0 +1,12 @@
contract c {
bytes data;
function test() public returns (bytes memory) {
for (uint256 i = 0; i < 33; i++) data.push(0x03);
for (uint256 j = 0; j < 4; j++) data.pop();
return data;
}
}
// ----
// test() -> 0x20, 29, 0x0303030303030303030303030303030303030303030303030303030303000000

View File

@ -0,0 +1,14 @@
contract c {
uint256 a;
uint256 b;
uint256 c;
bytes data;
function test() public returns (bool) {
data.pop();
return true;
}
}
// ----
// test() -> FAILURE

View File

@ -0,0 +1,13 @@
// This tests that the compiler knows the correct size of the function on the stack.
contract c {
bytes data;
function test() public returns (uint256 x) {
x = 2;
data.pop;
x = 3;
}
}
// ----
// test() -> 3

View File

@ -0,0 +1,12 @@
contract c {
bytes data;
function test() public returns (bytes memory) {
for (uint256 i = 0; i < 34; i++) data.push(0x03);
data.pop();
return data;
}
}
// ----
// test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,18 @@
contract c {
bytes data;
function test() public returns (bool x) {
data.push(0x05);
if (data.length != 1) return true;
if (data[0] != 0x05) return true;
data.push(0x04);
if (data[1] != 0x04) return true;
data.push(0x03);
uint256 l = data.length;
if (data[2] != 0x03) return true;
if (l != 0x03) return true;
}
}
// ----
// test() -> false

View File

@ -0,0 +1,18 @@
// Tests transition between short and long encoding
contract c {
bytes data;
function test() public returns (uint256) {
for (uint8 i = 1; i < 40; i++) {
data.push(bytes1(i));
if (data.length != i) return 0x1000 + i;
if (data[data.length - 1] != bytes1(i)) return i;
}
for (uint8 i = 1; i < 40; i++)
if (data[i - 1] != bytes1(i)) return 0x1000000 + i;
return 0;
}
}
// ----
// test() -> 0

View File

@ -0,0 +1,19 @@
contract C {
function f(uint256 x) public returns (uint256 a) {
assembly {
a := byte(x, 31)
}
}
function g(uint256 x) public returns (uint256 a) {
assembly {
a := byte(31, x)
}
}
}
// ====
// compileViaYul: also
// ----
// f(uint256): 2 -> 0
// g(uint256): 2 -> 2

View File

@ -0,0 +1,19 @@
contract c {
bytes data;
function test1() external returns (bool) {
data = new bytes(100);
for (uint256 i = 0; i < data.length; i++) data[i] = bytes1(uint8(i));
delete data[94];
delete data[96];
delete data[98];
return
data[94] == 0 &&
uint8(data[95]) == 95 &&
data[96] == 0 &&
uint8(data[97]) == 97;
}
}
// ----
// test1() -> true

View File

@ -0,0 +1,17 @@
contract c {
function set() public returns (bool) {
data = msg.data;
return true;
}
function getLength() public returns (uint256) {
return data.length;
}
bytes data;
}
// ----
// getLength() -> 0
// set(): 1, 2 -> true
// getLength() -> 68

View File

@ -0,0 +1,28 @@
contract test {
function f0() public returns (uint) {
return 2;
}
function f1() internal returns (function() internal returns (uint)) {
return f0;
}
function f2() internal returns (function() internal returns (function () internal returns (uint))) {
return f1;
}
function f3() internal returns (function() internal returns (function () internal returns (function () internal returns (uint)))) {
return f2;
}
function f() public returns (uint) {
function() internal returns(function() internal returns(function() internal returns(function() internal returns(uint)))) x;
x = f3;
return x()()()();
}
}
// ====
// compileViaYul: also
// ----
// f() -> 2

View File

@ -0,0 +1,16 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[2] calldata s)
external
pure
returns (uint256 a, uint256 b)
{
a = s[0];
b = s[1];
}
}
// ----
// f(uint256[2]): 42, 23 -> 42, 23

View File

@ -0,0 +1,21 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[][] calldata a) external returns (uint256) {
return 42;
}
function g(uint256[][] calldata a) external returns (uint256) {
a[0];
return 42;
}
}
// ----
// f(uint256[][]): 0x20, 0x0 -> 42 # valid access stub #
// f(uint256[][]): 0x20, 0x1 -> FAILURE # invalid on argument decoding #
// f(uint256[][]): 0x20, 0x1, 0x20 -> 42 # invalid on outer access #
// g(uint256[][]): 0x20, 0x1, 0x20 -> FAILURE
// f(uint256[][]): 0x20, 0x1, 0x20, 0x2, 0x42 -> 42 # invalid on inner access #
// g(uint256[][]): 0x20, 0x1, 0x20, 0x2, 0x42 -> FAILURE

View File

@ -0,0 +1,30 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[][1][] calldata a) external returns (uint256) {
return 42;
}
function g(uint256[][1][] calldata a) external returns (uint256) {
a[0];
return 42;
}
function h(uint256[][1][] calldata a) external returns (uint256) {
a[0][0];
return 42;
}
}
// ----
// f(uint256[][1][]): 0x20, 0x0 -> 42 # valid access stub #
// f(uint256[][1][]): 0x20, 0x1 -> FAILURE # invalid on argument decoding #
// f(uint256[][1][]): 0x20, 0x1, 0x20 -> 42 # invalid on outer access #
// g(uint256[][1][]): 0x20, 0x1, 0x20 -> FAILURE
// f(uint256[][1][]): 0x20, 0x1, 0x20, 0x20 -> 42 # invalid on inner access #
// g(uint256[][1][]): 0x20, 0x1, 0x20, 0x20 -> 42
// h(uint256[][1][]): 0x20, 0x1, 0x20, 0x20 -> FAILURE
// f(uint256[][1][]): 0x20, 0x1, 0x20, 0x20, 0x1 -> 42
// g(uint256[][1][]): 0x20, 0x1, 0x20, 0x20, 0x1 -> 42
// h(uint256[][1][]): 0x20, 0x1, 0x20, 0x20, 0x1 -> FAILURE

View File

@ -0,0 +1,24 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256 b;
}
function f(S[] calldata s)
external
pure
returns (uint256 l, uint256 a, uint256 b, uint256 c, uint256 d)
{
l = s.length;
a = s[0].a;
b = s[0].b;
c = s[1].a;
d = s[1].b;
}
}
// ----
// f((uint256,uint256)[]): 0x20, 0x2, 0x1, 0x2, 0x3, 0x4 -> 2, 1, 2, 3, 4

View File

@ -0,0 +1,25 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256 b;
}
function f(S[] calldata s)
external
pure
returns (uint256 l, uint256 a, uint256 b, uint256 c, uint256 d)
{
S[] memory m = s;
l = m.length;
a = m[0].a;
b = m[0].b;
c = m[1].a;
d = m[1].b;
}
}
// ----
// f((uint256,uint256)[]): 0x20, 0x2, 0x1, 0x2, 0x3, 0x4 -> 2, 1, 2, 3, 4

View File

@ -0,0 +1,15 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[][] calldata a)
external
returns (uint256, uint256[] memory)
{
uint256[] memory m = a[0];
return (a.length, m);
}
}
// ----
// f(uint256[][]): 0x20, 0x1, 0x20, 0x2, 0x17, 0x2a -> 0x1, 0x40, 0x2, 0x17, 0x2a

View File

@ -0,0 +1,17 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256 b;
}
function f(S calldata s) external pure returns (uint256 a, uint256 b) {
a = s.a;
b = s.b;
}
}
// ----
// f((uint256,uint256)): 42, 23 -> 42, 23

View File

@ -0,0 +1,20 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256 b;
}
function f(uint256 a, S calldata s, uint256 b)
external
pure
returns (uint256, uint256, uint256, uint256)
{
return (a, s.a, s.b, b);
}
}
// ----
// f(uint256,(uint256,uint256),uint256): 1, 2, 3, 4 -> 1, 2, 3, 4

View File

@ -0,0 +1,24 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256[2] b;
uint256 c;
}
function f(S calldata s)
external
pure
returns (uint256 a, uint256 b0, uint256 b1, uint256 c)
{
a = s.a;
b0 = s.b[0];
b1 = s.b[1];
c = s.c;
}
}
// ----
// f((uint256,uint256[2],uint256)): 42, 1, 2, 23 -> 42, 1, 2, 23

View File

@ -0,0 +1,17 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint256 a;
uint256 b;
}
function f(S calldata s) external pure returns (uint256, uint256) {
S memory m = s;
return (m.a, m.b);
}
}
// ----
// f((uint256,uint256)): 42, 23 -> 42, 23

View File

@ -0,0 +1,27 @@
pragma experimental ABIEncoderV2;
contract C {
struct S1 {
uint256 a;
uint256 b;
}
struct S2 {
uint256 a;
}
function f(S1 calldata s1, S2 calldata s2, S1 calldata s3)
external
pure
returns (uint256 a, uint256 b, uint256 c, uint256 d, uint256 e)
{
a = s1.a;
b = s1.b;
c = s2.a;
d = s3.a;
e = s3.b;
}
}
// ----
// f((uint256,uint256),(uint256),(uint256,uint256)): 1, 2, 3, 4, 5 -> 1, 2, 3, 4, 5

View File

@ -0,0 +1,28 @@
abstract contract D {
function g() public virtual;
}
contract C {
D d = D(0x1212);
function f() public returns (uint256) {
d.g();
return 7;
}
function g() public returns (uint256) {
d.g.gas(200)();
return 7;
}
function h() public returns (uint256) {
address(d).call(""); // this does not throw (low-level)
return 7;
}
}
// ----
// f() -> FAILURE
// g() -> FAILURE
// h() -> 7

View File

@ -0,0 +1,17 @@
contract C {
function intern() public returns (uint256) {
function (uint) internal returns (uint) x;
x(2);
return 7;
}
function extern() public returns (uint256) {
function (uint) external returns (uint) x;
x(2);
return 7;
}
}
// ----
// intern() -> FAILURE # This should throw exceptions #
// extern() -> FAILURE

View File

@ -0,0 +1,20 @@
contract C {
function() returns (uint256) internal x;
int256 mutex;
function t() public returns (uint256) {
if (mutex > 0) {
assembly {
mstore(0, 7)
return(0, 0x20)
}
}
mutex = 1;
// Avoid re-executing this function if we jump somewhere.
x();
return 2;
}
}
// ----
// t() -> FAILURE

View File

@ -0,0 +1,20 @@
contract C {
int256 mutex;
function t() public returns (uint256) {
if (mutex > 0) {
assembly {
mstore(0, 7)
return(0, 0x20)
}
}
mutex = 1;
// Avoid re-executing this function if we jump somewhere.
function() internal returns (uint)[200] memory x;
x[0]();
return 2;
}
}
// ----
// t() -> FAILURE

View File

@ -0,0 +1,33 @@
contract C {
function f() public pure returns (address r) {
bytes21 x = 0x1122334455667788990011223344556677889900ff;
bytes20 y;
assembly {
y := x
}
address z = address(y);
assembly {
r := z
}
require(z == 0x1122334455667788990011223344556677889900);
}
function g() public pure returns (address payable r) {
bytes21 x = 0x1122334455667788990011223344556677889900ff;
bytes20 y;
assembly {
y := x
}
address payable z = address(y);
assembly {
r := z
}
require(z == 0x1122334455667788990011223344556677889900);
}
}
// ====
// compileViaYul: also
// ----
// f() -> 0x1122334455667788990011223344556677889900
// g() -> 0x1122334455667788990011223344556677889900

View File

@ -0,0 +1,15 @@
contract C {
function f() public pure returns (bytes32 r) {
bytes4 x = 0xffffffff;
bytes2 y = bytes2(x);
assembly {
r := y
}
// At this point, r and y both store four bytes, but
// y is properly cleaned before the equality check
require(y == bytes2(0xffff));
}
}
// ----
// f() -> "\xff\xff\xff\xff"

View File

@ -0,0 +1,13 @@
contract C {
function test() public returns (uint256, uint256) {
uint32 a = 0xffffffff;
uint16 x = uint16(a);
uint16 y = x;
x /= 0x100;
y = y / 0x100;
return (x, y);
}
}
// ----
// test() -> 0xff, 0xff

View File

@ -0,0 +1,42 @@
contract D {
bytes32 public x;
constructor() public {
bytes32 codeHash;
assembly {
let size := codesize()
codecopy(mload(0x40), 0, size)
codeHash := keccak256(mload(0x40), size)
}
x = codeHash;
}
}
contract C {
function testRuntime() public returns (bool) {
D d = new D();
bytes32 runtimeHash = keccak256(type(D).runtimeCode);
bytes32 otherHash;
uint256 size;
assembly {
size := extcodesize(d)
extcodecopy(d, mload(0x40), 0, size)
otherHash := keccak256(mload(0x40), size)
}
require(size == type(D).runtimeCode.length);
require(runtimeHash == otherHash);
return true;
}
function testCreation() public returns (bool) {
D d = new D();
bytes32 creationHash = keccak256(type(D).creationCode);
require(creationHash == d.x());
return true;
}
}
// ----
// testRuntime() -> true
// testCreation() -> true

View File

@ -0,0 +1,26 @@
contract D {
uint256 x;
constructor() public {
x = 7;
}
function f() public view returns (uint256) {
return x;
}
}
contract C {
function test() public returns (uint256) {
bytes memory c = type(D).creationCode;
D d;
assembly {
d := create(0, add(c, 0x20), mload(c))
}
return d.f();
}
}
// ----
// test() -> 7

View File

@ -0,0 +1,19 @@
contract D {
function f() public pure returns (uint256) {
return 7;
}
}
contract C {
function diff() public pure returns (uint256 remainder) {
bytes memory a = type(D).creationCode;
bytes memory b = type(D).runtimeCode;
assembly {
remainder := mod(sub(b, a), 0x20)
}
}
}
// ----
// diff() -> 0 # This checks that the allocation function pads to multiples of 32 bytes #

View File

@ -0,0 +1,22 @@
contract C {
bytes constant a = "\x03\x01\x02";
bytes constant b = hex"030102";
string constant c = "hello";
function f() public returns (bytes memory) {
return a;
}
function g() public returns (bytes memory) {
return b;
}
function h() public returns (bytes memory) {
return bytes(c);
}
}
// ----
// f() -> 0x20, 3, "\x03\x01\x02"
// g() -> 0x20, 3, "\x03\x01\x02"
// h() -> 0x20, 5, "hello"

View File

@ -0,0 +1,14 @@
contract C {
uint256 constant LEN = 3;
uint256[LEN] public a;
constructor(uint256[LEN] memory _a) public {
a = _a;
}
}
// ----
// constructor(): 1, 2, 3 ->
// a(uint256): 0 -> 1
// a(uint256): 1 -> 2
// a(uint256): 2 -> 3

View File

@ -0,0 +1,11 @@
contract Foo {
uint256 constant x = 56;
enum ActionChoices {GoLeft, GoRight, GoStraight, Sit}
ActionChoices constant choices = ActionChoices.GoLeft;
bytes32 constant st = "abc\x00\xff__";
}
// ====
// compileViaYul: also
// ----
// constructor() ->

View File

@ -0,0 +1,12 @@
contract c {
enum Truth {False, True}
function test() public returns (uint256) {
return uint256(Truth(uint8(0x701)));
}
}
// ====
// compileViaYul: also
// ----
// test() -> 1

View File

@ -0,0 +1,22 @@
contract Main {
bytes3 name;
bool flag;
constructor(bytes3 x, bool f) public {
name = x;
flag = f;
}
function getName() public returns (bytes3 ret) {
return name;
}
function getFlag() public returns (bool ret) {
return flag;
}
}
// ----
// constructor(): "abc", true
// getFlag() -> true
// getName() -> "abc"

View File

@ -0,0 +1,38 @@
contract Helper {
bytes3 name;
bool flag;
constructor(bytes3 x, bool f) public {
name = x;
flag = f;
}
function getName() public returns (bytes3 ret) {
return name;
}
function getFlag() public returns (bool ret) {
return flag;
}
}
contract Main {
Helper h;
constructor() public {
h = new Helper("abc", true);
}
function getFlag() public returns (bool ret) {
return h.getFlag();
}
function getName() public returns (bytes3 ret) {
return h.getName();
}
}
// ----
// getFlag() -> true
// getName() -> "abc"

View File

@ -0,0 +1,16 @@
contract C {
uint256 public a;
uint256[3] public b;
constructor(uint256 _a, uint256[3] memory _b) public {
a = _a;
b = _b;
}
}
// ----
// constructor(): 1, 2, 3, 4 ->
// a() -> 1
// b(uint256): 0 -> 2
// b(uint256): 1 -> 3
// b(uint256): 2 -> 4

View File

@ -0,0 +1,20 @@
contract C {
uint256 public x;
modifier run() {
for (uint256 i = 0; i < 10; i++) {
if (i % 2 == 1) continue;
_;
}
}
function f() public run {
uint256 k = x;
uint256 t = k + 1;
x = t;
}
}
// ----
// x() -> 0
// f() ->
// x() -> 5

View File

@ -0,0 +1,20 @@
contract A {
function f() public {
new B();
}
}
contract B {
function f() public {}
}
contract C {
function f() public {
new B();
}
}
// ----
// constructor() ->

View File

@ -0,0 +1,18 @@
contract C {
function() internal returns (uint)[] x;
function() internal returns (uint)[] y;
function test() public returns (uint256) {
x = new function() internal returns (uint)[](10);
x[9] = a;
y = x;
return y[9]();
}
function a() public returns (uint256) {
return 7;
}
}
// ----
// test() -> 7

View File

@ -0,0 +1,22 @@
contract C {
function() internal returns (uint)[20] x;
int256 mutex;
function one() public returns (uint256) {
function() internal returns (uint)[20] memory xmem;
x = xmem;
return 3;
}
function two() public returns (uint256) {
if (mutex > 0) return 7;
mutex = 1;
// If this test fails, it might re-execute this function.
x[0]();
return 2;
}
}
// ----
// one() -> 3
// two() -> FAILURE

View File

@ -0,0 +1,15 @@
contract C {
function f() public returns (uint256 r) {
uint256;
uint256;
uint256;
uint256;
int256 x = -7;
return uint256(x);
}
}
// ====
// compileViaYul: also
// ----
// f() -> -7

View File

@ -0,0 +1,9 @@
contract C {
function f() public returns (uint256) {
uint256[][] memory a = new uint256[][](0);
return 7;
}
}
// ----
// f() -> 7

View File

@ -0,0 +1,21 @@
contract C {
struct S {
uint256[2] a;
bytes b;
}
function f() public returns (bytes1, uint256, uint256, bytes1) {
bytes memory x = new bytes(200);
x[199] = "A";
uint256[2][] memory y = new uint256[2][](300);
y[203][1] = 8;
S[] memory z = new S[](180);
z[170].a[1] = 4;
z[170].b = new bytes(102);
z[170].b[99] = "B";
return (x[199], y[203][1], z[170].a[1], z[170].b[99]);
}
}
// ----
// f() -> "A", 8, 4, "B"

View File

@ -0,0 +1,34 @@
contract C {
function f() public returns (uint256) {
uint256[][] memory x = new uint256[][](42);
assert(x[0].length == 0);
x[0] = new uint256[](1);
x[0][0] = 1;
assert(x[4].length == 0);
x[4] = new uint256[](1);
x[4][0] = 2;
assert(x[10].length == 0);
x[10] = new uint256[](1);
x[10][0] = 44;
uint256[][] memory y = new uint256[][](24);
assert(y[0].length == 0);
y[0] = new uint256[](1);
y[0][0] = 1;
assert(y[4].length == 0);
y[4] = new uint256[](1);
y[4][0] = 2;
assert(y[10].length == 0);
y[10] = new uint256[](1);
y[10][0] = 88;
if (
(x[0][0] == y[0][0]) &&
(x[4][0] == y[4][0]) &&
(x[10][0] == 44) &&
(y[10][0] == 88)
) return 7;
return 0;
}
}
// ----
// f() -> 7

View File

@ -0,0 +1,17 @@
contract Lib {
struct S {
uint256 a;
uint256 b;
}
}
contract Test {
function f() public returns (uint256 r) {
Lib.S memory x = Lib.S({a: 2, b: 3});
r = x.b;
}
}
// ----
// f() -> 3

View File

@ -0,0 +1,10 @@
contract C {
function f() public returns (uint256) {
uint256 x = 1;
(x) = 2;
return x;
}
}
// ----
// f() -> 2

View File

@ -0,0 +1,20 @@
// Test for a bug where we did not increment the counter properly while deleting a dynamic array.
contract C {
struct S {
uint256 x;
uint256[] y;
}
S[] data;
function f() public returns (bool) {
S storage s1 = data.push();
s1.x = 2**200;
S storage s2 = data.push();
s2.x = 2**200;
delete data;
return true;
}
}
// ----
// f() -> true # This code interprets x as an array length and thus will go out of gas. neither of the two should throw due to out-of-bounds access #

View File

@ -0,0 +1,21 @@
contract B {
function f() public returns (uint256) {
return 10;
}
}
contract C is B {
function f(uint256 i) public returns (uint256) {
return 2 * i;
}
function g() public returns (uint256) {
return f(1);
}
}
// ====
// compileViaYul: also
// ----
// g() -> 2

View File

@ -0,0 +1,29 @@
contract A {
function f(uint256 a) public returns (uint256) {
return 2 * a;
}
}
contract B {
function f() public returns (uint256) {
return 10;
}
}
contract C is A, B {
function g() public returns (uint256) {
return f();
}
function h() public returns (uint256) {
return f(1);
}
}
// ====
// compileViaYul: also
// ----
// g() -> 10
// h() -> 2

View File

@ -0,0 +1,36 @@
contract C {
uint256 x = 7;
bytes data;
uint256[] y;
uint256[] arrayData;
function returnsArray() public returns (uint256[] memory) {
arrayData = new uint256[](9);
arrayData[2] = 5;
arrayData[7] = 4;
return arrayData;
}
function f(bytes memory s) public returns (uint256) {
uint256 loc;
uint256[] memory memArray;
(loc, x, y, data, arrayData[3]) = (8, 4, returnsArray(), s, 2);
if (loc != 8) return 1;
if (x != 4) return 2;
if (y.length != 9) return 3;
if (y[2] != 5) return 4;
if (y[7] != 4) return 5;
if (data.length != s.length) return 6;
if (data[3] != s[3]) return 7;
if (arrayData[3] != 2) return 8;
(memArray, loc) = (arrayData, 3);
if (loc != 3) return 9;
if (memArray.length != arrayData.length) return 10;
bytes memory memBytes;
(x, memBytes, y[2], , ) = (456, s, 789, 101112, 131415);
if (x != 456 || memBytes.length != s.length || y[2] != 789) return 11;
}
}
// ----
// f(bytes): 0x20, 0x5, "abcde" -> 0

View File

@ -0,0 +1,15 @@
contract C {
function div(uint256 a, uint256 b) public returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) public returns (uint256) {
return a % b;
}
}
// ----
// div(uint256,uint256): 7, 2 -> 3
// div(uint256,uint256): 7, 0 -> FAILURE # throws #
// mod(uint256,uint256): 7, 2 -> 1
// mod(uint256,uint256): 7, 0 -> FAILURE # throws #

View File

@ -0,0 +1,53 @@
contract c {
struct Data {
uint256 x;
uint256 y;
}
Data[] data;
uint256[] ids;
function setIDStatic(uint256 id) public {
ids[2] = id;
}
function setID(uint256 index, uint256 id) public {
ids[index] = id;
}
function setData(uint256 index, uint256 x, uint256 y) public {
data[index].x = x;
data[index].y = y;
}
function getID(uint256 index) public returns (uint256) {
return ids[index];
}
function getData(uint256 index) public returns (uint256 x, uint256 y) {
x = data[index].x;
y = data[index].y;
}
function getLengths() public returns (uint256 l1, uint256 l2) {
l1 = data.length;
l2 = ids.length;
}
function setLengths(uint256 l1, uint256 l2) public {
while (data.length < l1) data.push();
while (ids.length < l2) ids.push();
}
}
// ----
// getLengths() -> 0, 0
// setLengths(uint256,uint256): 48, 49 ->
// getLengths() -> 48, 49
// setIDStatic(uint256): 11 ->
// getID(uint256): 2 -> 11
// setID(uint256,uint256): 7, 8 ->
// getID(uint256): 7 -> 8
// setData(uint256,uint256,uint256): 7, 8, 9 ->
// setData(uint256,uint256,uint256): 8, 10, 11 ->
// getData(uint256): 7 -> 8, 9
// getData(uint256): 8 -> 10, 11

View File

@ -0,0 +1,34 @@
contract c {
uint256[] data;
function enlarge(uint256 amount) public returns (uint256) {
while (data.length < amount) data.push();
return data.length;
}
function set(uint256 index, uint256 value) public returns (bool) {
data[index] = value;
return true;
}
function get(uint256 index) public returns (uint256) {
return data[index];
}
function length() public returns (uint256) {
return data.length;
}
}
// ====
// compileViaYul: also
// ----
// length() -> 0
// get(uint256): 3 -> FAILURE
// enlarge(uint256): 4 -> 4
// length() -> 4
// set(uint256,uint256): 3, 4 -> true
// get(uint256): 3 -> 4
// length() -> 4
// set(uint256,uint256): 4, 8 -> FAILURE
// length() -> 4

View File

@ -0,0 +1,10 @@
contract test {
function f(uint256 k) public returns (uint256) {
return k;
}
}
// ====
// compileViaYul: also
// ----
// f(uint256): 9 -> 9

Some files were not shown because too many files have changed in this diff Show More