mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8464 from aarlt/end-to-end-verified
[test] Extraction of 292 tests from SolidityEndToEndTest.cpp
This commit is contained in:
commit
8834b1acaf
22
scripts/endToEndExtraction/create_traces.sh
Executable file
22
scripts/endToEndExtraction/create_traces.sh
Executable 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"
|
183
scripts/endToEndExtraction/remove-testcases.py
Executable file
183
scripts/endToEndExtraction/remove-testcases.py
Executable 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:])
|
215
scripts/endToEndExtraction/verify-testcases.py
Executable file
215
scripts/endToEndExtraction/verify-testcases.py
Executable 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
@ -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
|
@ -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
|
@ -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
|
@ -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
|
22
test/libsolidity/semanticTests/extracted/abi_decode_v2.sol
Normal file
22
test/libsolidity/semanticTests/extracted/abi_decode_v2.sol
Normal 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
|
@ -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
|
@ -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
|
36
test/libsolidity/semanticTests/extracted/abi_encode.sol
Normal file
36
test/libsolidity/semanticTests/extracted/abi_encode.sol
Normal 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"
|
26
test/libsolidity/semanticTests/extracted/abi_encode_call.sol
Normal file
26
test/libsolidity/semanticTests/extracted/abi_encode_call.sol
Normal 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
|
@ -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"
|
@ -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
|
@ -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
|
@ -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
|
53
test/libsolidity/semanticTests/extracted/abi_encode_v2.sol
Normal file
53
test/libsolidity/semanticTests/extracted/abi_encode_v2.sol
Normal 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
|
@ -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
|
@ -0,0 +1,6 @@
|
||||
contract Lotto {
|
||||
uint256 public constant ticketPrice = 555;
|
||||
}
|
||||
|
||||
// ----
|
||||
// ticketPrice() -> 555
|
@ -0,0 +1,8 @@
|
||||
contract Lotto {
|
||||
uint256 public ticketPrice = 500;
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// ticketPrice() -> 500
|
12
test/libsolidity/semanticTests/extracted/addmod_mulmod.sol
Normal file
12
test/libsolidity/semanticTests/extracted/addmod_mulmod.sol
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
16
test/libsolidity/semanticTests/extracted/array_pop.sol
Normal file
16
test/libsolidity/semanticTests/extracted/array_pop.sol
Normal 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
|
@ -0,0 +1,11 @@
|
||||
contract c {
|
||||
uint256[] data;
|
||||
|
||||
function test() public returns (bool) {
|
||||
data.pop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// test() -> FAILURE
|
@ -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
|
19
test/libsolidity/semanticTests/extracted/array_push.sol
Normal file
19
test/libsolidity/semanticTests/extracted/array_push.sol
Normal 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
|
@ -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
|
@ -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
|
24
test/libsolidity/semanticTests/extracted/assert_require.sol
Normal file
24
test/libsolidity/semanticTests/extracted/assert_require.sol
Normal 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
|
@ -0,0 +1,10 @@
|
||||
contract C {
|
||||
uint256 constant x = 0x123 + 0x456;
|
||||
|
||||
function f() public returns (uint256) {
|
||||
return x + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// f() -> 0x57a
|
13
test/libsolidity/semanticTests/extracted/balance.sol
Normal file
13
test/libsolidity/semanticTests/extracted/balance.sol
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
17
test/libsolidity/semanticTests/extracted/byte_array_pop.sol
Normal file
17
test/libsolidity/semanticTests/extracted/byte_array_pop.sol
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
18
test/libsolidity/semanticTests/extracted/byte_array_push.sol
Normal file
18
test/libsolidity/semanticTests/extracted/byte_array_push.sol
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
16
test/libsolidity/semanticTests/extracted/calldata_array.sol
Normal file
16
test/libsolidity/semanticTests/extracted/calldata_array.sol
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
17
test/libsolidity/semanticTests/extracted/calldata_struct.sol
Normal file
17
test/libsolidity/semanticTests/extracted/calldata_struct.sol
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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"
|
@ -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
|
@ -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
|
@ -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
|
@ -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 #
|
22
test/libsolidity/semanticTests/extracted/constant_string.sol
Normal file
22
test/libsolidity/semanticTests/extracted/constant_string.sol
Normal 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"
|
@ -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
|
@ -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() ->
|
@ -0,0 +1,12 @@
|
||||
contract c {
|
||||
enum Truth {False, True}
|
||||
|
||||
function test() public returns (uint256) {
|
||||
return uint256(Truth(uint8(0x701)));
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 1
|
@ -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"
|
@ -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"
|
@ -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
|
@ -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
|
@ -0,0 +1,20 @@
|
||||
contract A {
|
||||
function f() public {
|
||||
new B();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract B {
|
||||
function f() public {}
|
||||
}
|
||||
|
||||
|
||||
contract C {
|
||||
function f() public {
|
||||
new B();
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// constructor() ->
|
@ -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
|
@ -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
|
@ -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
|
@ -0,0 +1,9 @@
|
||||
contract C {
|
||||
function f() public returns (uint256) {
|
||||
uint256[][] memory a = new uint256[][](0);
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// f() -> 7
|
@ -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"
|
@ -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
|
@ -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
|
10
test/libsolidity/semanticTests/extracted/decayed_tuple.sol
Normal file
10
test/libsolidity/semanticTests/extracted/decayed_tuple.sol
Normal file
@ -0,0 +1,10 @@
|
||||
contract C {
|
||||
function f() public returns (uint256) {
|
||||
uint256 x = 1;
|
||||
(x) = 2;
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// f() -> 2
|
@ -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 #
|
@ -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
|
@ -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
|
@ -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
|
@ -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 #
|
@ -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
|
@ -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
|
@ -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
Loading…
Reference in New Issue
Block a user