1 /*
2 	This file is part of solidity.
3 
4 	solidity is free software: you can redistribute it and/or modify
5 	it under the terms of the GNU General Public License as published by
6 	the Free Software Foundation, either version 3 of the License, or
7 	(at your option) any later version.
8 
9 	solidity is distributed in the hope that it will be useful,
10 	but WITHOUT ANY WARRANTY; without even the implied warranty of
11 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 	GNU General Public License for more details.
13 
14 	You should have received a copy of the GNU General Public License
15 	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 // SPDX-License-Identifier: GPL-3.0
18 /**
19  * @author Christian <c@ethdev.com>
20  * @author Gav Wood <g@ethdev.com>
21  * @date 2014
22  * Unit tests for the solidity expression compiler, testing the behaviour of the code.
23  */
24 
25 #include <test/libsolidity/SolidityExecutionFramework.h>
26 
27 #include <test/Common.h>
28 #include <test/EVMHost.h>
29 
30 #include <liblangutil/Exceptions.h>
31 #include <liblangutil/EVMVersion.h>
32 
33 #include <libevmasm/Assembly.h>
34 
35 #include <libsolutil/Keccak256.h>
36 #include <libsolutil/ErrorCodes.h>
37 
38 #include <boost/test/unit_test.hpp>
39 
40 #include <range/v3/view/transform.hpp>
41 
42 #include <functional>
43 #include <numeric>
44 #include <string>
45 #include <tuple>
46 
47 using namespace std;
48 using namespace std::placeholders;
49 using namespace solidity;
50 using namespace solidity::util;
51 using namespace solidity::test;
52 using namespace solidity::langutil;
53 
54 #define ALSO_VIA_YUL(CODE)                      \
55 {                                               \
56 	m_doEwasmTestrun = true;                    \
57                                                 \
58 	m_compileViaYul = false;                    \
59 	m_compileToEwasm = false;                   \
60 	{ CODE }                                    \
61                                                 \
62 	m_compileViaYul = true;                     \
63 	reset();                                    \
64 	{ CODE }                                    \
65                                                 \
66 	if (m_doEwasmTestrun)                       \
67 	{                                           \
68 		m_compileToEwasm = true;                \
69 		reset();                                \
70 		{ CODE }                                \
71 	}                                           \
72 }
73 
74 #define DISABLE_EWASM_TESTRUN() \
75 	{ m_doEwasmTestrun = false; }
76 
77 namespace solidity::frontend::test
78 {
79 
80 struct SolidityEndToEndTestExecutionFramework: public SolidityExecutionFramework
81 {
82 	bool m_doEwasmTestrun = false;
83 };
84 
BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest,SolidityEndToEndTestExecutionFramework)85 BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, SolidityEndToEndTestExecutionFramework)
86 
87 unsigned constexpr roundTo32(unsigned _num)
88 {
89 	return (_num + 31) / 32 * 32;
90 }
91 
BOOST_AUTO_TEST_CASE(exp_operator)92 BOOST_AUTO_TEST_CASE(exp_operator)
93 {
94 	char const* sourceCode = R"(
95 		contract test {
96 			function f(uint a) public returns(uint d) { return 2 ** a; }
97 		}
98 	)";
99 	compileAndRun(sourceCode);
100 	testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to<int>()); }, 0, 16);
101 }
102 
BOOST_AUTO_TEST_CASE(exp_zero)103 BOOST_AUTO_TEST_CASE(exp_zero)
104 {
105 	char const* sourceCode = R"(
106 		contract test {
107 			function f(uint a) public returns(uint d) { return a ** 0; }
108 		}
109 	)";
110 	compileAndRun(sourceCode);
111 	testContractAgainstCppOnRange("f(uint256)", [](u256 const&) -> u256 { return u256(1); }, 0, 16);
112 }
113 
114 /* TODO let's add this back when I figure out the correct type conversion.
115 BOOST_AUTO_TEST_CASE(conditional_expression_string_literal)
116 {
117 	char const* sourceCode = R"(
118 		contract test {
119 			function f(bool cond) public returns (bytes32) {
120 				return cond ? "true" : "false";
121 			}
122 		}
123 	)";
124 	compileAndRun(sourceCode);
125 	ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(string("true", 4)));
126 	ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(string("false", 5)));
127 }
128 */
129 
BOOST_AUTO_TEST_CASE(recursive_calls)130 BOOST_AUTO_TEST_CASE(recursive_calls)
131 {
132 	char const* sourceCode = R"(
133 		contract test {
134 			function f(uint n) public returns(uint nfac) {
135 				if (n <= 1) return 1;
136 				else return n * f(n - 1);
137 			}
138 		}
139 	)";
140 	ALSO_VIA_YUL(
141 		DISABLE_EWASM_TESTRUN()
142 
143 		compileAndRun(sourceCode);
144 		function<u256(u256)> recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256
145 		{
146 			if (n <= 1)
147 				return 1;
148 			else
149 				return n * recursive_calls_cpp(n - 1);
150 		};
151 
152 		testContractAgainstCppOnRange("f(uint256)", recursive_calls_cpp, 0, 5);
153 	)
154 }
155 
BOOST_AUTO_TEST_CASE(while_loop)156 BOOST_AUTO_TEST_CASE(while_loop)
157 {
158 	char const* sourceCode = R"(
159 		contract test {
160 			function f(uint n) public returns(uint nfac) {
161 				nfac = 1;
162 				uint i = 2;
163 				while (i <= n) nfac *= i++;
164 			}
165 		}
166 	)";
167 	ALSO_VIA_YUL(
168 		DISABLE_EWASM_TESTRUN()
169 
170 		compileAndRun(sourceCode);
171 
172 		auto while_loop_cpp = [](u256 const& n) -> u256
173 		{
174 			u256 nfac = 1;
175 			u256 i = 2;
176 			while (i <= n)
177 				nfac *= i++;
178 
179 			return nfac;
180 		};
181 
182 		testContractAgainstCppOnRange("f(uint256)", while_loop_cpp, 0, 5);
183 	)
184 }
185 
BOOST_AUTO_TEST_CASE(do_while_loop)186 BOOST_AUTO_TEST_CASE(do_while_loop)
187 {
188 	char const* sourceCode = R"(
189 		contract test {
190 			function f(uint n) public returns(uint nfac) {
191 				nfac = 1;
192 				uint i = 2;
193 				do { nfac *= i++; } while (i <= n);
194 			}
195 		}
196 	)";
197 	ALSO_VIA_YUL(
198 		DISABLE_EWASM_TESTRUN()
199 
200 		compileAndRun(sourceCode);
201 
202 		auto do_while_loop_cpp = [](u256 const& n) -> u256
203 		{
204 			u256 nfac = 1;
205 			u256 i = 2;
206 			do
207 			{
208 				nfac *= i++;
209 			}
210 			while (i <= n);
211 
212 			return nfac;
213 		};
214 
215 		testContractAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5);
216 	)
217 }
218 
BOOST_AUTO_TEST_CASE(do_while_loop_multiple_local_vars)219 BOOST_AUTO_TEST_CASE(do_while_loop_multiple_local_vars)
220 {
221 	char const* sourceCode = R"(
222 		contract test {
223 			function f(uint x) public pure returns(uint r) {
224 				uint i = 0;
225 				do
226 				{
227 					uint z = x * 2;
228 					if (z < 4) break;
229 					else {
230 						uint k = z + 1;
231 						if (k < 8) {
232 							x++;
233 							continue;
234 						}
235 					}
236 					if (z > 12) return 0;
237 					x++;
238 					i++;
239 				} while (true);
240 				return 42;
241 			}
242 		}
243 	)";
244 	ALSO_VIA_YUL(
245 		DISABLE_EWASM_TESTRUN()
246 
247 		compileAndRun(sourceCode);
248 
249 		auto do_while = [](u256 n) -> u256
250 		{
251 			u256 i = 0;
252 			do
253 			{
254 				u256 z = n * 2;
255 				if (z < 4) break;
256 				else {
257 					u256 k = z + 1;
258 					if (k < 8) {
259 						n++;
260 						continue;
261 					}
262 				}
263 				if (z > 12) return 0;
264 				n++;
265 				i++;
266 			} while (true);
267 			return 42;
268 		};
269 
270 		testContractAgainstCppOnRange("f(uint256)", do_while, 0, 12);
271 	)
272 }
273 
BOOST_AUTO_TEST_CASE(nested_loops)274 BOOST_AUTO_TEST_CASE(nested_loops)
275 {
276 	// tests that break and continue statements in nested loops jump to the correct place
277 	char const* sourceCode = R"(
278 		contract test {
279 			function f(uint x) public returns(uint y) {
280 				while (x > 1) {
281 					if (x == 10) break;
282 					while (x > 5) {
283 						if (x == 8) break;
284 						x--;
285 						if (x == 6) continue;
286 						return x;
287 					}
288 					x--;
289 					if (x == 3) continue;
290 					break;
291 				}
292 				return x;
293 			}
294 		}
295 	)";
296 	ALSO_VIA_YUL(
297 		DISABLE_EWASM_TESTRUN()
298 
299 		compileAndRun(sourceCode);
300 
301 		auto nested_loops_cpp = [](u256 n) -> u256
302 		{
303 			while (n > 1)
304 			{
305 				if (n == 10)
306 					break;
307 				while (n > 5)
308 				{
309 					if (n == 8)
310 						break;
311 					n--;
312 					if (n == 6)
313 						continue;
314 					return n;
315 				}
316 				n--;
317 				if (n == 3)
318 					continue;
319 				break;
320 			}
321 
322 			return n;
323 		};
324 
325 		testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12);
326 	)
327 }
328 
BOOST_AUTO_TEST_CASE(nested_loops_multiple_local_vars)329 BOOST_AUTO_TEST_CASE(nested_loops_multiple_local_vars)
330 {
331 	// tests that break and continue statements in nested loops jump to the correct place
332 	// and free local variables properly
333 	char const* sourceCode = R"(
334 		contract test {
335 			function f(uint x) public returns(uint y) {
336 				while (x > 0) {
337 					uint z = x + 10;
338 					uint k = z + 1;
339 					if (k > 20) {
340 						break;
341 						uint p = 100;
342 						k += p;
343 					}
344 					if (k > 15) {
345 						x--;
346 						continue;
347 						uint t = 1000;
348 						x += t;
349 					}
350 					while (k > 10) {
351 						uint m = k - 1;
352 						if (m == 10) return x;
353 						return k;
354 						uint h = 10000;
355 						z += h;
356 					}
357 					x--;
358 					break;
359 				}
360 				return x;
361 			}
362 		}
363 	)";
364 	ALSO_VIA_YUL(
365 		DISABLE_EWASM_TESTRUN()
366 
367 		compileAndRun(sourceCode);
368 
369 		auto nested_loops_cpp = [](u256 n) -> u256
370 		{
371 			while (n > 0)
372 			{
373 				u256 z = n + 10;
374 				u256 k = z + 1;
375 				if (k > 20) break;
376 				if (k > 15) {
377 					n--;
378 					continue;
379 				}
380 				while (k > 10)
381 				{
382 					u256 m = k - 1;
383 					if (m == 10) return n;
384 					return k;
385 				}
386 				n--;
387 				break;
388 			}
389 
390 			return n;
391 		};
392 
393 		testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12);
394 	)
395 }
396 
BOOST_AUTO_TEST_CASE(for_loop_multiple_local_vars)397 BOOST_AUTO_TEST_CASE(for_loop_multiple_local_vars)
398 {
399 	char const* sourceCode = R"(
400 		contract test {
401 			function f(uint x) public pure returns(uint r) {
402 				for (uint i = 0; i < 12; i++)
403 				{
404 					uint z = x + 1;
405 					if (z < 4) break;
406 					else {
407 						uint k = z * 2;
408 						if (i + k < 10) {
409 							x++;
410 							continue;
411 						}
412 					}
413 					if (z > 8) return 0;
414 					x++;
415 				}
416 				return 42;
417 			}
418 		}
419 	)";
420 	ALSO_VIA_YUL(
421 		DISABLE_EWASM_TESTRUN()
422 
423 		compileAndRun(sourceCode);
424 
425 		auto for_loop = [](u256 n) -> u256
426 		{
427 			for (u256 i = 0; i < 12; i++)
428 			{
429 				u256 z = n + 1;
430 				if (z < 4) break;
431 				else {
432 					u256 k = z * 2;
433 					if (i + k < 10) {
434 						n++;
435 						continue;
436 					}
437 				}
438 				if (z > 8) return 0;
439 				n++;
440 			}
441 			return 42;
442 		};
443 
444 		testContractAgainstCppOnRange("f(uint256)", for_loop, 0, 12);
445 	)
446 }
447 
BOOST_AUTO_TEST_CASE(nested_for_loop_multiple_local_vars)448 BOOST_AUTO_TEST_CASE(nested_for_loop_multiple_local_vars)
449 {
450 	char const* sourceCode = R"(
451 		contract test {
452 			function f(uint x) public pure returns(uint r) {
453 				for (uint i = 0; i < 5; i++)
454 				{
455 					uint z = x + 1;
456 					if (z < 3) {
457 						break;
458 						uint p = z + 2;
459 					}
460 					for (uint j = 0; j < 5; j++)
461 					{
462 						uint k = z * 2;
463 						if (j + k < 8) {
464 							x++;
465 							continue;
466 							uint t = z * 3;
467 						}
468 						x++;
469 						if (x > 20) {
470 							return 84;
471 							uint h = x + 42;
472 						}
473 					}
474 					if (x > 30) {
475 						return 42;
476 						uint b = 0xcafe;
477 					}
478 				}
479 				return 42;
480 			}
481 		}
482 	)";
483 	ALSO_VIA_YUL(
484 		DISABLE_EWASM_TESTRUN()
485 
486 		compileAndRun(sourceCode);
487 
488 		auto for_loop = [](u256 n) -> u256
489 		{
490 			for (u256 i = 0; i < 5; i++)
491 			{
492 				u256 z = n + 1;
493 				if (z < 3) break;
494 				for (u256 j = 0; j < 5; j++)
495 				{
496 					u256 k = z * 2;
497 					if (j + k < 8) {
498 						n++;
499 						continue;
500 					}
501 					n++;
502 					if (n > 20) return 84;
503 				}
504 				if (n > 30) return 42;
505 			}
506 			return 42;
507 		};
508 
509 		testContractAgainstCppOnRange("f(uint256)", for_loop, 0, 12);
510 	)
511 }
512 
BOOST_AUTO_TEST_CASE(for_loop)513 BOOST_AUTO_TEST_CASE(for_loop)
514 {
515 	char const* sourceCode = R"(
516 		contract test {
517 			function f(uint n) public returns(uint nfac) {
518 				nfac = 1;
519 				uint i;
520 				for (i = 2; i <= n; i++)
521 					nfac *= i;
522 			}
523 		}
524 	)";
525 	ALSO_VIA_YUL(
526 		DISABLE_EWASM_TESTRUN()
527 
528 		compileAndRun(sourceCode);
529 
530 		auto for_loop_cpp = [](u256 const& n) -> u256
531 		{
532 			u256 nfac = 1;
533 			for (auto i = 2; i <= n; i++)
534 				nfac *= i;
535 			return nfac;
536 		};
537 
538 		testContractAgainstCppOnRange("f(uint256)", for_loop_cpp, 0, 5);
539 	)
540 }
541 
BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr)542 BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr)
543 {
544 	char const* sourceCode = R"(
545 		contract test {
546 			function f(uint n) public returns(uint nfac) {
547 				nfac = 1;
548 				uint256 i;
549 				for (i = 2; i <= n; i++)
550 					nfac *= i;
551 			}
552 		}
553 	)";
554 	ALSO_VIA_YUL(
555 		DISABLE_EWASM_TESTRUN()
556 
557 		compileAndRun(sourceCode);
558 
559 		auto for_loop_simple_init_expr_cpp = [](u256 const& n) -> u256
560 		{
561 			u256 nfac = 1;
562 			u256 i;
563 			for (i = 2; i <= n; i++)
564 				nfac *= i;
565 			return nfac;
566 		};
567 
568 		testContractAgainstCppOnRange("f(uint256)", for_loop_simple_init_expr_cpp, 0, 5);
569 	)
570 }
571 
BOOST_AUTO_TEST_CASE(for_loop_break_continue)572 BOOST_AUTO_TEST_CASE(for_loop_break_continue)
573 {
574 	char const* sourceCode = R"(
575 		contract test {
576 			function f(uint n) public returns (uint r)
577 			{
578 				uint i = 1;
579 				uint k = 0;
580 				for (i *= 5; k < n; i *= 7)
581 				{
582 					k++;
583 					i += 4;
584 					if (n % 3 == 0)
585 						break;
586 					i += 9;
587 					if (n % 2 == 0)
588 						continue;
589 					i += 19;
590 				}
591 				return i;
592 			}
593 		}
594 	)";
595 	ALSO_VIA_YUL(
596 		DISABLE_EWASM_TESTRUN()
597 		compileAndRun(sourceCode);
598 
599 		auto breakContinue = [](u256 const& n) -> u256
600 		{
601 			u256 i = 1;
602 			u256 k = 0;
603 			for (i *= 5; k < n; i *= 7)
604 			{
605 				k++;
606 				i += 4;
607 				if (n % 3 == 0)
608 					break;
609 				i += 9;
610 				if (n % 2 == 0)
611 					continue;
612 				i += 19;
613 			}
614 			return i;
615 		};
616 
617 		testContractAgainstCppOnRange("f(uint256)", breakContinue, 0, 10);
618 	);
619 }
620 
BOOST_AUTO_TEST_CASE(short_circuiting)621 BOOST_AUTO_TEST_CASE(short_circuiting)
622 {
623 	char const* sourceCode = R"(
624 		contract test {
625 			function run(uint x) public returns(uint y) {
626 				x == 0 || ((x = 8) > 0);
627 				return x;
628 			}
629 		}
630 	)";
631 	ALSO_VIA_YUL(
632 		DISABLE_EWASM_TESTRUN()
633 
634 		compileAndRun(sourceCode);
635 
636 		auto short_circuiting_cpp = [](u256 n) -> u256
637 		{
638 			(void)(n == 0 || (n = 8) > 0);
639 			return n;
640 		};
641 
642 		testContractAgainstCppOnRange("run(uint256)", short_circuiting_cpp, 0, 2);
643 	)
644 }
645 
BOOST_AUTO_TEST_CASE(high_bits_cleaning)646 BOOST_AUTO_TEST_CASE(high_bits_cleaning)
647 {
648 	char const* sourceCode = R"(
649 		contract test {
650 			function run() public returns(uint256 y) {
651 				unchecked {
652 					uint32 t = uint32(0xffffffff);
653 					uint32 x = t + 10;
654 					if (x >= 0xffffffff) return 0;
655 					return x;
656 				}
657 			}
658 		}
659 	)";
660 	compileAndRun(sourceCode);
661 	auto high_bits_cleaning_cpp = []() -> u256
662 	{
663 		uint32_t t = uint32_t(0xffffffff);
664 		uint32_t x = t + 10;
665 		if (x >= 0xffffffff)
666 			return 0;
667 		return x;
668 	};
669 	testContractAgainstCpp("run()", high_bits_cleaning_cpp);
670 }
671 
BOOST_AUTO_TEST_CASE(sign_extension)672 BOOST_AUTO_TEST_CASE(sign_extension)
673 {
674 	char const* sourceCode = R"(
675 		contract test {
676 			function run() public returns(uint256 y) {
677 				unchecked {
678 					int64 x = -int32(int64(0xff));
679 					if (x >= 0xff) return 0;
680 					return 0 - uint256(int256(x));
681 				}
682 			}
683 		}
684 	)";
685 	compileAndRun(sourceCode);
686 	auto sign_extension_cpp = []() -> u256
687 	{
688 		int64_t x = -int32_t(0xff);
689 		if (x >= 0xff)
690 			return 0;
691 		return u256(x) * -1;
692 	};
693 	testContractAgainstCpp("run()", sign_extension_cpp);
694 }
695 
BOOST_AUTO_TEST_CASE(small_unsigned_types)696 BOOST_AUTO_TEST_CASE(small_unsigned_types)
697 {
698 	char const* sourceCode = R"(
699 		contract test {
700 			function run() public returns(uint256 y) {
701 				unchecked {
702 					uint32 t = uint32(0xffffff);
703 					uint32 x = t * 0xffffff;
704 					return x / 0x100;
705 				}
706 			}
707 		}
708 	)";
709 	compileAndRun(sourceCode);
710 	auto small_unsigned_types_cpp = []() -> u256
711 	{
712 		uint32_t t = uint32_t(0xffffff);
713 		uint32_t x = t * 0xffffff;
714 		return x / 0x100;
715 	};
716 	testContractAgainstCpp("run()", small_unsigned_types_cpp);
717 }
718 
BOOST_AUTO_TEST_CASE(mapping_state_inc_dec)719 BOOST_AUTO_TEST_CASE(mapping_state_inc_dec)
720 {
721 	char const* sourceCode = R"(
722 		contract test {
723 			uint value;
724 			mapping(uint => uint) table;
725 			function f(uint x) public returns (uint y) {
726 				value = x;
727 				if (x > 0) table[++value] = 8;
728 				if (x > 1) value--;
729 				if (x > 2) table[value]++;
730 				table[value] += 10;
731 				return --table[value++];
732 			}
733 		}
734 	)";
735 
736 	u256 value;
737 	map<u256, u256> table;
738 	auto f = [&](u256 const& _x) -> u256
739 	{
740 		value = _x;
741 		if (_x > 0)
742 			table[++value] = 8;
743 		if (_x > 1)
744 			value --;
745 		if (_x > 2)
746 			table[value]++;
747 		table[value] += 10;
748 		return --table[value++];
749 	};
750 	ALSO_VIA_YUL(
751 		DISABLE_EWASM_TESTRUN()
752 
753 		compileAndRun(sourceCode);
754 		value = 0;
755 		table.clear();
756 
757 		testContractAgainstCppOnRange("f(uint256)", f, 0, 5);
758 	)
759 }
760 
BOOST_AUTO_TEST_CASE(multi_level_mapping)761 BOOST_AUTO_TEST_CASE(multi_level_mapping)
762 {
763 	char const* sourceCode = R"(
764 		contract test {
765 			mapping(uint => mapping(uint => uint)) table;
766 			function f(uint x, uint y, uint z) public returns (uint w) {
767 				if (z == 0) return table[x][y];
768 				else return table[x][y] = z;
769 			}
770 		}
771 	)";
772 	map<u256, map<u256, u256>> table;
773 	auto f = [&](u256 const& _x, u256 const& _y, u256 const& _z) -> u256
774 	{
775 		if (_z == 0) return table[_x][_y];
776 		else return table[_x][_y] = _z;
777 	};
778 	ALSO_VIA_YUL(
779 		DISABLE_EWASM_TESTRUN()
780 
781 		compileAndRun(sourceCode);
782 		table.clear();
783 
784 		testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
785 		testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
786 		testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(9));
787 		testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
788 		testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
789 		testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(7));
790 		testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
791 		testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
792 	)
793 }
794 
BOOST_AUTO_TEST_CASE(constructor)795 BOOST_AUTO_TEST_CASE(constructor)
796 {
797 	char const* sourceCode = R"(
798 		contract test {
799 			mapping(uint => uint) data;
800 			constructor() {
801 				data[7] = 8;
802 			}
803 			function get(uint key) public returns (uint value) {
804 				return data[key];
805 			}
806 		}
807 	)";
808 
809 	map<u256, uint8_t> data;
810 	data[7] = 8;
811 	auto get = [&](u256 const& _x) -> u256
812 	{
813 		return data[_x];
814 	};
815 
816 	ALSO_VIA_YUL(
817 		DISABLE_EWASM_TESTRUN()
818 
819 		compileAndRun(sourceCode);
820 		testContractAgainstCpp("get(uint256)", get, u256(6));
821 		testContractAgainstCpp("get(uint256)", get, u256(7));
822 	)
823 }
824 
BOOST_AUTO_TEST_CASE(send_ether)825 BOOST_AUTO_TEST_CASE(send_ether)
826 {
827 	char const* sourceCode = R"(
828 		contract test {
829 			constructor() payable {}
830 			function a(address payable addr, uint amount) public returns (uint ret) {
831 				addr.send(amount);
832 				return address(this).balance;
833 			}
834 		}
835 	)";
836 	ALSO_VIA_YUL(
837 		DISABLE_EWASM_TESTRUN()
838 
839 		u256 amount(250);
840 		compileAndRun(sourceCode, amount + 1);
841 		h160 address(23);
842 		ABI_CHECK(callContractFunction("a(address,uint256)", address, amount), encodeArgs(1));
843 		BOOST_CHECK_EQUAL(balanceAt(address), amount);
844 	)
845 }
846 
BOOST_AUTO_TEST_CASE(transfer_ether)847 BOOST_AUTO_TEST_CASE(transfer_ether)
848 {
849 	char const* sourceCode = R"(
850 		contract A {
851 			constructor() payable {}
852 			function a(address payable addr, uint amount) public returns (uint) {
853 				addr.transfer(amount);
854 				return address(this).balance;
855 			}
856 			function b(address payable addr, uint amount) public {
857 				addr.transfer(amount);
858 			}
859 		}
860 
861 		contract B {
862 		}
863 
864 		contract C {
865 			receive () external payable {
866 				revert();
867 			}
868 		}
869 	)";
870 	ALSO_VIA_YUL(
871 		DISABLE_EWASM_TESTRUN()
872 
873 		compileAndRun(sourceCode, 0, "B");
874 		h160 const nonPayableRecipient = m_contractAddress;
875 		compileAndRun(sourceCode, 0, "C");
876 		h160 const oogRecipient = m_contractAddress;
877 		compileAndRun(sourceCode, 20, "A");
878 		h160 payableRecipient(23);
879 		ABI_CHECK(callContractFunction("a(address,uint256)", payableRecipient, 10), encodeArgs(10));
880 		BOOST_CHECK_EQUAL(balanceAt(payableRecipient), 10);
881 		BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10);
882 		ABI_CHECK(callContractFunction("b(address,uint256)", nonPayableRecipient, 10), encodeArgs());
883 		ABI_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10), encodeArgs());
884 	)
885 }
886 
BOOST_AUTO_TEST_CASE(selfdestruct)887 BOOST_AUTO_TEST_CASE(selfdestruct)
888 {
889 	char const* sourceCode = R"(
890 		contract test {
891 			constructor() payable {}
892 			function a(address payable receiver) public returns (uint ret) {
893 				selfdestruct(receiver);
894 				return 10;
895 			}
896 		}
897 	)";
898 	u256 amount(130);
899 	h160 address(23);
900 	ALSO_VIA_YUL(
901 		DISABLE_EWASM_TESTRUN()
902 
903 		compileAndRun(sourceCode, amount);
904 		ABI_CHECK(callContractFunction("a(address)", address), bytes());
905 		BOOST_CHECK(!addressHasCode(m_contractAddress));
906 		BOOST_CHECK_EQUAL(balanceAt(address), amount);
907 	)
908 }
909 
BOOST_AUTO_TEST_CASE(keccak256)910 BOOST_AUTO_TEST_CASE(keccak256)
911 {
912 	char const* sourceCode = R"(
913 		contract test {
914 			function a(bytes32 input) public returns (bytes32 hash) {
915 				return keccak256(abi.encodePacked(input));
916 			}
917 		}
918 	)";
919 	ALSO_VIA_YUL(
920 		DISABLE_EWASM_TESTRUN()
921 		compileAndRun(sourceCode);
922 		auto f = [&](u256 const& _x) -> u256
923 		{
924 			return util::keccak256(toBigEndian(_x));
925 		};
926 		testContractAgainstCpp("a(bytes32)", f, u256(4));
927 		testContractAgainstCpp("a(bytes32)", f, u256(5));
928 		testContractAgainstCpp("a(bytes32)", f, u256(-1));
929 	);
930 }
931 
BOOST_AUTO_TEST_CASE(sha256)932 BOOST_AUTO_TEST_CASE(sha256)
933 {
934 	char const* sourceCode = R"(
935 		contract test {
936 			function a(bytes32 input) public returns (bytes32 sha256hash) {
937 				return sha256(abi.encodePacked(input));
938 			}
939 		}
940 	)";
941 	auto f = [&](u256 const& _x) -> bytes
942 	{
943 		if (_x == u256(4))
944 			return fromHex("e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f");
945 		if (_x == u256(5))
946 			return fromHex("96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47");
947 		if (_x == u256(-1))
948 			return fromHex("af9613760f72635fbdb44a5a0a63c39f12af30f950a6ee5c971be188e89c4051");
949 		return fromHex("");
950 	};
951 	ALSO_VIA_YUL(
952 		DISABLE_EWASM_TESTRUN()
953 		compileAndRun(sourceCode);
954 		testContractAgainstCpp("a(bytes32)", f, u256(4));
955 		testContractAgainstCpp("a(bytes32)", f, u256(5));
956 		testContractAgainstCpp("a(bytes32)", f, u256(-1));
957 	)
958 }
959 
BOOST_AUTO_TEST_CASE(ripemd)960 BOOST_AUTO_TEST_CASE(ripemd)
961 {
962 	char const* sourceCode = R"(
963 		contract test {
964 			function a(bytes32 input) public returns (bytes32 sha256hash) {
965 				return ripemd160(abi.encodePacked(input));
966 			}
967 		}
968 	)";
969 	auto f = [&](u256 const& _x) -> bytes
970 	{
971 		if (_x == u256(4))
972 			return fromHex("1b0f3c404d12075c68c938f9f60ebea4f74941a0000000000000000000000000");
973 		if (_x == u256(5))
974 			return fromHex("ee54aa84fc32d8fed5a5fe160442ae84626829d9000000000000000000000000");
975 		if (_x == u256(-1))
976 			return fromHex("1cf4e77f5966e13e109703cd8a0df7ceda7f3dc3000000000000000000000000");
977 		return fromHex("");
978 	};
979 	ALSO_VIA_YUL(
980 		DISABLE_EWASM_TESTRUN()
981 		compileAndRun(sourceCode);
982 		testContractAgainstCpp("a(bytes32)", f, u256(4));
983 		testContractAgainstCpp("a(bytes32)", f, u256(5));
984 		testContractAgainstCpp("a(bytes32)", f, u256(-1));
985 	)
986 }
987 
BOOST_AUTO_TEST_CASE(packed_keccak256)988 BOOST_AUTO_TEST_CASE(packed_keccak256)
989 {
990 	char const* sourceCode = R"(
991 		contract test {
992 			function a(bytes32 input) public returns (bytes32 hash) {
993 				uint24 b = 65536;
994 				uint c = 256;
995 				return keccak256(abi.encodePacked(uint8(8), input, b, input, c));
996 			}
997 		}
998 	)";
999 	auto f = [&](u256 const& _x) -> u256
1000 	{
1001 		return util::keccak256(
1002 			toCompactBigEndian(unsigned(8)) +
1003 			toBigEndian(_x) +
1004 			toCompactBigEndian(unsigned(65536)) +
1005 			toBigEndian(_x) +
1006 			toBigEndian(u256(256))
1007 		);
1008 	};
1009 	ALSO_VIA_YUL(
1010 		DISABLE_EWASM_TESTRUN()
1011 		compileAndRun(sourceCode);
1012 		testContractAgainstCpp("a(bytes32)", f, u256(4));
1013 		testContractAgainstCpp("a(bytes32)", f, u256(5));
1014 		testContractAgainstCpp("a(bytes32)", f, u256(-1));
1015 	)
1016 }
1017 
BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types)1018 BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types)
1019 {
1020 	char const* sourceCode = R"(
1021 		contract test {
1022 			uint120[3] x;
1023 			function f() public returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) {
1024 				uint120[] memory y = new uint120[](3);
1025 				x[0] = y[0] = uint120(type(uint).max - 1);
1026 				x[1] = y[1] = uint120(type(uint).max - 2);
1027 				x[2] = y[2] = uint120(type(uint).max - 3);
1028 				hash1 = keccak256(abi.encodePacked(x));
1029 				hash2 = keccak256(abi.encodePacked(y));
1030 				hash3 = keccak256(abi.encodePacked(this.f));
1031 			}
1032 		}
1033 	)";
1034 	ALSO_VIA_YUL(
1035 		DISABLE_EWASM_TESTRUN()
1036 		compileAndRun(sourceCode);
1037 		// Strangely, arrays are encoded with intra-element padding.
1038 		ABI_CHECK(callContractFunction("f()"), encodeArgs(
1039 			util::keccak256(encodeArgs(u256("0xfffffffffffffffffffffffffffffe"), u256("0xfffffffffffffffffffffffffffffd"), u256("0xfffffffffffffffffffffffffffffc"))),
1040 			util::keccak256(encodeArgs(u256("0xfffffffffffffffffffffffffffffe"), u256("0xfffffffffffffffffffffffffffffd"), u256("0xfffffffffffffffffffffffffffffc"))),
1041 			util::keccak256(fromHex(m_contractAddress.hex() + "26121ff0"))
1042 		));
1043 	)
1044 }
1045 
BOOST_AUTO_TEST_CASE(packed_sha256)1046 BOOST_AUTO_TEST_CASE(packed_sha256)
1047 {
1048 	char const* sourceCode = R"(
1049 		contract test {
1050 			function a(bytes32 input) public returns (bytes32 hash) {
1051 				uint24 b = 65536;
1052 				uint c = 256;
1053 				return sha256(abi.encodePacked(uint8(8), input, b, input, c));
1054 			}
1055 		}
1056 	)";
1057 	auto f = [&](u256 const& _x) -> bytes
1058 	{
1059 		if (_x == u256(4))
1060 			return fromHex("804e0d7003cfd70fc925dc103174d9f898ebb142ecc2a286da1abd22ac2ce3ac");
1061 		if (_x == u256(5))
1062 			return fromHex("e94921945f9068726c529a290a954f412bcac53184bb41224208a31edbf63cf0");
1063 		if (_x == u256(-1))
1064 			return fromHex("f14def4d07cd185ddd8b10a81b2238326196a38867e6e6adbcc956dc913488c7");
1065 		return fromHex("");
1066 	};
1067 	ALSO_VIA_YUL(
1068 		DISABLE_EWASM_TESTRUN()
1069 		compileAndRun(sourceCode);
1070 		testContractAgainstCpp("a(bytes32)", f, u256(4));
1071 		testContractAgainstCpp("a(bytes32)", f, u256(5));
1072 		testContractAgainstCpp("a(bytes32)", f, u256(-1));
1073 	)
1074 }
1075 
BOOST_AUTO_TEST_CASE(packed_ripemd160)1076 BOOST_AUTO_TEST_CASE(packed_ripemd160)
1077 {
1078 	char const* sourceCode = R"(
1079 		contract test {
1080 			function a(bytes32 input) public returns (bytes32 hash) {
1081 				uint24 b = 65536;
1082 				uint c = 256;
1083 				return ripemd160(abi.encodePacked(uint8(8), input, b, input, c));
1084 			}
1085 		}
1086 	)";
1087 	auto f = [&](u256 const& _x) -> bytes
1088 	{
1089 		if (_x == u256(4))
1090 			return fromHex("f93175303eba2a7b372174fc9330237f5ad202fc000000000000000000000000");
1091 		if (_x == u256(5))
1092 			return fromHex("04f4fc112e2bfbe0d38f896a46629e08e2fcfad5000000000000000000000000");
1093 		if (_x == u256(-1))
1094 			return fromHex("c0a2e4b1f3ff766a9a0089e7a410391730872495000000000000000000000000");
1095 		return fromHex("");
1096 	};
1097 	ALSO_VIA_YUL(
1098 		DISABLE_EWASM_TESTRUN()
1099 		compileAndRun(sourceCode);
1100 		testContractAgainstCpp("a(bytes32)", f, u256(4));
1101 		testContractAgainstCpp("a(bytes32)", f, u256(5));
1102 		testContractAgainstCpp("a(bytes32)", f, u256(-1));
1103 	)
1104 }
1105 
BOOST_AUTO_TEST_CASE(inter_contract_calls)1106 BOOST_AUTO_TEST_CASE(inter_contract_calls)
1107 {
1108 	char const* sourceCode = R"(
1109 		contract Helper {
1110 			function multiply(uint a, uint b) public returns (uint c) {
1111 				return a * b;
1112 			}
1113 		}
1114 		contract Main {
1115 			Helper h;
1116 			function callHelper(uint a, uint b) public returns (uint c) {
1117 				return h.multiply(a, b);
1118 			}
1119 			function getHelper() public returns (address haddress) {
1120 				return address(h);
1121 			}
1122 			function setHelper(address haddress) public {
1123 				h = Helper(haddress);
1124 			}
1125 		}
1126 	)";
1127 	compileAndRun(sourceCode, 0, "Helper");
1128 	h160 const c_helperAddress = m_contractAddress;
1129 	compileAndRun(sourceCode, 0, "Main");
1130 	BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes());
1131 	BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress));
1132 	u256 a(3456789);
1133 	u256 b("0x282837623374623234aa74");
1134 	BOOST_REQUIRE(callContractFunction("callHelper(uint256,uint256)", a, b) == encodeArgs(a * b));
1135 }
1136 
BOOST_AUTO_TEST_CASE(inter_contract_calls_with_complex_parameters)1137 BOOST_AUTO_TEST_CASE(inter_contract_calls_with_complex_parameters)
1138 {
1139 	char const* sourceCode = R"(
1140 		contract Helper {
1141 			function sel(uint a, bool select, uint b) public returns (uint c) {
1142 				if (select) return a; else return b;
1143 			}
1144 		}
1145 		contract Main {
1146 			Helper h;
1147 			function callHelper(uint a, bool select, uint b) public returns (uint c) {
1148 				return h.sel(a, select, b) * 3;
1149 			}
1150 			function getHelper() public returns (address haddress) {
1151 				return address(h);
1152 			}
1153 			function setHelper(address haddress) public {
1154 				h = Helper(haddress);
1155 			}
1156 		}
1157 	)";
1158 	compileAndRun(sourceCode, 0, "Helper");
1159 	h160 const c_helperAddress = m_contractAddress;
1160 	compileAndRun(sourceCode, 0, "Main");
1161 	BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes());
1162 	BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress));
1163 	u256 a(3456789);
1164 	u256 b("0x282837623374623234aa74");
1165 	BOOST_REQUIRE(callContractFunction("callHelper(uint256,bool,uint256)", a, true, b) == encodeArgs(a * 3));
1166 	BOOST_REQUIRE(callContractFunction("callHelper(uint256,bool,uint256)", a, false, b) == encodeArgs(b * 3));
1167 }
1168 
BOOST_AUTO_TEST_CASE(inter_contract_calls_accessing_this)1169 BOOST_AUTO_TEST_CASE(inter_contract_calls_accessing_this)
1170 {
1171 	char const* sourceCode = R"(
1172 		contract Helper {
1173 			function getAddress() public returns (address addr) {
1174 				return address(this);
1175 			}
1176 		}
1177 		contract Main {
1178 			Helper h;
1179 			function callHelper() public returns (address addr) {
1180 				return h.getAddress();
1181 			}
1182 			function getHelper() public returns (address addr) {
1183 				return address(h);
1184 			}
1185 			function setHelper(address addr) public {
1186 				h = Helper(addr);
1187 			}
1188 		}
1189 	)";
1190 	compileAndRun(sourceCode, 0, "Helper");
1191 	h160 const c_helperAddress = m_contractAddress;
1192 	compileAndRun(sourceCode, 0, "Main");
1193 	BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes());
1194 	BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress));
1195 	BOOST_REQUIRE(callContractFunction("callHelper()") == encodeArgs(c_helperAddress));
1196 }
1197 
BOOST_AUTO_TEST_CASE(calls_to_this)1198 BOOST_AUTO_TEST_CASE(calls_to_this)
1199 {
1200 	char const* sourceCode = R"(
1201 		contract Helper {
1202 			function invoke(uint a, uint b) public returns (uint c) {
1203 				return this.multiply(a, b, 10);
1204 			}
1205 			function multiply(uint a, uint b, uint8 c) public returns (uint ret) {
1206 				return a * b + c;
1207 			}
1208 		}
1209 		contract Main {
1210 			Helper h;
1211 			function callHelper(uint a, uint b) public returns (uint ret) {
1212 				return h.invoke(a, b);
1213 			}
1214 			function getHelper() public returns (address addr) {
1215 				return address(h);
1216 			}
1217 			function setHelper(address addr) public {
1218 				h = Helper(addr);
1219 			}
1220 		}
1221 	)";
1222 	compileAndRun(sourceCode, 0, "Helper");
1223 	h160 const c_helperAddress = m_contractAddress;
1224 	compileAndRun(sourceCode, 0, "Main");
1225 	BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes());
1226 	BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress));
1227 	u256 a(3456789);
1228 	u256 b("0x282837623374623234aa74");
1229 	BOOST_REQUIRE(callContractFunction("callHelper(uint256,uint256)", a, b) == encodeArgs(a * b + 10));
1230 }
1231 
BOOST_AUTO_TEST_CASE(inter_contract_calls_with_local_vars)1232 BOOST_AUTO_TEST_CASE(inter_contract_calls_with_local_vars)
1233 {
1234 	// note that a reference to another contract's function occupies two stack slots,
1235 	// so this tests correct stack slot allocation
1236 	char const* sourceCode = R"(
1237 		contract Helper {
1238 			function multiply(uint a, uint b) public returns (uint c) {
1239 				return a * b;
1240 			}
1241 		}
1242 		contract Main {
1243 			Helper h;
1244 			function callHelper(uint a, uint b) public returns (uint c) {
1245 				uint8 y = 9;
1246 				uint256 ret = h.multiply(a, b);
1247 				return ret + y;
1248 			}
1249 			function getHelper() public returns (address haddress) {
1250 				return address(h);
1251 			}
1252 			function setHelper(address haddress) public {
1253 				h = Helper(haddress);
1254 			}
1255 		}
1256 	)";
1257 	compileAndRun(sourceCode, 0, "Helper");
1258 	h160 const c_helperAddress = m_contractAddress;
1259 	compileAndRun(sourceCode, 0, "Main");
1260 	BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes());
1261 	BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress));
1262 	u256 a(3456789);
1263 	u256 b("0x282837623374623234aa74");
1264 	BOOST_REQUIRE(callContractFunction("callHelper(uint256,uint256)", a, b) == encodeArgs(a * b + 9));
1265 }
1266 
BOOST_AUTO_TEST_CASE(fixed_bytes_in_calls)1267 BOOST_AUTO_TEST_CASE(fixed_bytes_in_calls)
1268 {
1269 	char const* sourceCode = R"(
1270 		contract Helper {
1271 			function invoke(bytes3 x, bool stop) public returns (bytes4 ret) {
1272 				return x;
1273 			}
1274 		}
1275 		contract Main {
1276 			Helper h;
1277 			function callHelper(bytes2 x, bool stop) public returns (bytes5 ret) {
1278 				return h.invoke(x, stop);
1279 			}
1280 			function getHelper() public returns (address addr) {
1281 				return address(h);
1282 			}
1283 			function setHelper(address addr) public {
1284 				h = Helper(addr);
1285 			}
1286 		}
1287 	)";
1288 	compileAndRun(sourceCode, 0, "Helper");
1289 	h160 const c_helperAddress = m_contractAddress;
1290 	compileAndRun(sourceCode, 0, "Main");
1291 	BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes());
1292 	BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress));
1293 	ABI_CHECK(callContractFunction("callHelper(bytes2,bool)", string("\0a", 2), true), encodeArgs(string("\0a\0\0\0", 5)));
1294 }
1295 
BOOST_AUTO_TEST_CASE(constructor_with_long_arguments)1296 BOOST_AUTO_TEST_CASE(constructor_with_long_arguments)
1297 {
1298 	char const* sourceCode = R"(
1299 		contract Main {
1300 			string public a;
1301 			string public b;
1302 
1303 			constructor(string memory _a, string memory _b) {
1304 				a = _a;
1305 				b = _b;
1306 			}
1307 		}
1308 	)";
1309 	string a = "01234567890123gabddunaouhdaoneudapcgadi4567890789012oneudapcgadi4567890789012oneudapcgadi4567890789012oneudapcgadi4567890789012oneudapcgadi4567890789012oneudapcgadi4567890789012oneudapcgadi4567890789012oneudapcgadi45678907890123456789abcd123456787890123456789abcd90123456789012345678901234567890123456789aboneudapcgadi4567890789012oneudapcgadi4567890789012oneudapcgadi45678907890123456789abcd123456787890123456789abcd90123456789012345678901234567890123456789aboneudapcgadi4567890789012oneudapcgadi4567890789012oneudapcgadi45678907890123456789abcd123456787890123456789abcd90123456789012345678901234567890123456789aboneudapcgadi4567890789012cdef";
1310 	string b = "AUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PYAUTAHIACIANOTUHAOCUHAOEUNAOEHUNTHDYDHPYDRCPYDRSTITOEUBXHUDGO>PY";
1311 
1312 	compileAndRun(sourceCode, 0, "Main", encodeArgs(
1313 		u256(0x40),
1314 		u256(0x40 + 0x20 + ((a.length() + 31) / 32) * 32),
1315 		u256(a.length()),
1316 		a,
1317 		u256(b.length()),
1318 		b
1319 	));
1320 	ABI_CHECK(callContractFunction("a()"), encodeDyn(a));
1321 	ABI_CHECK(callContractFunction("b()"), encodeDyn(b));
1322 }
1323 
BOOST_AUTO_TEST_CASE(contracts_as_addresses)1324 BOOST_AUTO_TEST_CASE(contracts_as_addresses)
1325 {
1326 	char const* sourceCode = R"(
1327 		contract helper {
1328 			receive() external payable { } // can receive ether
1329 		}
1330 		contract test {
1331 			helper h;
1332 			constructor() payable { h = new helper(); payable(h).send(5); }
1333 			function getBalance() public returns (uint256 myBalance, uint256 helperBalance) {
1334 				myBalance = address(this).balance;
1335 				helperBalance = address(h).balance;
1336 			}
1337 		}
1338 	)";
1339 	compileAndRun(sourceCode, 20);
1340 	BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 20 - 5);
1341 	BOOST_REQUIRE(callContractFunction("getBalance()") == encodeArgs(u256(20 - 5), u256(5)));
1342 }
1343 
BOOST_AUTO_TEST_CASE(blockhash)1344 BOOST_AUTO_TEST_CASE(blockhash)
1345 {
1346 	char const* sourceCode = R"(
1347 		contract C {
1348 			uint256 counter;
1349 			function g() public returns (bool) { counter++; return true; }
1350 			function f() public returns (bytes32[] memory r) {
1351 				r = new bytes32[](259);
1352 				for (uint i = 0; i < 259; i++) {
1353 					unchecked {
1354 						r[i] = blockhash(block.number - 257 + i);
1355 					}
1356 				}
1357 			}
1358 		}
1359 	)";
1360 	compileAndRun(sourceCode);
1361 	// generate a sufficient amount of blocks
1362 	while (blockNumber() < u256(255))
1363 		ABI_CHECK(callContractFunction("g()"), encodeArgs(true));
1364 
1365 	vector<u256> hashes;
1366 	// ``blockhash()`` is only valid for the last 256 blocks, otherwise zero
1367 	hashes.emplace_back(0);
1368 	for (u256 i = blockNumber() - u256(255); i <= blockNumber(); i++)
1369 		hashes.emplace_back(blockHash(i));
1370 	// the current block hash is not yet known at execution time and therefore zero
1371 	hashes.emplace_back(0);
1372 	// future block hashes are zero
1373 	hashes.emplace_back(0);
1374 
1375 	ABI_CHECK(callContractFunction("f()"), encodeDyn(hashes));
1376 }
1377 
BOOST_AUTO_TEST_CASE(internal_constructor)1378 BOOST_AUTO_TEST_CASE(internal_constructor)
1379 {
1380 	char const* sourceCode = R"(
1381 		abstract contract C {
1382 			constructor() {}
1383 		}
1384 	)";
1385 	// via yul disabled because it will throw an error instead of
1386 	// returning empty bytecode.
1387 	BOOST_CHECK(compileAndRunWithoutCheck({{"", sourceCode}}, 0, "C").empty());
1388 }
1389 
BOOST_AUTO_TEST_CASE(default_fallback_throws)1390 BOOST_AUTO_TEST_CASE(default_fallback_throws)
1391 {
1392 	char const* sourceCode = R"YY(
1393 		contract A {
1394 			function f() public returns (bool) {
1395 				(bool success,) = address(this).call("");
1396 				return success;
1397 			}
1398 		}
1399 	)YY";
1400 	compileAndRun(sourceCode);
1401 	ABI_CHECK(callContractFunction("f()"), encodeArgs(0));
1402 
1403 	if (solidity::test::CommonOptions::get().evmVersion().hasStaticCall())
1404 	{
1405 		char const* sourceCode = R"YY(
1406 			contract A {
1407 				function f() public returns (bool) {
1408 					(bool success, bytes memory data) = address(this).staticcall("");
1409 					assert(data.length == 0);
1410 					return success;
1411 				}
1412 			}
1413 		)YY";
1414 		compileAndRun(sourceCode);
1415 		ABI_CHECK(callContractFunction("f()"), encodeArgs(0));
1416 	}
1417 }
1418 
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)1419 BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
1420 {
1421 	char const* sourceCode = R"(
1422 		contract test {
1423 			function f(uint, uint k) public returns(uint ret_k, uint ret_g){
1424 				uint g = 8;
1425 				ret_k = k;
1426 				ret_g = g;
1427 			}
1428 		}
1429 	)";
1430 	ALSO_VIA_YUL(
1431 		DISABLE_EWASM_TESTRUN()
1432 
1433 		compileAndRun(sourceCode);
1434 		BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8));
1435 		ABI_CHECK(callContractFunction("f(uint256,uint256)", 5, 9), encodeArgs(9, 8));
1436 	)
1437 }
1438 
BOOST_AUTO_TEST_CASE(generic_call)1439 BOOST_AUTO_TEST_CASE(generic_call)
1440 {
1441 	char const* sourceCode = R"**(
1442 			contract receiver {
1443 				uint public received;
1444 				function recv(uint256 x) public payable { received = x; }
1445 			}
1446 			contract sender {
1447 				constructor() payable {}
1448 				function doSend(address rec) public returns (uint d)
1449 				{
1450 					bytes4 signature = bytes4(bytes32(keccak256("recv(uint256)")));
1451 					rec.call{value: 2}(abi.encodeWithSelector(signature, 23));
1452 					return receiver(rec).received();
1453 				}
1454 			}
1455 	)**";
1456 	compileAndRun(sourceCode, 0, "receiver");
1457 	h160 const c_receiverAddress = m_contractAddress;
1458 	compileAndRun(sourceCode, 50, "sender");
1459 	BOOST_REQUIRE(callContractFunction("doSend(address)", c_receiverAddress) == encodeArgs(23));
1460 	BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 50 - 2);
1461 }
1462 
BOOST_AUTO_TEST_CASE(generic_delegatecall)1463 BOOST_AUTO_TEST_CASE(generic_delegatecall)
1464 {
1465 	char const* sourceCode = R"**(
1466 			contract Receiver {
1467 				uint public received;
1468 				address public sender;
1469 				uint public value;
1470 				constructor() payable {}
1471 				function recv(uint256 x) public payable { received = x; sender = msg.sender; value = msg.value; }
1472 			}
1473 			contract Sender {
1474 				uint public received;
1475 				address public sender;
1476 				uint public value;
1477 				constructor() payable {}
1478 				function doSend(address rec) public payable
1479 				{
1480 					bytes4 signature = bytes4(bytes32(keccak256("recv(uint256)")));
1481 					(bool success,) = rec.delegatecall(abi.encodeWithSelector(signature, 23));
1482 					success;
1483 				}
1484 			}
1485 	)**";
1486 
1487 	for (auto v2: {false, true})
1488 	{
1489 		string source = "pragma abicoder " + string(v2 ? "v2" : "v1") + ";\n" + string(sourceCode);
1490 
1491 		compileAndRun(source, 0, "Receiver");
1492 		h160 const c_receiverAddress = m_contractAddress;
1493 		compileAndRun(source, 50, "Sender");
1494 		h160 const c_senderAddress = m_contractAddress;
1495 		BOOST_CHECK(m_sender != c_senderAddress); // just for sanity
1496 		ABI_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress), encodeArgs());
1497 		ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(23)));
1498 		ABI_CHECK(callContractFunction("sender()"), encodeArgs(m_sender));
1499 		ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(11)));
1500 		m_contractAddress = c_receiverAddress;
1501 		ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(0)));
1502 		ABI_CHECK(callContractFunction("sender()"), encodeArgs(u256(0)));
1503 		ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(0)));
1504 		BOOST_CHECK(storageEmpty(c_receiverAddress));
1505 		BOOST_CHECK(!storageEmpty(c_senderAddress));
1506 		BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0);
1507 		BOOST_CHECK_EQUAL(balanceAt(c_senderAddress), 50 + 11);
1508 	}
1509 }
1510 
BOOST_AUTO_TEST_CASE(generic_staticcall)1511 BOOST_AUTO_TEST_CASE(generic_staticcall)
1512 {
1513 	if (solidity::test::CommonOptions::get().evmVersion().hasStaticCall())
1514 	{
1515 		char const* sourceCode = R"**(
1516 				contract A {
1517 					uint public x;
1518 					constructor() { x = 42; }
1519 					function pureFunction(uint256 p) public pure returns (uint256) { return p; }
1520 					function viewFunction(uint256 p) public view returns (uint256) { return p + x; }
1521 					function nonpayableFunction(uint256 p) public returns (uint256) { x = p; return x; }
1522 					function assertFunction(uint256 p) public view returns (uint256) { assert(x == p); return x; }
1523 				}
1524 				contract C {
1525 					function f(address a) public view returns (bool, bytes memory)
1526 					{
1527 						return a.staticcall(abi.encodeWithSignature("pureFunction(uint256)", 23));
1528 					}
1529 					function g(address a) public view returns (bool, bytes memory)
1530 					{
1531 						return a.staticcall(abi.encodeWithSignature("viewFunction(uint256)", 23));
1532 					}
1533 					function h(address a) public view returns (bool, bytes memory)
1534 					{
1535 						return a.staticcall(abi.encodeWithSignature("nonpayableFunction(uint256)", 23));
1536 					}
1537 					function i(address a, uint256 v) public view returns (bool, bytes memory)
1538 					{
1539 						return a.staticcall(abi.encodeWithSignature("assertFunction(uint256)", v));
1540 					}
1541 				}
1542 		)**";
1543 		compileAndRun(sourceCode, 0, "A");
1544 		h160 const c_addressA = m_contractAddress;
1545 		compileAndRun(sourceCode, 0, "C");
1546 		ABI_CHECK(callContractFunction("f(address)", c_addressA), encodeArgs(true, 0x40, 0x20, 23));
1547 		ABI_CHECK(callContractFunction("g(address)", c_addressA), encodeArgs(true, 0x40, 0x20, 23 + 42));
1548 		ABI_CHECK(callContractFunction("h(address)", c_addressA), encodeArgs(false, 0x40, 0x00));
1549 		ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 42), encodeArgs(true, 0x40, 0x20, 42));
1550 		ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 23), encodeArgs(false, 0x40, 0x24) + panicData(PanicCode::Assert) + bytes(32 - 4, 0));
1551 	}
1552 }
1553 
BOOST_AUTO_TEST_CASE(library_call_protection)1554 BOOST_AUTO_TEST_CASE(library_call_protection)
1555 {
1556 	// This tests code that reverts a call if it is a direct call to a library
1557 	// as opposed to a delegatecall.
1558 	char const* sourceCode = R"(
1559 		library Lib {
1560 			struct S { uint x; }
1561 			// a direct call to this should revert
1562 			function np(S storage s) public returns (address) { s.x = 3; return msg.sender; }
1563 			// a direct call to this is fine
1564 			function v(S storage) public view returns (address) { return msg.sender; }
1565 			// a direct call to this is fine
1566 			function pu() public pure returns (uint) { return 2; }
1567 		}
1568 		contract Test {
1569 			Lib.S public s;
1570 			function np() public returns (address) { return Lib.np(s); }
1571 			function v() public view returns (address) { return Lib.v(s); }
1572 			function pu() public pure returns (uint) { return Lib.pu(); }
1573 		}
1574 	)";
1575 	ALSO_VIA_YUL(
1576 		DISABLE_EWASM_TESTRUN()
1577 		compileAndRun(sourceCode, 0, "Lib");
1578 		ABI_CHECK(callContractFunction("np(Lib.S storage)", 0), encodeArgs());
1579 		ABI_CHECK(callContractFunction("v(Lib.S storage)", 0), encodeArgs(m_sender));
1580 		ABI_CHECK(callContractFunction("pu()"), encodeArgs(2));
1581 		compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
1582 		ABI_CHECK(callContractFunction("s()"), encodeArgs(0));
1583 		ABI_CHECK(callContractFunction("np()"), encodeArgs(m_sender));
1584 		ABI_CHECK(callContractFunction("s()"), encodeArgs(3));
1585 		ABI_CHECK(callContractFunction("v()"), encodeArgs(m_sender));
1586 		ABI_CHECK(callContractFunction("pu()"), encodeArgs(2));
1587 	)
1588 }
1589 
BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory)1590 BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory)
1591 {
1592 	char const* sourceCode = R"(
1593 		contract C {
1594 			function f() public returns (bytes32) {
1595 				return keccak256(abi.encodePacked("abc", msg.data));
1596 			}
1597 		}
1598 	)";
1599 	ALSO_VIA_YUL(
1600 		DISABLE_EWASM_TESTRUN();
1601 		compileAndRun(sourceCode);
1602 		bytes calldata1 = FixedHash<4>(util::keccak256("f()")).asBytes() + bytes(61, 0x22) + bytes(12, 0x12);
1603 		sendMessage(calldata1, false);
1604 		BOOST_CHECK(m_transactionSuccessful);
1605 		BOOST_CHECK(m_output == encodeArgs(util::keccak256(bytes{'a', 'b', 'c'} + calldata1)));
1606 	);
1607 }
1608 
BOOST_AUTO_TEST_CASE(call_forward_bytes_length)1609 BOOST_AUTO_TEST_CASE(call_forward_bytes_length)
1610 {
1611 	char const* sourceCode = R"(
1612 		contract receiver {
1613 			uint public calledLength;
1614 			fallback() external { calledLength = msg.data.length; }
1615 		}
1616 		contract sender {
1617 			receiver rec;
1618 			constructor() { rec = new receiver(); }
1619 			function viaCalldata() public returns (uint) {
1620 				(bool success,) = address(rec).call(msg.data);
1621 				require(success);
1622 				return rec.calledLength();
1623 			}
1624 			function viaMemory() public returns (uint) {
1625 				bytes memory x = msg.data;
1626 				(bool success,) = address(rec).call(x);
1627 				require(success);
1628 				return rec.calledLength();
1629 			}
1630 			bytes s;
1631 			function viaStorage() public returns (uint) {
1632 				s = msg.data;
1633 				(bool success,) = address(rec).call(s);
1634 				require(success);
1635 				return rec.calledLength();
1636 			}
1637 		}
1638 	)";
1639 	ALSO_VIA_YUL(
1640 		DISABLE_EWASM_TESTRUN();
1641 		compileAndRun(sourceCode, 0, "sender");
1642 
1643 		// No additional data, just function selector
1644 		ABI_CHECK(callContractFunction("viaCalldata()"), encodeArgs(4));
1645 		ABI_CHECK(callContractFunction("viaMemory()"), encodeArgs(4));
1646 		ABI_CHECK(callContractFunction("viaStorage()"), encodeArgs(4));
1647 
1648 		// Some additional unpadded data
1649 		bytes unpadded = asBytes(string("abc"));
1650 		ABI_CHECK(callContractFunctionNoEncoding("viaCalldata()", unpadded), encodeArgs(7));
1651 		ABI_CHECK(callContractFunctionNoEncoding("viaMemory()", unpadded), encodeArgs(7));
1652 		ABI_CHECK(callContractFunctionNoEncoding("viaStorage()", unpadded), encodeArgs(7));
1653 	);
1654 }
1655 
BOOST_AUTO_TEST_CASE(copying_bytes_multiassign)1656 BOOST_AUTO_TEST_CASE(copying_bytes_multiassign)
1657 {
1658 	char const* sourceCode = R"(
1659 		contract receiver {
1660 			uint public received;
1661 			function recv(uint x) public { received += x + 1; }
1662 			fallback() external { received = 0x80; }
1663 		}
1664 		contract sender {
1665 			constructor() { rec = new receiver(); }
1666 			fallback() external { savedData1 = savedData2 = msg.data; }
1667 			function forward(bool selector) public returns (bool) {
1668 				if (selector) { address(rec).call(savedData1); delete savedData1; }
1669 				else { address(rec).call(savedData2); delete savedData2; }
1670 				return true;
1671 			}
1672 			function val() public returns (uint) { return rec.received(); }
1673 			receiver rec;
1674 			bytes savedData1;
1675 			bytes savedData2;
1676 		}
1677 	)";
1678 	ALSO_VIA_YUL(
1679 		DISABLE_EWASM_TESTRUN()
1680 		compileAndRun(sourceCode, 0, "sender");
1681 		ABI_CHECK(callContractFunction("recv(uint256)", 7), bytes());
1682 		ABI_CHECK(callContractFunction("val()"), encodeArgs(0));
1683 		ABI_CHECK(callContractFunction("forward(bool)", true), encodeArgs(true));
1684 		ABI_CHECK(callContractFunction("val()"), encodeArgs(8));
1685 		ABI_CHECK(callContractFunction("forward(bool)", false), encodeArgs(true));
1686 		ABI_CHECK(callContractFunction("val()"), encodeArgs(16));
1687 		ABI_CHECK(callContractFunction("forward(bool)", true), encodeArgs(true));
1688 		ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80));
1689 	);
1690 }
1691 
BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data)1692 BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data)
1693 {
1694 	char const* sourceCode = R"(
1695 		contract c {
1696 			function set() public returns (bool) { data = msg.data; return true; }
1697 			fallback() external { data = msg.data; }
1698 			bytes data;
1699 		}
1700 	)";
1701 	ALSO_VIA_YUL(
1702 		DISABLE_EWASM_TESTRUN()
1703 		compileAndRun(sourceCode);
1704 		ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true));
1705 		BOOST_CHECK(!storageEmpty(m_contractAddress));
1706 		sendMessage(bytes(), false);
1707 		BOOST_CHECK(m_transactionSuccessful);
1708 		BOOST_CHECK(m_output.empty());
1709 		BOOST_CHECK(storageEmpty(m_contractAddress));
1710 	);
1711 }
1712 
BOOST_AUTO_TEST_CASE(struct_referencing)1713 BOOST_AUTO_TEST_CASE(struct_referencing)
1714 {
1715 	static char const* sourceCode = R"(
1716 		pragma abicoder v2;
1717 		interface I {
1718 			struct S { uint a; }
1719 		}
1720 		library L {
1721 			struct S { uint b; uint a; }
1722 			function f() public pure returns (S memory) {
1723 				S memory s;
1724 				s.a = 3;
1725 				return s;
1726 			}
1727 			function g() public pure returns (I.S memory) {
1728 				I.S memory s;
1729 				s.a = 4;
1730 				return s;
1731 			}
1732 			// argument-dependant lookup tests
1733 			function a(I.S memory) public pure returns (uint) { return 1; }
1734 			function a(S memory) public pure returns (uint) { return 2; }
1735 		}
1736 		contract C is I {
1737 			function f() public pure returns (S memory) {
1738 				S memory s;
1739 				s.a = 1;
1740 				return s;
1741 			}
1742 			function g() public pure returns (I.S memory) {
1743 				I.S memory s;
1744 				s.a = 2;
1745 				return s;
1746 			}
1747 			function h() public pure returns (L.S memory) {
1748 				L.S memory s;
1749 				s.a = 5;
1750 				return s;
1751 			}
1752 			function x() public pure returns (L.S memory) {
1753 				return L.f();
1754 			}
1755 			function y() public pure returns (I.S memory) {
1756 				return L.g();
1757 			}
1758 			function a1() public pure returns (uint) { S memory s; return L.a(s); }
1759 			function a2() public pure returns (uint) { L.S memory s; return L.a(s); }
1760 		}
1761 	)";
1762 	ALSO_VIA_YUL(
1763 		DISABLE_EWASM_TESTRUN()
1764 		compileAndRun(sourceCode, 0, "L");
1765 		ABI_CHECK(callContractFunction("f()"), encodeArgs(0, 3));
1766 		ABI_CHECK(callContractFunction("g()"), encodeArgs(4));
1767 		compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{ {":L", m_contractAddress}});
1768 		ABI_CHECK(callContractFunction("f()"), encodeArgs(1));
1769 		ABI_CHECK(callContractFunction("g()"), encodeArgs(2));
1770 		ABI_CHECK(callContractFunction("h()"), encodeArgs(0, 5));
1771 		ABI_CHECK(callContractFunction("x()"), encodeArgs(0, 3));
1772 		ABI_CHECK(callContractFunction("y()"), encodeArgs(4));
1773 		ABI_CHECK(callContractFunction("a1()"), encodeArgs(1));
1774 		ABI_CHECK(callContractFunction("a2()"), encodeArgs(2));
1775 	)
1776 }
1777 
BOOST_AUTO_TEST_CASE(enum_referencing)1778 BOOST_AUTO_TEST_CASE(enum_referencing)
1779 {
1780 	char const* sourceCode = R"(
1781 		interface I {
1782 			enum Direction { A, B, Left, Right }
1783 		}
1784 		library L {
1785 			enum Direction { Left, Right }
1786 			function f() public pure returns (Direction) {
1787 				return Direction.Right;
1788 			}
1789 			function g() public pure returns (I.Direction) {
1790 				return I.Direction.Right;
1791 			}
1792 		}
1793 		contract C is I {
1794 			function f() public pure returns (Direction) {
1795 				return Direction.Right;
1796 			}
1797 			function g() public pure returns (I.Direction) {
1798 				return I.Direction.Right;
1799 			}
1800 			function h() public pure returns (L.Direction) {
1801 				return L.Direction.Right;
1802 			}
1803 			function x() public pure returns (L.Direction) {
1804 				return L.f();
1805 			}
1806 			function y() public pure returns (I.Direction) {
1807 				return L.g();
1808 			}
1809 		}
1810 	)";
1811 	ALSO_VIA_YUL(
1812 		DISABLE_EWASM_TESTRUN()
1813 		compileAndRun(sourceCode, 0, "L");
1814 		ABI_CHECK(callContractFunction("f()"), encodeArgs(1));
1815 		ABI_CHECK(callContractFunction("g()"), encodeArgs(3));
1816 		compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{{":L", m_contractAddress}});
1817 		ABI_CHECK(callContractFunction("f()"), encodeArgs(3));
1818 		ABI_CHECK(callContractFunction("g()"), encodeArgs(3));
1819 		ABI_CHECK(callContractFunction("h()"), encodeArgs(1));
1820 		ABI_CHECK(callContractFunction("x()"), encodeArgs(1));
1821 		ABI_CHECK(callContractFunction("y()"), encodeArgs(3));
1822 	)
1823 }
1824 
BOOST_AUTO_TEST_CASE(bytes_in_arguments)1825 BOOST_AUTO_TEST_CASE(bytes_in_arguments)
1826 {
1827 	char const* sourceCode = R"(
1828 		contract c {
1829 			uint result;
1830 			function f(uint a, uint b) public { result += a + b; }
1831 			function g(uint a) public { result *= a; }
1832 			function test(uint a, bytes calldata data1, bytes calldata data2, uint b) external returns (uint r_a, uint r, uint r_b, uint l) {
1833 				r_a = a;
1834 				address(this).call(data1);
1835 				address(this).call(data2);
1836 				r = result;
1837 				r_b = b;
1838 				l = data1.length;
1839 			}
1840 		}
1841 	)";
1842 	ALSO_VIA_YUL(
1843 		DISABLE_EWASM_TESTRUN()
1844 
1845 		compileAndRun(sourceCode);
1846 
1847 		string innercalldata1 = asString(FixedHash<4>(util::keccak256("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9));
1848 		string innercalldata2 = asString(FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + encodeArgs(3));
1849 		bytes calldata = encodeArgs(
1850 			12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13,
1851 			u256(innercalldata1.length()), innercalldata1,
1852 			u256(innercalldata2.length()), innercalldata2);
1853 		ABI_CHECK(
1854 			callContractFunction("test(uint256,bytes,bytes,uint256)", calldata),
1855 			encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))
1856 		);
1857 	);
1858 }
1859 
BOOST_AUTO_TEST_CASE(array_copy_storage_abi)1860 BOOST_AUTO_TEST_CASE(array_copy_storage_abi)
1861 {
1862 	// NOTE: This does not really test copying from storage to ABI directly,
1863 	// because it will always copy to memory first.
1864 	char const* sourceCode = R"(
1865 		pragma abicoder v2;
1866 		contract c {
1867 			uint8[] x;
1868 			uint16[] y;
1869 			uint24[] z;
1870 			uint24[][] w;
1871 			function test1() public returns (uint8[] memory) {
1872 				for (uint i = 0; i < 101; ++i)
1873 					x.push(uint8(i));
1874 				return x;
1875 			}
1876 			function test2() public returns (uint16[] memory) {
1877 				for (uint i = 0; i < 101; ++i)
1878 					y.push(uint16(i));
1879 				return y;
1880 			}
1881 			function test3() public returns (uint24[] memory) {
1882 				for (uint i = 0; i < 101; ++i)
1883 					z.push(uint24(i));
1884 				return z;
1885 			}
1886 			function test4() public returns (uint24[][] memory) {
1887 				w = new uint24[][](5);
1888 				for (uint i = 0; i < 5; ++i)
1889 					for (uint j = 0; j < 101; ++j)
1890 						w[i].push(uint24(j));
1891 				return w;
1892 			}
1893 		}
1894 	)";
1895 	ALSO_VIA_YUL(
1896 		DISABLE_EWASM_TESTRUN()
1897 
1898 		compileAndRun(sourceCode);
1899 		bytes valueSequence;
1900 		for (size_t i = 0; i < 101; ++i)
1901 			valueSequence += toBigEndian(u256(i));
1902 		ABI_CHECK(callContractFunction("test1()"), encodeArgs(0x20, 101) + valueSequence);
1903 		ABI_CHECK(callContractFunction("test2()"), encodeArgs(0x20, 101) + valueSequence);
1904 		ABI_CHECK(callContractFunction("test3()"), encodeArgs(0x20, 101) + valueSequence);
1905 		ABI_CHECK(callContractFunction("test4()"),
1906 			encodeArgs(0x20, 5, 0xa0, 0xa0 + 102 * 32 * 1, 0xa0 + 102 * 32 * 2, 0xa0 + 102 * 32 * 3, 0xa0 + 102 * 32 * 4) +
1907 			encodeArgs(101) + valueSequence +
1908 			encodeArgs(101) + valueSequence +
1909 			encodeArgs(101) + valueSequence +
1910 			encodeArgs(101) + valueSequence +
1911 			encodeArgs(101) + valueSequence
1912 		);
1913 	);
1914 }
1915 
1916 //BOOST_AUTO_TEST_CASE(assignment_to_const_array_vars)
1917 //{
1918 //	char const* sourceCode = R"(
1919 //		contract C {
1920 //			uint[3] constant x = [uint(1), 2, 3];
1921 //			uint constant y = x[0] + x[1] + x[2];
1922 //			function f() public returns (uint) { return y; }
1923 //		}
1924 //	)";
1925 //	compileAndRun(sourceCode);
1926 //	ABI_CHECK(callContractFunction("f()"), encodeArgs(1 + 2 + 3));
1927 //}
1928 
1929 // Disabled until https://github.com/ethereum/solidity/issues/715 is implemented
1930 //BOOST_AUTO_TEST_CASE(constant_struct)
1931 //{
1932 //	char const* sourceCode = R"(
1933 //		contract C {
1934 //			struct S { uint x; uint[] y; }
1935 //			S constant x = S(5, new uint[](4));
1936 //			function f() public returns (uint) { return x.x; }
1937 //		}
1938 //	)";
1939 //	compileAndRun(sourceCode);
1940 //	ABI_CHECK(callContractFunction("f()"), encodeArgs(5));
1941 //}
1942 
BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund)1943 BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund)
1944 {
1945 	char const* sourceCode = R"(
1946 		contract A {
1947 			uint public test = 1;
1948 			uint[3] arr;
1949 			constructor()
1950 			{
1951 				uint index = 5;
1952 				test = arr[index];
1953 				++test;
1954 			}
1955 		}
1956 	)";
1957 	ABI_CHECK(compileAndRunWithoutCheck({{"", sourceCode}}, 0, "A"), panicData(PanicCode::ArrayOutOfBounds));
1958 	BOOST_CHECK(!m_transactionSuccessful);
1959 }
1960 
BOOST_AUTO_TEST_CASE(failing_send)1961 BOOST_AUTO_TEST_CASE(failing_send)
1962 {
1963 	char const* sourceCode = R"(
1964 		contract Helper {
1965 			uint[] data;
1966 			fallback () external {
1967 				data[9]; // trigger exception
1968 			}
1969 		}
1970 		contract Main {
1971 			constructor() payable {}
1972 			function callHelper(address payable _a) public returns (bool r, uint bal) {
1973 				r = !_a.send(5);
1974 				bal = address(this).balance;
1975 			}
1976 		}
1977 	)";
1978 	compileAndRun(sourceCode, 0, "Helper");
1979 	h160 const c_helperAddress = m_contractAddress;
1980 	compileAndRun(sourceCode, 20, "Main");
1981 	BOOST_REQUIRE(callContractFunction("callHelper(address)", c_helperAddress) == encodeArgs(true, 20));
1982 }
1983 
BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes)1984 BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes)
1985 {
1986 	char const* sourceCode = R"(
1987 		contract Main {
1988 			string public s1;
1989 			string public s2;
1990 			function set(string calldata _s1, uint x, string calldata _s2) external returns (uint) {
1991 				s1 = _s1;
1992 				s2 = _s2;
1993 				return x;
1994 			}
1995 			function get() public returns (string memory r1, string memory r2) {
1996 				r1 = s1;
1997 				r2 = s2;
1998 			}
1999 		}
2000 	)";
2001 	compileAndRun(sourceCode, 0, "Main");
2002 	string s1(
2003 		"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
2004 		"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
2005 		"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
2006 		"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
2007 	);
2008 	string s2(
2009 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ"
2010 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ"
2011 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ"
2012 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ"
2013 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ"
2014 	);
2015 	vector<size_t> lengths{0, 30, 32, 63, 64, 65, 210, 300};
2016 	for (auto l1: lengths)
2017 		for (auto l2: lengths)
2018 		{
2019 			bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1));
2020 			bytes dyn2 = encodeArgs(u256(l2), s2.substr(0, l2));
2021 			bytes args = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn1.size())) + dyn1 + dyn2;
2022 			BOOST_REQUIRE(
2023 				callContractFunction("set(string,uint256,string)", asString(args)) ==
2024 				encodeArgs(u256(l1))
2025 			);
2026 			bytes result = encodeArgs(u256(0x40), u256(0x40 + dyn1.size())) + dyn1 + dyn2;
2027 			ABI_CHECK(callContractFunction("get()"), result);
2028 			ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn1);
2029 			ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn2);
2030 		}
2031 }
2032 
BOOST_AUTO_TEST_CASE(accessor_involving_strings)2033 BOOST_AUTO_TEST_CASE(accessor_involving_strings)
2034 {
2035 	char const* sourceCode = R"(
2036 		contract Main {
2037 			struct stringData { string a; uint b; string c; }
2038 			mapping(uint => stringData[]) public data;
2039 			function set(uint x, uint y, string calldata a, uint b, string calldata c) external returns (bool) {
2040 				while (data[x].length < y + 1)
2041 					data[x].push();
2042 				data[x][y].a = a;
2043 				data[x][y].b = b;
2044 				data[x][y].c = c;
2045 				return true;
2046 			}
2047 		}
2048 	)";
2049 	compileAndRun(sourceCode, 0, "Main");
2050 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
2051 	string s2("ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ");
2052 	bytes s1Data = encodeArgs(u256(s1.length()), s1);
2053 	bytes s2Data = encodeArgs(u256(s2.length()), s2);
2054 	u256 b = 765;
2055 	u256 x = 7;
2056 	u256 y = 123;
2057 	bytes args = encodeArgs(x, y, u256(0xa0), b, u256(0xa0 + s1Data.size()), s1Data, s2Data);
2058 	bytes result = encodeArgs(u256(0x60), b, u256(0x60 + s1Data.size()), s1Data, s2Data);
2059 	BOOST_REQUIRE(callContractFunction("set(uint256,uint256,string,uint256,string)", asString(args)) == encodeArgs(true));
2060 	BOOST_REQUIRE(callContractFunction("data(uint256,uint256)", x, y) == result);
2061 }
2062 
BOOST_AUTO_TEST_CASE(bytes_in_function_calls)2063 BOOST_AUTO_TEST_CASE(bytes_in_function_calls)
2064 {
2065 	char const* sourceCode = R"(
2066 		contract Main {
2067 			string public s1;
2068 			string public s2;
2069 			function set(string memory _s1, uint x, string memory _s2) public returns (uint) {
2070 				s1 = _s1;
2071 				s2 = _s2;
2072 				return x;
2073 			}
2074 			function setIndirectFromMemory(string memory _s1, uint x, string memory _s2) public returns (uint) {
2075 				return this.set(_s1, x, _s2);
2076 			}
2077 			function setIndirectFromCalldata(string calldata _s1, uint x, string calldata _s2) external returns (uint) {
2078 				return this.set(_s1, x, _s2);
2079 			}
2080 		}
2081 	)";
2082 	compileAndRun(sourceCode, 0, "Main");
2083 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
2084 	string s2("ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ");
2085 	vector<size_t> lengths{0, 31, 64, 65};
2086 	for (auto l1: lengths)
2087 		for (auto l2: lengths)
2088 		{
2089 			bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1));
2090 			bytes dyn2 = encodeArgs(u256(l2), s2.substr(0, l2));
2091 			bytes args1 = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn1.size())) + dyn1 + dyn2;
2092 			BOOST_REQUIRE(
2093 				callContractFunction("setIndirectFromMemory(string,uint256,string)", asString(args1)) ==
2094 				encodeArgs(u256(l1))
2095 			);
2096 			ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn1);
2097 			ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn2);
2098 			// swapped
2099 			bytes args2 = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn2.size())) + dyn2 + dyn1;
2100 			BOOST_REQUIRE(
2101 				callContractFunction("setIndirectFromCalldata(string,uint256,string)", asString(args2)) ==
2102 				encodeArgs(u256(l1))
2103 			);
2104 			ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn2);
2105 			ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn1);
2106 		}
2107 }
2108 
BOOST_AUTO_TEST_CASE(return_bytes_internal)2109 BOOST_AUTO_TEST_CASE(return_bytes_internal)
2110 {
2111 	char const* sourceCode = R"(
2112 		contract Main {
2113 			bytes s1;
2114 			function doSet(bytes memory _s1) public returns (bytes memory _r1) {
2115 				s1 = _s1;
2116 				_r1 = s1;
2117 			}
2118 			function set(bytes calldata _s1) external returns (uint _r, bytes memory _r1) {
2119 				_r1 = doSet(_s1);
2120 				_r = _r1.length;
2121 			}
2122 		}
2123 	)";
2124 	compileAndRun(sourceCode, 0, "Main");
2125 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
2126 	vector<size_t> lengths{0, 31, 64, 65};
2127 	for (auto l1: lengths)
2128 	{
2129 		bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1));
2130 		bytes args1 = encodeArgs(u256(0x20)) + dyn1;
2131 		BOOST_REQUIRE(
2132 			callContractFunction("set(bytes)", asString(args1)) ==
2133 			encodeArgs(u256(l1), u256(0x40)) + dyn1
2134 		);
2135 	}
2136 }
2137 
BOOST_AUTO_TEST_CASE(calldata_struct_short)2138 BOOST_AUTO_TEST_CASE(calldata_struct_short)
2139 {
2140 	char const* sourceCode = R"(
2141 		pragma abicoder v2;
2142 		contract C {
2143 			struct S { uint256 a; uint256 b; }
2144 			function f(S calldata) external pure returns (uint256) {
2145 				return msg.data.length;
2146 			}
2147 		}
2148 	)";
2149 	compileAndRun(sourceCode, 0, "C");
2150 
2151 	// double check that the valid case goes through
2152 	ABI_CHECK(callContractFunction("f((uint256,uint256))", u256(1), u256(2)), encodeArgs(0x44));
2153 
2154 	ABI_CHECK(callContractFunctionNoEncoding("f((uint256,uint256))", bytes(63,0)), encodeArgs());
2155 	ABI_CHECK(callContractFunctionNoEncoding("f((uint256,uint256))", bytes(33,0)), encodeArgs());
2156 	ABI_CHECK(callContractFunctionNoEncoding("f((uint256,uint256))", bytes(32,0)), encodeArgs());
2157 	ABI_CHECK(callContractFunctionNoEncoding("f((uint256,uint256))", bytes(31,0)), encodeArgs());
2158 	ABI_CHECK(callContractFunctionNoEncoding("f((uint256,uint256))", bytes()), encodeArgs());
2159 }
2160 
BOOST_AUTO_TEST_CASE(calldata_struct_function_type)2161 BOOST_AUTO_TEST_CASE(calldata_struct_function_type)
2162 {
2163 	char const* sourceCode = R"(
2164 		pragma abicoder v2;
2165 		contract C {
2166 			struct S { function (uint) external returns (uint) fn; }
2167 			function f(S calldata s) external returns (uint256) {
2168 				return s.fn(42);
2169 			}
2170 			function g(uint256 a) external returns (uint256) {
2171 				return a * 3;
2172 			}
2173 			function h(uint256 a) external returns (uint256) {
2174 				return 23;
2175 			}
2176 		}
2177 	)";
2178 	compileAndRun(sourceCode, 0, "C");
2179 
2180 	bytes fn_C_g = m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + bytes(8,0);
2181 	bytes fn_C_h = m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("h(uint256)")).asBytes() + bytes(8,0);
2182 	ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_g), encodeArgs(42 * 3));
2183 	ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_h), encodeArgs(23));
2184 }
2185 
BOOST_AUTO_TEST_CASE(calldata_array_dynamic_three_dimensional)2186 BOOST_AUTO_TEST_CASE(calldata_array_dynamic_three_dimensional)
2187 {
2188 	vector<vector<vector<u256>>> data {
2189 		{
2190 			{ 0x010A01, 0x010A02, 0x010A03 },
2191 			{ 0x010B01, 0x010B02, 0x010B03 }
2192 		},
2193 		{
2194 			{ 0x020A01, 0x020A02, 0x020A03 },
2195 			{ 0x020B01, 0x020B02, 0x020B03 }
2196 		}
2197 	};
2198 
2199 	for (bool outerDynamicallySized: { true, false })
2200 	for (bool middleDynamicallySized: { true, false })
2201 	for (bool innerDynamicallySized: { true, false })
2202 	{
2203 		// only test dynamically encoded arrays
2204 		if (!outerDynamicallySized && !middleDynamicallySized && !innerDynamicallySized)
2205 			continue;
2206 
2207 		string arrayType = "uint256";
2208 		arrayType += innerDynamicallySized ? "[]" : "[3]";
2209 		arrayType += middleDynamicallySized ? "[]" : "[2]";
2210 		arrayType += outerDynamicallySized ? "[]" : "[2]";
2211 
2212 		string sourceCode = R"(
2213 			pragma abicoder v2;
2214 			contract C {
2215 				function test()" + arrayType + R"( calldata a) external returns (uint256) {
2216 					return a.length;
2217 				}
2218 				function test()" + arrayType + R"( calldata a, uint256 i) external returns (uint256) {
2219 					return a[i].length;
2220 				}
2221 				function test()" + arrayType + R"( calldata a, uint256 i, uint256 j) external returns (uint256) {
2222 					return a[i][j].length;
2223 				}
2224 				function test()" + arrayType + R"( calldata a, uint256 i, uint256 j, uint256 k) external returns (uint256) {
2225 					return a[i][j][k];
2226 				}
2227 				function reenc()" + arrayType + R"( calldata a, uint256 i, uint256 j, uint256 k) external returns (uint256) {
2228 					return this.test(a, i, j, k);
2229 				}
2230 			}
2231 		)";
2232 		compileAndRun(sourceCode, 0, "C");
2233 
2234 		bytes encoding = encodeArray(
2235 			outerDynamicallySized,
2236 			middleDynamicallySized || innerDynamicallySized,
2237 			data | ranges::views::transform([&](auto const& _middleData) {
2238 				return encodeArray(
2239 					middleDynamicallySized,
2240 					innerDynamicallySized,
2241 					_middleData | ranges::views::transform([&](auto const& _values) {
2242 						return encodeArray(innerDynamicallySized, false, _values);
2243 					})
2244 				);
2245 			})
2246 		);
2247 
2248 		ABI_CHECK(callContractFunction("test(" + arrayType + ")", 0x20, encoding), encodeArgs(data.size()));
2249 		for (size_t i = 0; i < data.size(); i++)
2250 		{
2251 			ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, i, encoding), encodeArgs(data[i].size()));
2252 			for (size_t j = 0; j < data[i].size(); j++)
2253 			{
2254 				ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, j, encoding), encodeArgs(data[i][j].size()));
2255 				for (size_t k = 0; k < data[i][j].size(); k++)
2256 				{
2257 					ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256,uint256)", 0x80, i, j, k, encoding), encodeArgs(data[i][j][k]));
2258 					ABI_CHECK(callContractFunction("reenc(" + arrayType + ",uint256,uint256,uint256)", 0x80, i, j, k, encoding), encodeArgs(data[i][j][k]));
2259 				}
2260 				ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256,uint256)", 0x80, i, j, data[i][j].size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
2261 			}
2262 			ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, data[i].size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
2263 		}
2264 		ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, data.size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
2265 	}
2266 }
2267 
BOOST_AUTO_TEST_CASE(literal_strings)2268 BOOST_AUTO_TEST_CASE(literal_strings)
2269 {
2270 	char const* sourceCode = R"(
2271 		contract Test {
2272 			string public long;
2273 			string public medium;
2274 			string public short;
2275 			string public empty;
2276 			function f() public returns (string memory) {
2277 				long = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
2278 				medium = "01234567890123456789012345678901234567890123456789012345678901234567890123456789";
2279 				short = "123";
2280 				empty = "";
2281 				return "Hello, World!";
2282 			}
2283 		}
2284 	)";
2285 	compileAndRun(sourceCode, 0, "Test");
2286 	string longStr = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
2287 	string medium = "01234567890123456789012345678901234567890123456789012345678901234567890123456789";
2288 	string shortStr = "123";
2289 	string hello = "Hello, World!";
2290 
2291 	ABI_CHECK(callContractFunction("f()"), encodeDyn(hello));
2292 	ABI_CHECK(callContractFunction("long()"), encodeDyn(longStr));
2293 	ABI_CHECK(callContractFunction("medium()"), encodeDyn(medium));
2294 	ABI_CHECK(callContractFunction("short()"), encodeDyn(shortStr));
2295 	ABI_CHECK(callContractFunction("empty()"), encodeDyn(string()));
2296 }
2297 
BOOST_AUTO_TEST_CASE(initialise_string_constant)2298 BOOST_AUTO_TEST_CASE(initialise_string_constant)
2299 {
2300 	char const* sourceCode = R"(
2301 		contract Test {
2302 			string public short = "abcdef";
2303 			string public long = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
2304 		}
2305 	)";
2306 	compileAndRun(sourceCode, 0, "Test");
2307 	string longStr = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
2308 	string shortStr = "abcdef";
2309 
2310 	ABI_CHECK(callContractFunction("long()"), encodeDyn(longStr));
2311 	ABI_CHECK(callContractFunction("short()"), encodeDyn(shortStr));
2312 }
2313 
BOOST_AUTO_TEST_CASE(string_as_mapping_key)2314 BOOST_AUTO_TEST_CASE(string_as_mapping_key)
2315 {
2316 	char const* sourceCode = R"(
2317 		contract Test {
2318 			mapping(string => uint) data;
2319 			function set(string memory _s, uint _v) public { data[_s] = _v; }
2320 			function get(string memory _s) public returns (uint) { return data[_s]; }
2321 		}
2322 	)";
2323 
2324 	vector<string> strings{
2325 		"Hello, World!",
2326 		"Hello,                            World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1111",
2327 		"",
2328 		"1"
2329 	};
2330 
2331 	ALSO_VIA_YUL(
2332 		DISABLE_EWASM_TESTRUN()
2333 
2334 		compileAndRun(sourceCode, 0, "Test");
2335 		for (unsigned i = 0; i < strings.size(); i++)
2336 			ABI_CHECK(callContractFunction(
2337 				"set(string,uint256)",
2338 				u256(0x40),
2339 				u256(7 + i),
2340 				u256(strings[i].size()),
2341 				strings[i]
2342 			), encodeArgs());
2343 		for (unsigned i = 0; i < strings.size(); i++)
2344 			ABI_CHECK(callContractFunction(
2345 				"get(string)",
2346 				u256(0x20),
2347 				u256(strings[i].size()),
2348 				strings[i]
2349 			), encodeArgs(u256(7 + i)));
2350 	)
2351 }
2352 
BOOST_AUTO_TEST_CASE(string_as_public_mapping_key)2353 BOOST_AUTO_TEST_CASE(string_as_public_mapping_key)
2354 {
2355 	char const* sourceCode = R"(
2356 		contract Test {
2357 			mapping(string => uint) public data;
2358 			function set(string memory _s, uint _v) public { data[_s] = _v; }
2359 		}
2360 	)";
2361 	compileAndRun(sourceCode, 0, "Test");
2362 	vector<string> strings{
2363 		"Hello, World!",
2364 		"Hello,                            World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1111",
2365 		"",
2366 		"1"
2367 	};
2368 	for (unsigned i = 0; i < strings.size(); i++)
2369 		ABI_CHECK(callContractFunction(
2370 			"set(string,uint256)",
2371 			u256(0x40),
2372 			u256(7 + i),
2373 			u256(strings[i].size()),
2374 			strings[i]
2375 		), encodeArgs());
2376 	for (unsigned i = 0; i < strings.size(); i++)
2377 		ABI_CHECK(callContractFunction(
2378 			"data(string)",
2379 			u256(0x20),
2380 			u256(strings[i].size()),
2381 			strings[i]
2382 		), encodeArgs(u256(7 + i)));
2383 }
2384 
BOOST_AUTO_TEST_CASE(nested_string_as_public_mapping_key)2385 BOOST_AUTO_TEST_CASE(nested_string_as_public_mapping_key)
2386 {
2387 	char const* sourceCode = R"(
2388 		contract Test {
2389 			mapping(string => mapping(string => uint)) public data;
2390 			function set(string memory _s, string memory _s2, uint _v) public {
2391 				data[_s][_s2] = _v; }
2392 		}
2393 	)";
2394 	compileAndRun(sourceCode, 0, "Test");
2395 	vector<string> strings{
2396 		"Hello, World!",
2397 		"Hello,                            World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1111",
2398 		"",
2399 		"1",
2400 		"last one"
2401 	};
2402 	for (unsigned i = 0; i + 1 < strings.size(); i++)
2403 		ABI_CHECK(callContractFunction(
2404 			"set(string,string,uint256)",
2405 			u256(0x60),
2406 			u256(roundTo32(static_cast<unsigned>(0x80 + strings[i].size()))),
2407 			u256(7 + i),
2408 			u256(strings[i].size()),
2409 			strings[i],
2410 			u256(strings[i+1].size()),
2411 			strings[i+1]
2412 		), encodeArgs());
2413 	for (unsigned i = 0; i + 1 < strings.size(); i++)
2414 		ABI_CHECK(callContractFunction(
2415 			"data(string,string)",
2416 			u256(0x40),
2417 			u256(roundTo32(static_cast<unsigned>(0x60 + strings[i].size()))),
2418 			u256(strings[i].size()),
2419 			strings[i],
2420 			u256(strings[i+1].size()),
2421 			strings[i+1]
2422 		), encodeArgs(u256(7 + i)));
2423 }
2424 
BOOST_AUTO_TEST_CASE(nested_mixed_string_as_public_mapping_key)2425 BOOST_AUTO_TEST_CASE(nested_mixed_string_as_public_mapping_key)
2426 {
2427 	char const* sourceCode = R"(
2428 		contract Test {
2429 			mapping(string =>
2430 				mapping(int =>
2431 					mapping(address =>
2432 						mapping(bytes => int)))) public data;
2433 
2434 			function set(
2435 				string memory _s1,
2436 				int _s2,
2437 				address _s3,
2438 				bytes memory _s4,
2439 				int _value
2440 			) public
2441 			{
2442 				data[_s1][_s2][_s3][_s4] = _value;
2443 			}
2444 		}
2445 	)";
2446 	compileAndRun(sourceCode, 0, "Test");
2447 
2448 	struct Index
2449 	{
2450 		string s1;
2451 		int s2;
2452 		int s3;
2453 		string s4;
2454 	};
2455 
2456 	vector<Index> data{
2457 		{ "aabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcbc", 4, 23, "efg" },
2458 		{ "tiaron", 456, 63245, "908apzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapzapz" },
2459 		{ "", 2345, 12934, "665i65i65i65i65i65i65i65i65i65i65i65i65i65i65i65i65i65i5iart" },
2460 		{ "¡¿…", 9781, 8148, "" },
2461 		{ "ρν♀♀ω₂₃♀", 929608, 303030, "" }
2462 	};
2463 
2464 	for (size_t i = 0; i + 1 < data.size(); i++)
2465 		ABI_CHECK(callContractFunction(
2466 			"set(string,int256,address,bytes,int256)",
2467 			u256(0xA0),
2468 			u256(data[i].s2),
2469 			u256(data[i].s3),
2470 			u256(roundTo32(static_cast<unsigned>(0xC0 + data[i].s1.size()))),
2471 			u256(i - 3),
2472 			u256(data[i].s1.size()),
2473 			data[i].s1,
2474 			u256(data[i].s4.size()),
2475 			data[i].s4
2476 		), encodeArgs());
2477 	for (size_t i = 0; i + 1 < data.size(); i++)
2478 		ABI_CHECK(callContractFunction(
2479 			"data(string,int256,address,bytes)",
2480 			u256(0x80),
2481 			u256(data[i].s2),
2482 			u256(data[i].s3),
2483 			u256(roundTo32(static_cast<unsigned>(0xA0 + data[i].s1.size()))),
2484 			u256(data[i].s1.size()),
2485 			data[i].s1,
2486 			u256(data[i].s4.size()),
2487 			data[i].s4
2488 		), encodeArgs(u256(i - 3)));
2489 }
2490 
BOOST_AUTO_TEST_CASE(library_call)2491 BOOST_AUTO_TEST_CASE(library_call)
2492 {
2493 	char const* sourceCode = R"(
2494 		library Lib { function m(uint x, uint y) public returns (uint) { return x * y; } }
2495 		contract Test {
2496 			function f(uint x) public returns (uint) {
2497 				return Lib.m(x, 9);
2498 			}
2499 		}
2500 	)";
2501 	ALSO_VIA_YUL(
2502 		DISABLE_EWASM_TESTRUN()
2503 		compileAndRun(sourceCode, 0, "Lib");
2504 		compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
2505 		ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(33) * 9));
2506 	)
2507 }
2508 
BOOST_AUTO_TEST_CASE(library_function_external)2509 BOOST_AUTO_TEST_CASE(library_function_external)
2510 {
2511 	char const* sourceCode = R"(
2512 		library Lib { function m(bytes calldata b) external pure returns (bytes1) { return b[2]; } }
2513 		contract Test {
2514 			function f(bytes memory b) public pure returns (bytes1) {
2515 				return Lib.m(b);
2516 			}
2517 		}
2518 	)";
2519 	ALSO_VIA_YUL(
2520 		DISABLE_EWASM_TESTRUN()
2521 		compileAndRun(sourceCode, 0, "Lib");
2522 		compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
2523 		ABI_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), "abcde"), encodeArgs("c"));
2524 	)
2525 }
2526 
BOOST_AUTO_TEST_CASE(using_library_mappings_external)2527 BOOST_AUTO_TEST_CASE(using_library_mappings_external)
2528 {
2529 	char const* libSourceCode = R"(
2530 			library Lib {
2531 				function set(mapping(uint => uint) storage m, uint key, uint value) external
2532 				{
2533 					m[key] = value * 2;
2534 				}
2535 			}
2536 		)";
2537 	char const* sourceCode = R"(
2538 			library Lib {
2539 				function set(mapping(uint => uint) storage m, uint key, uint value) external {}
2540 			}
2541 			contract Test {
2542 				mapping(uint => uint) m1;
2543 				mapping(uint => uint) m2;
2544 				function f() public returns (uint, uint, uint, uint, uint, uint)
2545 				{
2546 					Lib.set(m1, 0, 1);
2547 					Lib.set(m1, 2, 42);
2548 					Lib.set(m2, 0, 23);
2549 					Lib.set(m2, 2, 99);
2550 					return (m1[0], m1[1], m1[2], m2[0], m2[1], m2[2]);
2551 				}
2552 			}
2553 		)";
2554 	for (auto v2: {false, true})
2555 	{
2556 		string prefix = "pragma abicoder " + string(v2 ? "v2" : "v1") + ";\n";
2557 		compileAndRun(prefix + libSourceCode, 0, "Lib");
2558 		compileAndRun(prefix + sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
2559 		ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2), u256(0), u256(84), u256(46), u256(0), u256(198)));
2560 	}
2561 }
2562 
BOOST_AUTO_TEST_CASE(short_strings)2563 BOOST_AUTO_TEST_CASE(short_strings)
2564 {
2565 	// This test verifies that the byte array encoding that combines length and data works
2566 	// correctly.
2567 	char const* sourceCode = R"(
2568 		contract A {
2569 			bytes public data1 = "123";
2570 			bytes data2;
2571 			function lengthChange() public returns (uint)
2572 			{
2573 				// store constant in short and long string
2574 				data1 = "123";
2575 				if (!equal(data1, "123")) return 1;
2576 				data2 = "12345678901234567890123456789012345678901234567890a";
2577 				if (data2[17] != "8") return 3;
2578 				if (data2.length != 51) return 4;
2579 				if (data2[data2.length - 1] != "a") return 5;
2580 				// change length: short -> short
2581 				while (data1.length < 5)
2582 					data1.push();
2583 				if (data1.length != 5) return 6;
2584 				data1[4] = "4";
2585 				if (data1[0] != "1") return 7;
2586 				if (data1[4] != "4") return 8;
2587 				// change length: short -> long
2588 				while (data1.length < 80)
2589 					data1.push();
2590 				if (data1.length != 80) return 9;
2591 				while (data1.length > 70)
2592 					data1.pop();
2593 				if (data1.length != 70) return 9;
2594 				if (data1[0] != "1") return 10;
2595 				if (data1[4] != "4") return 11;
2596 				for (uint i = 0; i < data1.length; i ++)
2597 					data1[i] = bytes1(uint8(i * 3));
2598 				if (uint8(data1[4]) != 4 * 3) return 12;
2599 				if (uint8(data1[67]) != 67 * 3) return 13;
2600 				// change length: long -> short
2601 				while (data1.length > 22)
2602 					data1.pop();
2603 				if (data1.length != 22) return 14;
2604 				if (uint8(data1[21]) != 21 * 3) return 15;
2605 				if (uint8(data1[2]) != 2 * 3) return 16;
2606 				// change length: short -> shorter
2607 				while (data1.length > 19)
2608 					data1.pop();
2609 				if (data1.length != 19) return 17;
2610 				if (uint8(data1[7]) != 7 * 3) return 18;
2611 				// and now again to original size
2612 				while (data1.length < 22)
2613 					data1.push();
2614 				if (data1.length != 22) return 19;
2615 				if (data1[21] != 0) return 20;
2616 				while (data1.length > 0)
2617 					data1.pop();
2618 				while (data2.length > 0)
2619 					data2.pop();
2620 			}
2621 			function copy() public returns (uint) {
2622 				bytes memory x = "123";
2623 				bytes memory y = "012345678901234567890123456789012345678901234567890123456789";
2624 				bytes memory z = "1234567";
2625 				data1 = x;
2626 				data2 = y;
2627 				if (!equal(data1, x)) return 1;
2628 				if (!equal(data2, y)) return 2;
2629 				// lengthen
2630 				data1 = y;
2631 				if (!equal(data1, y)) return 3;
2632 				// shorten
2633 				data1 = x;
2634 				if (!equal(data1, x)) return 4;
2635 				// change while keeping short
2636 				data1 = z;
2637 				if (!equal(data1, z)) return 5;
2638 				// copy storage -> storage
2639 				data1 = x;
2640 				data2 = y;
2641 				// lengthen
2642 				data1 = data2;
2643 				if (!equal(data1, y)) return 6;
2644 				// shorten
2645 				data1 = x;
2646 				data2 = data1;
2647 				if (!equal(data2, x)) return 7;
2648 				bytes memory c = data2;
2649 				data1 = c;
2650 				if (!equal(data1, x)) return 8;
2651 				data1 = "";
2652 				data2 = "";
2653 			}
2654 			function deleteElements() public returns (uint) {
2655 				data1 = "01234";
2656 				delete data1[2];
2657 				if (data1[2] != 0) return 1;
2658 				if (data1[0] != "0") return 2;
2659 				if (data1[3] != "3") return 3;
2660 				delete data1;
2661 				if (data1.length != 0) return 4;
2662 			}
2663 
2664 			function equal(bytes storage a, bytes memory b) internal returns (bool) {
2665 				if (a.length != b.length) return false;
2666 				for (uint i = 0; i < a.length; ++i) if (a[i] != b[i]) return false;
2667 				return true;
2668 			}
2669 		}
2670 	)";
2671 	ALSO_VIA_YUL(
2672 		DISABLE_EWASM_TESTRUN()
2673 		compileAndRun(sourceCode, 0, "A");
2674 		ABI_CHECK(callContractFunction("data1()"), encodeDyn(string("123")));
2675 		ABI_CHECK(callContractFunction("lengthChange()"), encodeArgs(u256(0)));
2676 		BOOST_CHECK(storageEmpty(m_contractAddress));
2677 		ABI_CHECK(callContractFunction("deleteElements()"), encodeArgs(u256(0)));
2678 		BOOST_CHECK(storageEmpty(m_contractAddress));
2679 		ABI_CHECK(callContractFunction("copy()"), encodeArgs(u256(0)));
2680 		BOOST_CHECK(storageEmpty(m_contractAddress));
2681 	)
2682 }
2683 
BOOST_AUTO_TEST_CASE(calldata_offset)2684 BOOST_AUTO_TEST_CASE(calldata_offset)
2685 {
2686 	// This tests a specific bug that was caused by not using the correct memory offset in the
2687 	// calldata unpacker.
2688 	char const* sourceCode = R"(
2689 		contract CB
2690 		{
2691 			address[] _arr;
2692 			string public last = "nd";
2693 			constructor(address[] memory guardians)
2694 			{
2695 				_arr = guardians;
2696 			}
2697 		}
2698 	)";
2699 	compileAndRun(sourceCode, 0, "CB", encodeArgs(u256(0x20), u256(0x00)));
2700 	ABI_CHECK(callContractFunction("last()", encodeArgs()), encodeDyn(string("nd")));
2701 }
2702 
BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library)2703 BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library)
2704 {
2705 	char const* sourceCode = R"(
2706 		library lib {}
2707 		contract c {
2708 			constructor() payable {}
2709 			function f(address payable x) public returns (bool) {
2710 				return x.send(1);
2711 			}
2712 			receive () external payable {}
2713 		}
2714 	)";
2715 	ALSO_VIA_YUL(
2716 		DISABLE_EWASM_TESTRUN()
2717 		compileAndRun(sourceCode, 0, "lib");
2718 		Address libraryAddress = m_contractAddress;
2719 		compileAndRun(sourceCode, 10, "c");
2720 		BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10);
2721 		BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0);
2722 		ABI_CHECK(callContractFunction("f(address)", encodeArgs(libraryAddress)), encodeArgs(false));
2723 		BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10);
2724 		BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0);
2725 		ABI_CHECK(callContractFunction("f(address)", encodeArgs(m_contractAddress)), encodeArgs(true));
2726 		BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10);
2727 		BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0);
2728 	)
2729 }
2730 
BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size)2731 BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size)
2732 {
2733 	// Check allocation size of byte array. Should be 32 plus length rounded up to next
2734 	// multiple of 32
2735 	char const* sourceCode = R"(
2736 		contract C {
2737 			function f() public pure returns (uint d1, uint d2, uint d3, uint memsize) {
2738 				bytes memory b1 = new bytes(31);
2739 				bytes memory b2 = new bytes(32);
2740 				bytes memory b3 = new bytes(256);
2741 				bytes memory b4 = new bytes(31);
2742 				assembly {
2743 					d1 := sub(b2, b1)
2744 					d2 := sub(b3, b2)
2745 					d3 := sub(b4, b3)
2746 					memsize := msize()
2747 				}
2748 			}
2749 		}
2750 	)";
2751 	if (!m_optimiserSettings.runYulOptimiser)
2752 	{
2753 		compileAndRun(sourceCode);
2754 		ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256, 0x260));
2755 	}
2756 }
2757 
BOOST_AUTO_TEST_CASE(inline_long_string_return)2758 BOOST_AUTO_TEST_CASE(inline_long_string_return)
2759 {
2760 		char const* sourceCode = R"(
2761 		contract C {
2762 			function f() public returns (string memory) {
2763 				return (["somethingShort", "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"][1]);
2764 			}
2765 		}
2766 	)";
2767 
2768 	string strLong = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
2769 	compileAndRun(sourceCode, 0, "C");
2770 	ABI_CHECK(callContractFunction("f()"), encodeDyn(strLong));
2771 }
2772 
BOOST_AUTO_TEST_CASE(index_access_with_type_conversion)2773 BOOST_AUTO_TEST_CASE(index_access_with_type_conversion)
2774 {
2775 	// Test for a bug where higher order bits cleanup was not done for array index access.
2776 	char const* sourceCode = R"(
2777 			contract C {
2778 				function f(uint x) public returns (uint[256] memory r){
2779 					r[uint8(x)] = 2;
2780 				}
2781 			}
2782 	)";
2783 	compileAndRun(sourceCode, 0, "C");
2784 	// neither of the two should throw due to out-of-bounds access
2785 	BOOST_CHECK(callContractFunction("f(uint256)", u256(0x01)).size() == 256 * 32);
2786 	BOOST_CHECK(callContractFunction("f(uint256)", u256(0x101)).size() == 256 * 32);
2787 }
2788 
BOOST_AUTO_TEST_CASE(correctly_initialize_memory_array_in_constructor)2789 BOOST_AUTO_TEST_CASE(correctly_initialize_memory_array_in_constructor)
2790 {
2791 	// Memory arrays are initialized using calldatacopy past the size of the calldata.
2792 	// This test checks that it also works in the constructor context.
2793 	char const* sourceCode = R"(
2794 		contract C {
2795 			bool public success;
2796 			constructor() {
2797 				// Make memory dirty.
2798 				assembly {
2799 					for { let i := 0 } lt(i, 64) { i := add(i, 1) } {
2800 						mstore(msize(), not(0))
2801 					}
2802 				}
2803 				uint16[3] memory c;
2804 				require(c[0] == 0 && c[1] == 0 && c[2] == 0);
2805 				uint16[] memory x = new uint16[](3);
2806 				require(x[0] == 0 && x[1] == 0 && x[2] == 0);
2807 				success = true;
2808 			}
2809 		}
2810 	)";
2811 	// Cannot run against yul optimizer because of msize
2812 	if (!m_optimiserSettings.runYulOptimiser)
2813 	{
2814 		compileAndRun(sourceCode, 0, "C");
2815 		ABI_CHECK(callContractFunction("success()"), encodeArgs(u256(1)));
2816 	}
2817 }
2818 
BOOST_AUTO_TEST_CASE(mutex)2819 BOOST_AUTO_TEST_CASE(mutex)
2820 {
2821 	char const* sourceCode = R"(
2822 		contract mutexed {
2823 			bool locked;
2824 			modifier protected {
2825 				if (locked) revert();
2826 				locked = true;
2827 				_;
2828 				locked = false;
2829 			}
2830 		}
2831 		contract Fund is mutexed {
2832 			uint shares;
2833 			constructor() payable { shares = msg.value; }
2834 			function withdraw(uint amount) public protected returns (uint) {
2835 				// NOTE: It is very bad practice to write this function this way.
2836 				// Please refer to the documentation of how to do this properly.
2837 				if (amount > shares) revert();
2838 				(bool success,) = msg.sender.call{value: amount}("");
2839 				require(success);
2840 				shares -= amount;
2841 				return shares;
2842 			}
2843 			function withdrawUnprotected(uint amount) public returns (uint) {
2844 				// NOTE: It is very bad practice to write this function this way.
2845 				// Please refer to the documentation of how to do this properly.
2846 				if (amount > shares) revert();
2847 				(bool success,) = msg.sender.call{value: amount}("");
2848 				require(success);
2849 				shares -= amount;
2850 				return shares;
2851 			}
2852 		}
2853 		contract Attacker {
2854 			Fund public fund;
2855 			uint callDepth;
2856 			bool protected;
2857 			function setProtected(bool _protected) public { protected = _protected; }
2858 			constructor(Fund _fund) { fund = _fund; }
2859 			function attack() public returns (uint) {
2860 				callDepth = 0;
2861 				return attackInternal();
2862 			}
2863 			function attackInternal() internal returns (uint) {
2864 				if (protected)
2865 					return fund.withdraw(10);
2866 				else
2867 					return fund.withdrawUnprotected(10);
2868 			}
2869 			fallback() external payable {
2870 				callDepth++;
2871 				if (callDepth < 4)
2872 					attackInternal();
2873 			}
2874 		}
2875 	)";
2876 	compileAndRun(sourceCode, 500, "Fund");
2877 	h160 const fund = m_contractAddress;
2878 	BOOST_CHECK_EQUAL(balanceAt(fund), 500);
2879 	compileAndRun(sourceCode, 0, "Attacker", encodeArgs(fund));
2880 	ABI_CHECK(callContractFunction("setProtected(bool)", true), encodeArgs());
2881 	ABI_CHECK(callContractFunction("attack()"), encodeArgs());
2882 	BOOST_CHECK_EQUAL(balanceAt(fund), 500);
2883 	ABI_CHECK(callContractFunction("setProtected(bool)", false), encodeArgs());
2884 	ABI_CHECK(callContractFunction("attack()"), encodeArgs(u256(460)));
2885 	BOOST_CHECK_EQUAL(balanceAt(fund), 460);
2886 }
2887 
BOOST_AUTO_TEST_CASE(payable_function)2888 BOOST_AUTO_TEST_CASE(payable_function)
2889 {
2890 	char const* sourceCode = R"(
2891 		contract C {
2892 			uint public a;
2893 			function f() payable public returns (uint) {
2894 				return msg.value;
2895 			}
2896 			fallback() external payable {
2897 				a = msg.value + 1;
2898 			}
2899 		}
2900 	)";
2901 	compileAndRun(sourceCode, 0, "C");
2902 	ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs(u256(27)));
2903 	BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27);
2904 	ABI_CHECK(callContractFunctionWithValue("", 27), encodeArgs());
2905 	BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27);
2906 	ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(28)));
2907 	BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27);
2908 }
2909 
BOOST_AUTO_TEST_CASE(non_payable_throw)2910 BOOST_AUTO_TEST_CASE(non_payable_throw)
2911 {
2912 	char const* sourceCode = R"(
2913 		contract C {
2914 			uint public a;
2915 			function f() public returns (uint) {
2916 				return msgvalue();
2917 			}
2918 			function msgvalue() internal returns (uint) {
2919 				return msg.value;
2920 			}
2921 			fallback() external {
2922 				update();
2923 			}
2924 			function update() internal {
2925 				a = msg.value + 1;
2926 			}
2927 
2928 		}
2929 	)";
2930 	ALSO_VIA_YUL(
2931 		DISABLE_EWASM_TESTRUN()
2932 		compileAndRun(sourceCode, 0, "C");
2933 		ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs());
2934 		BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
2935 		ABI_CHECK(callContractFunction(""), encodeArgs());
2936 		ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1)));
2937 		ABI_CHECK(callContractFunctionWithValue("", 27), encodeArgs());
2938 		BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
2939 		ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1)));
2940 		ABI_CHECK(callContractFunctionWithValue("a()", 27), encodeArgs());
2941 		BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
2942 	)
2943 }
2944 
BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)2945 BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)
2946 {
2947 	// This tests that memory resize for return values is not paid during the call, which would
2948 	// make the gas calculation overly complex. We access the end of the output area before
2949 	// the call is made.
2950 	// Tests that this also survives the optimizer.
2951 	char const* sourceCode = R"(
2952 		contract C {
2953 			function f() public returns (uint[200] memory) {}
2954 		}
2955 		contract D {
2956 			function f(C c) public returns (uint) { c.f(); return 7; }
2957 		}
2958 	)";
2959 
2960 	compileAndRun(sourceCode, 0, "C");
2961 	h160 const cAddr = m_contractAddress;
2962 	compileAndRun(sourceCode, 0, "D");
2963 	ABI_CHECK(callContractFunction("f(address)", cAddr), encodeArgs(u256(7)));
2964 }
2965 
BOOST_AUTO_TEST_CASE(receive_external_function_type)2966 BOOST_AUTO_TEST_CASE(receive_external_function_type)
2967 {
2968 	char const* sourceCode = R"(
2969 		contract C {
2970 			function g() public returns (uint) { return 7; }
2971 			function f(function() external returns (uint) g) public returns (uint) {
2972 				return g();
2973 			}
2974 		}
2975 	)";
2976 
2977 	ALSO_VIA_YUL(
2978 		DISABLE_EWASM_TESTRUN()
2979 		compileAndRun(sourceCode, 0, "C");
2980 		ABI_CHECK(callContractFunction(
2981 			"f(function)",
2982 			m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0)
2983 		), encodeArgs(u256(7)));
2984 	)
2985 }
2986 
BOOST_AUTO_TEST_CASE(return_external_function_type)2987 BOOST_AUTO_TEST_CASE(return_external_function_type)
2988 {
2989 	char const* sourceCode = R"(
2990 		contract C {
2991 			function g() public {}
2992 			function f() public returns (function() external) {
2993 				return this.g;
2994 			}
2995 		}
2996 	)";
2997 
2998 	compileAndRun(sourceCode, 0, "C");
2999 	ABI_CHECK(
3000 		callContractFunction("f()"),
3001 		m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0)
3002 	);
3003 }
3004 
3005 // TODO: store bound internal library functions
3006 
BOOST_AUTO_TEST_CASE(shift_bytes)3007 BOOST_AUTO_TEST_CASE(shift_bytes)
3008 {
3009 	char const* sourceCode = R"(
3010 		contract C {
3011 			function left(bytes20 x, uint8 y) public returns (bytes20) {
3012 				return x << y;
3013 			}
3014 			function right(bytes20 x, uint8 y) public returns (bytes20) {
3015 				return x >> y;
3016 			}
3017 		}
3018 	)";
3019 	compileAndRun(sourceCode, 0, "C");
3020 	ABI_CHECK(callContractFunction("left(bytes20,uint8)", "12345678901234567890", 8 * 8), encodeArgs("901234567890" + string(8, 0)));
3021 	ABI_CHECK(callContractFunction("right(bytes20,uint8)", "12345678901234567890", 8 * 8), encodeArgs(string(8, 0) + "123456789012"));
3022 }
3023 
BOOST_AUTO_TEST_CASE(contracts_separated_with_comment)3024 BOOST_AUTO_TEST_CASE(contracts_separated_with_comment)
3025 {
3026 	char const* sourceCode = R"(
3027 		contract C1 {}
3028 		/**
3029 		**/
3030 		contract C2 {}
3031 	)";
3032 	ALSO_VIA_YUL(
3033 		DISABLE_EWASM_TESTRUN()
3034 
3035 		compileAndRun(sourceCode, 0, "C1");
3036 		compileAndRun(sourceCode, 0, "C2");
3037 	)
3038 }
3039 
BOOST_AUTO_TEST_CASE(include_creation_bytecode_only_once)3040 BOOST_AUTO_TEST_CASE(include_creation_bytecode_only_once)
3041 {
3042 	char const* sourceCode = R"(
3043 		contract D {
3044 			bytes a = hex"1237651237125387136581271652831736512837126583171583712358126123765123712538713658127165283173651283712658317158371235812612376512371253871365812716528317365128371265831715837123581261237651237125387136581271652831736512837126583171583712358126";
3045 			bytes b = hex"1237651237125327136581271252831736512837126583171383712358126123765125712538713658127165253173651283712658357158371235812612376512371a5387136581271652a317365128371265a317158371235812612a765123712538a13658127165a83173651283712a58317158371235a126";
3046 			constructor(uint) {}
3047 		}
3048 		contract Double {
3049 			function f() public {
3050 				new D(2);
3051 			}
3052 			function g() public {
3053 				new D(3);
3054 			}
3055 		}
3056 		contract Single {
3057 			function f() public {
3058 				new D(2);
3059 			}
3060 		}
3061 	)";
3062 	compileAndRun(sourceCode);
3063 	BOOST_CHECK_LE(
3064 		double(m_compiler.object("Double").bytecode.size()),
3065 		1.2 * double(m_compiler.object("Single").bytecode.size())
3066 	);
3067 }
3068 
BOOST_AUTO_TEST_CASE(revert_with_cause)3069 BOOST_AUTO_TEST_CASE(revert_with_cause)
3070 {
3071 	char const* sourceCode = R"(
3072 		contract D {
3073 			string constant msg1 = "test1234567890123456789012345678901234567890";
3074 			string msg2 = "test1234567890123456789012345678901234567890";
3075 			function f() public {
3076 				revert("test123");
3077 			}
3078 			function g() public {
3079 				revert("test1234567890123456789012345678901234567890");
3080 			}
3081 			function h() public {
3082 				revert(msg1);
3083 			}
3084 			function i() public {
3085 				revert(msg2);
3086 			}
3087 			function j() public {
3088 				string memory msg3 = "test1234567890123456789012345678901234567890";
3089 				revert(msg3);
3090 			}
3091 		}
3092 		contract C {
3093 			D d = new D();
3094 			function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) {
3095 				uint retsize;
3096 				assembly {
3097 					success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0)
3098 					retsize := returndatasize()
3099 				}
3100 				retval = new bytes(retsize);
3101 				assembly {
3102 					returndatacopy(add(retval, 0x20), 0, returndatasize())
3103 				}
3104 			}
3105 			function f() public returns (bool, bytes memory) {
3106 				return forward(address(d), msg.data);
3107 			}
3108 			function g() public returns (bool, bytes memory) {
3109 				return forward(address(d), msg.data);
3110 			}
3111 			function h() public returns (bool, bytes memory) {
3112 				return forward(address(d), msg.data);
3113 			}
3114 			function i() public returns (bool, bytes memory) {
3115 				return forward(address(d), msg.data);
3116 			}
3117 			function j() public returns (bool, bytes memory) {
3118 				return forward(address(d), msg.data);
3119 			}
3120 		}
3121 	)";
3122 	if (solidity::test::CommonOptions::get().evmVersion().supportsReturndata())
3123 	{
3124 		compileAndRun(sourceCode, 0, "C");
3125 		bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0};
3126 		ABI_CHECK(callContractFunction("f()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "test123") + bytes(28, 0));
3127 		ABI_CHECK(callContractFunction("g()"), encodeArgs(0, 0x40, 0x84) + errorSignature + encodeArgs(0x20, 44, "test1234567890123456789012345678901234567890") + bytes(28, 0));
3128 		ABI_CHECK(callContractFunction("h()"), encodeArgs(0, 0x40, 0x84) + errorSignature + encodeArgs(0x20, 44, "test1234567890123456789012345678901234567890") + bytes(28, 0));
3129 		ABI_CHECK(callContractFunction("i()"), encodeArgs(0, 0x40, 0x84) + errorSignature + encodeArgs(0x20, 44, "test1234567890123456789012345678901234567890") + bytes(28, 0));
3130 		ABI_CHECK(callContractFunction("j()"), encodeArgs(0, 0x40, 0x84) + errorSignature + encodeArgs(0x20, 44, "test1234567890123456789012345678901234567890") + bytes(28, 0));
3131 	}
3132 }
3133 
BOOST_AUTO_TEST_CASE(require_with_message)3134 BOOST_AUTO_TEST_CASE(require_with_message)
3135 {
3136 	char const* sourceCode = R"(
3137 		contract D {
3138 			bool flag = false;
3139 			string storageError = "abc";
3140 			string constant constantError = "abc";
3141 			function f(uint x) public {
3142 				require(x > 7, "failed");
3143 			}
3144 			function g() public {
3145 				// As a side-effect of internalFun, the flag will be set to true
3146 				// (even if the condition is true),
3147 				// but it will only throw in the next evaluation.
3148 				bool flagCopy = flag;
3149 				require(flagCopy == false, internalFun());
3150 			}
3151 			function internalFun() public returns (string memory) {
3152 				flag = true;
3153 				return "only on second run";
3154 			}
3155 			function h() public {
3156 				require(false, storageError);
3157 			}
3158 			function i() public {
3159 				require(false, constantError);
3160 			}
3161 			function j() public {
3162 				string memory errMsg = "msg";
3163 				require(false, errMsg);
3164 			}
3165 		}
3166 		contract C {
3167 			D d = new D();
3168 			function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) {
3169 				uint retsize;
3170 				assembly {
3171 					success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0)
3172 					retsize := returndatasize()
3173 				}
3174 				retval = new bytes(retsize);
3175 				assembly {
3176 					returndatacopy(add(retval, 0x20), 0, returndatasize())
3177 				}
3178 			}
3179 			function f(uint x) public returns (bool, bytes memory) {
3180 				return forward(address(d), msg.data);
3181 			}
3182 			function g() public returns (bool, bytes memory) {
3183 				return forward(address(d), msg.data);
3184 			}
3185 			function h() public returns (bool, bytes memory) {
3186 				return forward(address(d), msg.data);
3187 			}
3188 			function i() public returns (bool, bytes memory) {
3189 				return forward(address(d), msg.data);
3190 			}
3191 			function j() public returns (bool, bytes memory) {
3192 				return forward(address(d), msg.data);
3193 			}
3194 		}
3195 	)";
3196 	if (solidity::test::CommonOptions::get().evmVersion().supportsReturndata())
3197 	{
3198 		compileAndRun(sourceCode, 0, "C");
3199 		bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0};
3200 		ABI_CHECK(callContractFunction("f(uint256)", 8), encodeArgs(1, 0x40, 0));
3201 		ABI_CHECK(callContractFunction("f(uint256)", 5), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 6, "failed") + bytes(28, 0));
3202 		ABI_CHECK(callContractFunction("g()"), encodeArgs(1, 0x40, 0));
3203 		ABI_CHECK(callContractFunction("g()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 18, "only on second run") + bytes(28, 0));
3204 		ABI_CHECK(callContractFunction("h()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 3, "abc") + bytes(28, 0));
3205 		ABI_CHECK(callContractFunction("i()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 3, "abc") + bytes(28, 0));
3206 		ABI_CHECK(callContractFunction("j()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 3, "msg") + bytes(28, 0));
3207 	}
3208 }
3209 
BOOST_AUTO_TEST_CASE(bubble_up_error_messages)3210 BOOST_AUTO_TEST_CASE(bubble_up_error_messages)
3211 {
3212 	char const* sourceCode = R"(
3213 		contract D {
3214 			function f() public {
3215 				revert("message");
3216 			}
3217 			function g() public {
3218 				this.f();
3219 			}
3220 		}
3221 		contract C {
3222 			D d = new D();
3223 			function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) {
3224 				uint retsize;
3225 				assembly {
3226 					success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0)
3227 					retsize := returndatasize()
3228 				}
3229 				retval = new bytes(retsize);
3230 				assembly {
3231 					returndatacopy(add(retval, 0x20), 0, returndatasize())
3232 				}
3233 			}
3234 			function f() public returns (bool, bytes memory) {
3235 				return forward(address(d), msg.data);
3236 			}
3237 			function g() public returns (bool, bytes memory) {
3238 				return forward(address(d), msg.data);
3239 			}
3240 		}
3241 	)";
3242 	if (solidity::test::CommonOptions::get().evmVersion().supportsReturndata())
3243 	{
3244 		compileAndRun(sourceCode, 0, "C");
3245 		bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0};
3246 		ABI_CHECK(callContractFunction("f()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0));
3247 		ABI_CHECK(callContractFunction("g()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0));
3248 	}
3249 }
3250 
BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_transfer)3251 BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_transfer)
3252 {
3253 	char const* sourceCode = R"(
3254 		contract D {
3255 			receive() external payable {
3256 				revert("message");
3257 			}
3258 			function f() public {
3259 				payable(this).transfer(0);
3260 			}
3261 		}
3262 		contract C {
3263 			D d = new D();
3264 			function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) {
3265 				uint retsize;
3266 				assembly {
3267 					success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0)
3268 					retsize := returndatasize()
3269 				}
3270 				retval = new bytes(retsize);
3271 				assembly {
3272 					returndatacopy(add(retval, 0x20), 0, returndatasize())
3273 				}
3274 			}
3275 			function f() public returns (bool, bytes memory) {
3276 				return forward(address(d), msg.data);
3277 			}
3278 		}
3279 	)";
3280 	if (solidity::test::CommonOptions::get().evmVersion().supportsReturndata())
3281 	{
3282 		compileAndRun(sourceCode, 0, "C");
3283 		bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0};
3284 		ABI_CHECK(callContractFunction("f()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0));
3285 	}
3286 }
3287 
BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_create)3288 BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_create)
3289 {
3290 	char const* sourceCode = R"(
3291 		contract E {
3292 			constructor() {
3293 				revert("message");
3294 			}
3295 		}
3296 		contract D {
3297 			function f() public {
3298 				E x = new E();
3299 			}
3300 		}
3301 		contract C {
3302 			D d = new D();
3303 			function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) {
3304 				uint retsize;
3305 				assembly {
3306 					success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0)
3307 					retsize := returndatasize()
3308 				}
3309 				retval = new bytes(retsize);
3310 				assembly {
3311 					returndatacopy(add(retval, 0x20), 0, returndatasize())
3312 				}
3313 			}
3314 			function f() public returns (bool, bytes memory) {
3315 				return forward(address(d), msg.data);
3316 			}
3317 		}
3318 	)";
3319 	if (solidity::test::CommonOptions::get().evmVersion().supportsReturndata())
3320 	{
3321 		compileAndRun(sourceCode, 0, "C");
3322 		bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0};
3323 		ABI_CHECK(callContractFunction("f()"), encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0));
3324 	}
3325 }
3326 
BOOST_AUTO_TEST_CASE(interface_contract)3327 BOOST_AUTO_TEST_CASE(interface_contract)
3328 {
3329 	char const* sourceCode = R"(
3330 		interface I {
3331 			event A();
3332 			function f() external returns (bool);
3333 			fallback() external payable;
3334 		}
3335 
3336 		contract A is I {
3337 			function f() public override returns (bool) {
3338 				return g();
3339 			}
3340 
3341 			function g() public returns (bool) {
3342 				return true;
3343 			}
3344 
3345 			fallback() override external payable {
3346 			}
3347 		}
3348 
3349 		contract C {
3350 			function f(address payable _interfaceAddress) public returns (bool) {
3351 				I i = I(_interfaceAddress);
3352 				return i.f();
3353 			}
3354 		}
3355 	)";
3356 	compileAndRun(sourceCode, 0, "A");
3357 	h160 const recipient = m_contractAddress;
3358 	compileAndRun(sourceCode, 0, "C");
3359 	ABI_CHECK(callContractFunction("f(address)", recipient), encodeArgs(true));
3360 }
3361 
BOOST_AUTO_TEST_CASE(bare_call_invalid_address)3362 BOOST_AUTO_TEST_CASE(bare_call_invalid_address)
3363 {
3364 	char const* sourceCode = R"YY(
3365 		contract C {
3366 			/// Calling into non-existent account is successful (creates the account)
3367 			function f() external returns (bool) {
3368 				(bool success,) = address(0x4242).call("");
3369 				return success;
3370 			}
3371 			function h() external returns (bool) {
3372 				(bool success,) = address(0x4242).delegatecall("");
3373 				return success;
3374 			}
3375 		}
3376 	)YY";
3377 	compileAndRun(sourceCode, 0, "C");
3378 	ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1)));
3379 	ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(1)));
3380 
3381 	if (solidity::test::CommonOptions::get().evmVersion().hasStaticCall())
3382 	{
3383 		char const* sourceCode = R"YY(
3384 			contract C {
3385 				function f() external returns (bool, bytes memory) {
3386 					return address(0x4242).staticcall("");
3387 				}
3388 			}
3389 		)YY";
3390 		compileAndRun(sourceCode, 0, "C");
3391 		ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), 0x40, 0x00));
3392 	}
3393 }
3394 
BOOST_AUTO_TEST_CASE(bare_call_return_data)3395 BOOST_AUTO_TEST_CASE(bare_call_return_data)
3396 {
3397 	if (solidity::test::CommonOptions::get().evmVersion().supportsReturndata())
3398 	{
3399 		vector<string> calltypes = {"call", "delegatecall"};
3400 		if (solidity::test::CommonOptions::get().evmVersion().hasStaticCall())
3401 			calltypes.emplace_back("staticcall");
3402 		for (string const& calltype: calltypes)
3403 		{
3404 			string sourceCode = R"DELIMITER(
3405 				contract A {
3406 					constructor() {
3407 					}
3408 					function return_bool() public pure returns(bool) {
3409 						return true;
3410 					}
3411 					function return_int32() public pure returns(int32) {
3412 						return -32;
3413 					}
3414 					function return_uint32() public pure returns(uint32) {
3415 						return 0x3232;
3416 					}
3417 					function return_int256() public pure returns(int256) {
3418 						return -256;
3419 					}
3420 					function return_uint256() public pure returns(uint256) {
3421 						return 0x256256;
3422 					}
3423 					function return_bytes4() public pure returns(bytes4) {
3424 						return 0xabcd0012;
3425 					}
3426 					function return_multi() public pure returns(bool, uint32, bytes4) {
3427 						return (false, 0x3232, 0xabcd0012);
3428 					}
3429 					function return_bytes() public pure returns(bytes memory b) {
3430 						b = new bytes(2);
3431 						b[0] = 0x42;
3432 						b[1] = 0x21;
3433 					}
3434 				}
3435 				contract C {
3436 					A addr;
3437 					constructor() {
3438 						addr = new A();
3439 					}
3440 					function f(string memory signature) public returns (bool, bytes memory) {
3441 						return address(addr).)DELIMITER" + calltype + R"DELIMITER((abi.encodeWithSignature(signature));
3442 					}
3443 					function check_bool() external returns (bool) {
3444 						(bool success, bytes memory data) = f("return_bool()");
3445 						assert(success);
3446 						bool a = abi.decode(data, (bool));
3447 						assert(a);
3448 						return true;
3449 					}
3450 					function check_int32() external returns (bool) {
3451 						(bool success, bytes memory data) = f("return_int32()");
3452 						assert(success);
3453 						int32 a = abi.decode(data, (int32));
3454 						assert(a == -32);
3455 						return true;
3456 					}
3457 					function check_uint32() external returns (bool) {
3458 						(bool success, bytes memory data) = f("return_uint32()");
3459 						assert(success);
3460 						uint32 a = abi.decode(data, (uint32));
3461 						assert(a == 0x3232);
3462 						return true;
3463 					}
3464 					function check_int256() external returns (bool) {
3465 						(bool success, bytes memory data) = f("return_int256()");
3466 						assert(success);
3467 						int256 a = abi.decode(data, (int256));
3468 						assert(a == -256);
3469 						return true;
3470 					}
3471 					function check_uint256() external returns (bool) {
3472 						(bool success, bytes memory data) = f("return_uint256()");
3473 						assert(success);
3474 						uint256 a = abi.decode(data, (uint256));
3475 						assert(a == 0x256256);
3476 						return true;
3477 					}
3478 					function check_bytes4() external returns (bool) {
3479 						(bool success, bytes memory data) = f("return_bytes4()");
3480 						assert(success);
3481 						bytes4 a = abi.decode(data, (bytes4));
3482 						assert(a == 0xabcd0012);
3483 						return true;
3484 					}
3485 					function check_multi() external returns (bool) {
3486 						(bool success, bytes memory data) = f("return_multi()");
3487 						assert(success);
3488 						(bool a, uint32 b, bytes4 c) = abi.decode(data, (bool, uint32, bytes4));
3489 						assert(a == false && b == 0x3232 && c == 0xabcd0012);
3490 						return true;
3491 					}
3492 					function check_bytes() external returns (bool) {
3493 						(bool success, bytes memory data) = f("return_bytes()");
3494 						assert(success);
3495 						(bytes memory d) = abi.decode(data, (bytes));
3496 						assert(d.length == 2 && d[0] == 0x42 && d[1] == 0x21);
3497 						return true;
3498 					}
3499 				}
3500 			)DELIMITER";
3501 			ALSO_VIA_YUL(
3502 				DISABLE_EWASM_TESTRUN()
3503 				compileAndRun(sourceCode, 0, "C");
3504 				ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bool()"))), encodeArgs(true, 0x40, 0x20, true));
3505 				ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_int32()"))), encodeArgs(true, 0x40, 0x20, u256(-32)));
3506 				ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_uint32()"))), encodeArgs(true, 0x40, 0x20, u256(0x3232)));
3507 				ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_int256()"))), encodeArgs(true, 0x40, 0x20, u256(-256)));
3508 				ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_uint256()"))), encodeArgs(true, 0x40, 0x20, u256(0x256256)));
3509 				ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bytes4()"))), encodeArgs(true, 0x40, 0x20, u256(0xabcd0012) << (28*8)));
3510 				ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_multi()"))), encodeArgs(true, 0x40, 0x60, false, u256(0x3232), u256(0xabcd0012) << (28*8)));
3511 				ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bytes()"))), encodeArgs(true, 0x40, 0x60, 0x20, 0x02, encode(bytes{0x42,0x21}, false)));
3512 				ABI_CHECK(callContractFunction("check_bool()"), encodeArgs(true));
3513 				ABI_CHECK(callContractFunction("check_int32()"), encodeArgs(true));
3514 				ABI_CHECK(callContractFunction("check_uint32()"), encodeArgs(true));
3515 				ABI_CHECK(callContractFunction("check_int256()"), encodeArgs(true));
3516 				ABI_CHECK(callContractFunction("check_uint256()"), encodeArgs(true));
3517 				ABI_CHECK(callContractFunction("check_bytes4()"), encodeArgs(true));
3518 				ABI_CHECK(callContractFunction("check_multi()"), encodeArgs(true));
3519 				ABI_CHECK(callContractFunction("check_bytes()"), encodeArgs(true));
3520 			)
3521 		}
3522 	}
3523 }
3524 
BOOST_AUTO_TEST_CASE(abi_encodePacked)3525 BOOST_AUTO_TEST_CASE(abi_encodePacked)
3526 {
3527 	char const* sourceCode = R"(
3528 		contract C {
3529 			function f0() public pure returns (bytes memory) {
3530 				return abi.encodePacked();
3531 			}
3532 			function f1() public pure returns (bytes memory) {
3533 				return abi.encodePacked(uint8(1), uint8(2));
3534 			}
3535 			function f2() public pure returns (bytes memory) {
3536 				string memory x = "abc";
3537 				return abi.encodePacked(uint8(1), x, uint8(2));
3538 			}
3539 			function f3() public pure returns (bytes memory r) {
3540 				// test that memory is properly allocated
3541 				string memory x = "abc";
3542 				r = abi.encodePacked(uint8(1), x, uint8(2));
3543 				bytes memory y = "def";
3544 				require(y[0] == "d");
3545 				y[0] = "e";
3546 				require(y[0] == "e");
3547 			}
3548 			function f4() public pure returns (bytes memory) {
3549 				string memory x = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
3550 				return abi.encodePacked(uint16(0x0701), x, uint16(0x1201));
3551 			}
3552 			function f_literal() public pure returns (bytes memory) {
3553 				return abi.encodePacked(uint8(0x01), "abc", uint8(0x02));
3554 			}
3555 			function f_calldata() public pure returns (bytes memory) {
3556 				return abi.encodePacked(uint8(0x01), msg.data, uint8(0x02));
3557 			}
3558 		}
3559 	)";
3560 	for (auto v2: {false, true})
3561 	{
3562 		ALSO_VIA_YUL(
3563 			DISABLE_EWASM_TESTRUN()
3564 			string prefix = "pragma abicoder " + string(v2 ? "v2" : "v1") + ";\n";
3565 			compileAndRun(prefix + sourceCode, 0, "C");
3566 			ABI_CHECK(callContractFunction("f0()"), encodeArgs(0x20, 0));
3567 			ABI_CHECK(callContractFunction("f1()"), encodeArgs(0x20, 2, "\x01\x02"));
3568 			ABI_CHECK(callContractFunction("f2()"), encodeArgs(0x20, 5, "\x01" "abc" "\x02"));
3569 			ABI_CHECK(callContractFunction("f3()"), encodeArgs(0x20, 5, "\x01" "abc" "\x02"));
3570 			ABI_CHECK(callContractFunction("f4()"), encodeArgs(0x20, 2 + 26 + 26 + 2, "\x07\x01" "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" "\x12\x01"));
3571 			ABI_CHECK(callContractFunction("f_literal()"), encodeArgs(0x20, 5, "\x01" "abc" "\x02"));
3572 			ABI_CHECK(callContractFunction("f_calldata()"), encodeArgs(0x20, 6, "\x01" "\xa5\xbf\xa1\xee" "\x02"));
3573 		)
3574 	}
3575 }
3576 
BOOST_AUTO_TEST_CASE(abi_encodePacked_from_storage)3577 BOOST_AUTO_TEST_CASE(abi_encodePacked_from_storage)
3578 {
3579 	char const* sourceCode = R"(
3580 		contract C {
3581 			uint24[9] small_fixed;
3582 			int24[9] small_fixed_signed;
3583 			uint24[] small_dyn;
3584 			uint248[5] large_fixed;
3585 			uint248[] large_dyn;
3586 			bytes bytes_storage;
3587 			function sf() public returns (bytes memory) {
3588 				small_fixed[0] = 0xfffff1;
3589 				small_fixed[2] = 0xfffff2;
3590 				small_fixed[5] = 0xfffff3;
3591 				small_fixed[8] = 0xfffff4;
3592 				return abi.encodePacked(uint8(0x01), small_fixed, uint8(0x02));
3593 			}
3594 			function sd() public returns (bytes memory) {
3595 				small_dyn.push(0xfffff1);
3596 				small_dyn.push(0x00);
3597 				small_dyn.push(0xfffff2);
3598 				small_dyn.push(0x00);
3599 				small_dyn.push(0x00);
3600 				small_dyn.push(0xfffff3);
3601 				small_dyn.push(0x00);
3602 				small_dyn.push(0x00);
3603 				small_dyn.push(0xfffff4);
3604 				return abi.encodePacked(uint8(0x01), small_dyn, uint8(0x02));
3605 			}
3606 			function sfs() public returns (bytes memory) {
3607 				small_fixed_signed[0] = -2;
3608 				small_fixed_signed[2] = 0xffff2;
3609 				small_fixed_signed[5] = -200;
3610 				small_fixed_signed[8] = 0xffff4;
3611 				return abi.encodePacked(uint8(0x01), small_fixed_signed, uint8(0x02));
3612 			}
3613 			function lf() public returns (bytes memory) {
3614 				large_fixed[0] = 2**248-1;
3615 				large_fixed[1] = 0xfffff2;
3616 				large_fixed[2] = 2**248-2;
3617 				large_fixed[4] = 0xfffff4;
3618 				return abi.encodePacked(uint8(0x01), large_fixed, uint8(0x02));
3619 			}
3620 			function ld() public returns (bytes memory) {
3621 				large_dyn.push(2**248-1);
3622 				large_dyn.push(0xfffff2);
3623 				large_dyn.push(2**248-2);
3624 				large_dyn.push(0);
3625 				large_dyn.push(0xfffff4);
3626 				return abi.encodePacked(uint8(0x01), large_dyn, uint8(0x02));
3627 			}
3628 			function bytes_short() public returns (bytes memory) {
3629 				bytes_storage = "abcd";
3630 				return abi.encodePacked(uint8(0x01), bytes_storage, uint8(0x02));
3631 			}
3632 			function bytes_long() public returns (bytes memory) {
3633 				bytes_storage = "0123456789012345678901234567890123456789";
3634 				return abi.encodePacked(uint8(0x01), bytes_storage, uint8(0x02));
3635 			}
3636 		}
3637 	)";
3638 	for (auto v2: {false, true})
3639 	{
3640 		ALSO_VIA_YUL(
3641 			DISABLE_EWASM_TESTRUN()
3642 			string prefix = "pragma abicoder " + string(v2 ? "v2" : "v1") + ";\n";
3643 			compileAndRun(prefix + sourceCode, 0, "C");
3644 			bytes payload = encodeArgs(0xfffff1, 0, 0xfffff2, 0, 0, 0xfffff3, 0, 0, 0xfffff4);
3645 			bytes encoded = encodeArgs(0x20, 0x122, "\x01" + asString(payload) + "\x02");
3646 			ABI_CHECK(callContractFunction("sf()"), encoded);
3647 			ABI_CHECK(callContractFunction("sd()"), encoded);
3648 			ABI_CHECK(callContractFunction("sfs()"), encodeArgs(0x20, 0x122, "\x01" + asString(encodeArgs(
3649 				u256(-2), 0, 0xffff2, 0, 0, u256(-200), 0, 0, 0xffff4
3650 			)) + "\x02"));
3651 			payload = encodeArgs(
3652 				u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
3653 				0xfffff2,
3654 				u256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"),
3655 				0,
3656 				0xfffff4
3657 			);
3658 			ABI_CHECK(callContractFunction("lf()"), encodeArgs(0x20, 5 * 32 + 2, "\x01" + asString(encodeArgs(payload)) + "\x02"));
3659 			ABI_CHECK(callContractFunction("ld()"), encodeArgs(0x20, 5 * 32 + 2, "\x01" + asString(encodeArgs(payload)) + "\x02"));
3660 			ABI_CHECK(callContractFunction("bytes_short()"), encodeArgs(0x20, 6, "\x01" "abcd\x02"));
3661 			ABI_CHECK(callContractFunction("bytes_long()"), encodeArgs(0x20, 42, "\x01" "0123456789012345678901234567890123456789\x02"));
3662 		)
3663 	}
3664 }
3665 
BOOST_AUTO_TEST_CASE(abi_encodePacked_from_memory)3666 BOOST_AUTO_TEST_CASE(abi_encodePacked_from_memory)
3667 {
3668 	char const* sourceCode = R"(
3669 		contract C {
3670 			function sf() public pure returns (bytes memory) {
3671 				uint24[9] memory small_fixed;
3672 				small_fixed[0] = 0xfffff1;
3673 				small_fixed[2] = 0xfffff2;
3674 				small_fixed[5] = 0xfffff3;
3675 				small_fixed[8] = 0xfffff4;
3676 				return abi.encodePacked(uint8(0x01), small_fixed, uint8(0x02));
3677 			}
3678 			function sd() public pure returns (bytes memory) {
3679 				uint24[] memory small_dyn = new uint24[](9);
3680 				small_dyn[0] = 0xfffff1;
3681 				small_dyn[2] = 0xfffff2;
3682 				small_dyn[5] = 0xfffff3;
3683 				small_dyn[8] = 0xfffff4;
3684 				return abi.encodePacked(uint8(0x01), small_dyn, uint8(0x02));
3685 			}
3686 			function sfs() public pure returns (bytes memory) {
3687 				int24[9] memory small_fixed_signed;
3688 				small_fixed_signed[0] = -2;
3689 				small_fixed_signed[2] = 0xffff2;
3690 				small_fixed_signed[5] = -200;
3691 				small_fixed_signed[8] = 0xffff4;
3692 				return abi.encodePacked(uint8(0x01), small_fixed_signed, uint8(0x02));
3693 			}
3694 			function lf() public pure returns (bytes memory) {
3695 				uint248[5] memory large_fixed;
3696 				large_fixed[0] = 2**248-1;
3697 				large_fixed[1] = 0xfffff2;
3698 				large_fixed[2] = 2**248-2;
3699 				large_fixed[4] = 0xfffff4;
3700 				return abi.encodePacked(uint8(0x01), large_fixed, uint8(0x02));
3701 			}
3702 			function ld() public pure returns (bytes memory) {
3703 				uint248[] memory large_dyn = new uint248[](5);
3704 				large_dyn[0] = 2**248-1;
3705 				large_dyn[1] = 0xfffff2;
3706 				large_dyn[2] = 2**248-2;
3707 				large_dyn[4] = 0xfffff4;
3708 				return abi.encodePacked(uint8(0x01), large_dyn, uint8(0x02));
3709 			}
3710 		}
3711 	)";
3712 	for (auto v2: {false, true})
3713 	{
3714 		ALSO_VIA_YUL(
3715 			DISABLE_EWASM_TESTRUN()
3716 			string prefix = "pragma abicoder " + string(v2 ? "v2" : "v1") + ";\n";
3717 			compileAndRun(prefix + sourceCode, 0, "C");
3718 			bytes payload = encodeArgs(0xfffff1, 0, 0xfffff2, 0, 0, 0xfffff3, 0, 0, 0xfffff4);
3719 			bytes encoded = encodeArgs(0x20, 0x122, "\x01" + asString(payload) + "\x02");
3720 			ABI_CHECK(callContractFunction("sf()"), encoded);
3721 			ABI_CHECK(callContractFunction("sd()"), encoded);
3722 			ABI_CHECK(callContractFunction("sfs()"), encodeArgs(0x20, 0x122, "\x01" + asString(encodeArgs(
3723 				u256(-2), 0, 0xffff2, 0, 0, u256(-200), 0, 0, 0xffff4
3724 			)) + "\x02"));
3725 			payload = encodeArgs(
3726 				u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
3727 				0xfffff2,
3728 				u256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"),
3729 				0,
3730 				0xfffff4
3731 			);
3732 			ABI_CHECK(callContractFunction("lf()"), encodeArgs(0x20, 5 * 32 + 2, "\x01" + asString(encodeArgs(payload)) + "\x02"));
3733 			ABI_CHECK(callContractFunction("ld()"), encodeArgs(0x20, 5 * 32 + 2, "\x01" + asString(encodeArgs(payload)) + "\x02"));
3734 		)
3735 	}
3736 }
3737 
BOOST_AUTO_TEST_CASE(abi_encodePacked_functionPtr)3738 BOOST_AUTO_TEST_CASE(abi_encodePacked_functionPtr)
3739 {
3740 	char const* sourceCode = R"(
3741 		contract C {
3742 			C other = C(0x1112131400000000000011121314000000000087);
3743 			function testDirect() public view returns (bytes memory) {
3744 				return abi.encodePacked(uint8(8), other.f, uint8(2));
3745 			}
3746 			function testFixedArray() public view returns (bytes memory) {
3747 				function () external pure returns (bytes memory)[1] memory x;
3748 				x[0] = other.f;
3749 				return abi.encodePacked(uint8(8), x, uint8(2));
3750 			}
3751 			function testDynamicArray() public view returns (bytes memory) {
3752 				function () external pure returns (bytes memory)[] memory x = new function() external pure returns (bytes memory)[](1);
3753 				x[0] = other.f;
3754 				return abi.encodePacked(uint8(8), x, uint8(2));
3755 			}
3756 			function f() public pure returns (bytes memory) {}
3757 		}
3758 	)";
3759 	for (auto v2: {false, true})
3760 	{
3761 		ALSO_VIA_YUL(
3762 			DISABLE_EWASM_TESTRUN()
3763 			string prefix = "pragma abicoder " + string(v2 ? "v2" : "v1") + ";\n";
3764 			compileAndRun(prefix + sourceCode, 0, "C");
3765 			string directEncoding = asString(fromHex("08" "1112131400000000000011121314000000000087" "26121ff0" "02"));
3766 			ABI_CHECK(callContractFunction("testDirect()"), encodeArgs(0x20, directEncoding.size(), directEncoding));
3767 			string arrayEncoding = asString(fromHex("08" "1112131400000000000011121314000000000087" "26121ff0" "0000000000000000" "02"));
3768 			ABI_CHECK(callContractFunction("testFixedArray()"), encodeArgs(0x20, arrayEncoding.size(), arrayEncoding));
3769 			ABI_CHECK(callContractFunction("testDynamicArray()"), encodeArgs(0x20, arrayEncoding.size(), arrayEncoding));
3770 		)
3771 	}
3772 }
3773 
BOOST_AUTO_TEST_CASE(abi_encodePackedV2_structs)3774 BOOST_AUTO_TEST_CASE(abi_encodePackedV2_structs)
3775 {
3776 	char const* sourceCode = R"(
3777 		pragma abicoder v2;
3778 		contract C {
3779 			struct S {
3780 				uint8 a;
3781 				int16 b;
3782 				uint8[2] c;
3783 				int16[] d;
3784 			}
3785 			S s;
3786 			event E(S indexed);
3787 			constructor() {
3788 				s.a = 0x12;
3789 				s.b = -7;
3790 				s.c[0] = 2;
3791 				s.c[1] = 3;
3792 				s.d.push(-7);
3793 				s.d.push(-8);
3794 			}
3795 			function testStorage() public {
3796 				emit E(s);
3797 			}
3798 			function testMemory() public {
3799 				S memory m = s;
3800 				emit E(m);
3801 			}
3802 		}
3803 	)";
3804 	ALSO_VIA_YUL(
3805 		DISABLE_EWASM_TESTRUN()
3806 		compileAndRun(sourceCode, 0, "C");
3807 		bytes structEnc = encodeArgs(int(0x12), u256(-7), int(2), int(3), u256(-7), u256(-8));
3808 		ABI_CHECK(callContractFunction("testStorage()"), encodeArgs());
3809 		BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
3810 		BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
3811 		BOOST_CHECK_EQUAL(logTopic(0, 1), util::keccak256(asString(structEnc)));
3812 		ABI_CHECK(callContractFunction("testMemory()"), encodeArgs());
3813 		BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
3814 		BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
3815 		BOOST_CHECK_EQUAL(logTopic(0, 1), util::keccak256(asString(structEnc)));
3816 	)
3817 }
3818 
BOOST_AUTO_TEST_CASE(abi_encodePackedV2_nestedArray)3819 BOOST_AUTO_TEST_CASE(abi_encodePackedV2_nestedArray)
3820 {
3821 	char const* sourceCode = R"(
3822 		pragma abicoder v2;
3823 		contract C {
3824 			struct S {
3825 				uint8 a;
3826 				int16 b;
3827 			}
3828 			event E(S[2][][3] indexed);
3829 			function testNestedArrays() public {
3830 				S[2][][3] memory x;
3831 				x[1] = new S[2][](2);
3832 				x[1][0][0].a = 1;
3833 				x[1][0][0].b = 2;
3834 				x[1][0][1].a = 3;
3835 				x[1][1][1].b = 4;
3836 				emit E(x);
3837 			}
3838 		}
3839 	)";
3840 	ALSO_VIA_YUL(
3841 		DISABLE_EWASM_TESTRUN()
3842 		compileAndRun(sourceCode, 0, "C");
3843 		bytes structEnc = encodeArgs(1, 2, 3, 0, 0, 0, 0, 4);
3844 		ABI_CHECK(callContractFunction("testNestedArrays()"), encodeArgs());
3845 		BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
3846 		BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("E((uint8,int16)[2][][3])")));
3847 		BOOST_CHECK_EQUAL(logTopic(0, 1), util::keccak256(asString(structEnc)));
3848 	)
3849 }
3850 
BOOST_AUTO_TEST_CASE(abi_encodePackedV2_arrayOfStrings)3851 BOOST_AUTO_TEST_CASE(abi_encodePackedV2_arrayOfStrings)
3852 {
3853 	char const* sourceCode = R"(
3854 		pragma abicoder v2;
3855 		contract C {
3856 			string[] x;
3857 			event E(string[] indexed);
3858 			constructor() {
3859 				x.push("abc");
3860 				x.push("0123456789012345678901234567890123456789");
3861 			}
3862 			function testStorage() public {
3863 				emit E(x);
3864 			}
3865 			function testMemory() public {
3866 				string[] memory y = x;
3867 				emit E(y);
3868 			}
3869 		}
3870 	)";
3871 	ALSO_VIA_YUL(
3872 		DISABLE_EWASM_TESTRUN()
3873 		compileAndRun(sourceCode, 0, "C");
3874 		bytes arrayEncoding = encodeArgs("abc", "0123456789012345678901234567890123456789");
3875 		ABI_CHECK(callContractFunction("testStorage()"), encodeArgs());
3876 		BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
3877 		BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("E(string[])")));
3878 		BOOST_CHECK_EQUAL(logTopic(0, 1), util::keccak256(asString(arrayEncoding)));
3879 		ABI_CHECK(callContractFunction("testMemory()"), encodeArgs());
3880 		BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
3881 		BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("E(string[])")));
3882 		BOOST_CHECK_EQUAL(logTopic(0, 1), util::keccak256(asString(arrayEncoding)));
3883 	)
3884 }
3885 
BOOST_AUTO_TEST_CASE(code_access)3886 BOOST_AUTO_TEST_CASE(code_access)
3887 {
3888 	char const* sourceCode = R"(
3889 		contract C {
3890 			function lengths() public pure returns (bool) {
3891 				uint crLen = type(D).creationCode.length;
3892 				uint runLen = type(D).runtimeCode.length;
3893 				require(runLen < crLen);
3894 				require(crLen >= 0x20);
3895 				require(runLen >= 0x20);
3896 				return true;
3897 			}
3898 			function creation() public pure returns (bytes memory) {
3899 				return type(D).creationCode;
3900 			}
3901 			function runtime() public pure returns (bytes memory) {
3902 				return type(D).runtimeCode;
3903 			}
3904 			function runtimeAllocCheck() public pure returns (bytes memory) {
3905 				uint[] memory a = new uint[](2);
3906 				bytes memory c = type(D).runtimeCode;
3907 				uint[] memory b = new uint[](2);
3908 				a[0] = 0x1111;
3909 				a[1] = 0x2222;
3910 				b[0] = 0x3333;
3911 				b[1] = 0x4444;
3912 				return c;
3913 			}
3914 		}
3915 		contract D {
3916 			function f() public pure returns (uint) { return 7; }
3917 		}
3918 	)";
3919 	compileAndRun(sourceCode, 0, "C");
3920 	ABI_CHECK(callContractFunction("lengths()"), encodeArgs(true));
3921 	bytes codeCreation = callContractFunction("creation()");
3922 	bytes codeRuntime1 = callContractFunction("runtime()");
3923 	bytes codeRuntime2 = callContractFunction("runtimeAllocCheck()");
3924 	ABI_CHECK(codeRuntime1, codeRuntime2);
3925 }
3926 
BOOST_AUTO_TEST_CASE(contract_name)3927 BOOST_AUTO_TEST_CASE(contract_name)
3928 {
3929 	char const* sourceCode = R"(
3930 		contract C {
3931 			string public nameAccessor = type(C).name;
3932 			string public constant constantNameAccessor = type(C).name;
3933 
3934 			function name() public virtual pure returns (string memory) {
3935 				return type(C).name;
3936 			}
3937 		}
3938 		contract D is C {
3939 			function name() public override pure returns (string memory) {
3940 				return type(D).name;
3941 			}
3942 			function name2() public pure returns (string memory) {
3943 				return type(C).name;
3944 			}
3945 		}
3946 		contract ThisIsAVeryLongContractNameExceeding256bits {
3947 			string public nameAccessor = type(ThisIsAVeryLongContractNameExceeding256bits).name;
3948 			string public constant constantNameAccessor = type(ThisIsAVeryLongContractNameExceeding256bits).name;
3949 
3950 			function name() public pure returns (string memory) {
3951 				return type(ThisIsAVeryLongContractNameExceeding256bits).name;
3952 			}
3953 		}
3954 	)";
3955 
3956 	compileAndRun(sourceCode, 0, "C");
3957 	bytes argsC = encodeArgs(u256(0x20), u256(1), "C");
3958 	ABI_CHECK(callContractFunction("name()"), argsC);
3959 	ABI_CHECK(callContractFunction("nameAccessor()"), argsC);
3960 	ABI_CHECK(callContractFunction("constantNameAccessor()"), argsC);
3961 
3962 	compileAndRun(sourceCode, 0, "D");
3963 	bytes argsD = encodeArgs(u256(0x20), u256(1), "D");
3964 	ABI_CHECK(callContractFunction("name()"), argsD);
3965 	ABI_CHECK(callContractFunction("name2()"), argsC);
3966 
3967 	string longName = "ThisIsAVeryLongContractNameExceeding256bits";
3968 	compileAndRun(sourceCode, 0, longName);
3969 	bytes argsLong = encodeArgs(u256(0x20), u256(longName.length()), longName);
3970 	ABI_CHECK(callContractFunction("name()"), argsLong);
3971 	ABI_CHECK(callContractFunction("nameAccessor()"), argsLong);
3972 	ABI_CHECK(callContractFunction("constantNameAccessor()"), argsLong);
3973 }
3974 
BOOST_AUTO_TEST_CASE(event_wrong_abi_name)3975 BOOST_AUTO_TEST_CASE(event_wrong_abi_name)
3976 {
3977 	char const* sourceCode = R"(
3978 		library ClientReceipt {
3979 			event Deposit(Test indexed _from, bytes32 indexed _id, uint _value);
3980 			function deposit(bytes32 _id) public {
3981 				Test a;
3982 				emit Deposit(a, _id, msg.value);
3983 			}
3984 		}
3985 		contract Test {
3986 			function f() public {
3987 				ClientReceipt.deposit("123");
3988 			}
3989 		}
3990 	)";
3991 	ALSO_VIA_YUL(
3992 		DISABLE_EWASM_TESTRUN()
3993 		compileAndRun(sourceCode, 0, "ClientReceipt", bytes());
3994 		compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":ClientReceipt", m_contractAddress}});
3995 
3996 		callContractFunction("f()");
3997 		BOOST_REQUIRE_EQUAL(numLogs(), 1);
3998 		BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
3999 		BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
4000 		BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("Deposit(address,bytes32,uint256)")));
4001 	)
4002 }
4003 
BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser)4004 BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser)
4005 {
4006 	char const* sourceCode = R"(
4007 		contract C {
4008 			event X(uint);
4009 			constructor() {
4010 				assembly {
4011 					// make scratch space dirty
4012 					mstore(0, 0x4242424242424242424242424242424242424242424242424242424242424242)
4013 				}
4014 				uint x = 0x0000000000001234123412431234123412412342112341234124312341234124;
4015 				// This is just to create many instances of x
4016 				unchecked { emit X(x + f() * g(tx.origin) ^ h(block.number)); }
4017 				assembly {
4018 					// make scratch space dirty
4019 					mstore(0, 0x4242424242424242424242424242424242424242424242424242424242424242)
4020 				}
4021 				emit X(x);
4022 			}
4023 			function f() internal pure returns (uint) {
4024 				return 0x0000000000001234123412431234123412412342112341234124312341234124;
4025 			}
4026 			function g(address a) internal pure returns (uint) {
4027 				unchecked { return uint(uint160(a)) * 0x0000000000001234123412431234123412412342112341234124312341234124; }
4028 			}
4029 			function h(uint a) internal pure returns (uint) {
4030 				unchecked { return a * 0x0000000000001234123412431234123412412342112341234124312341234124; }
4031 			}
4032 		}
4033 	)";
4034 	compileAndRun(sourceCode, 0, "C");
4035 	BOOST_REQUIRE_EQUAL(numLogs(), 2);
4036 	BOOST_CHECK_EQUAL(logAddress(1), m_contractAddress);
4037 	ABI_CHECK(
4038 		logData(1),
4039 		encodeArgs(u256("0x0000000000001234123412431234123412412342112341234124312341234124"))
4040 	);
4041 }
4042 
BOOST_AUTO_TEST_CASE(strip_reason_strings)4043 BOOST_AUTO_TEST_CASE(strip_reason_strings)
4044 {
4045 	char const* sourceCode = R"(
4046 		contract C {
4047 			function f(bool _x) public pure returns (uint) {
4048 				require(_x, "some reason");
4049 				return 7;
4050 			}
4051 			function g(bool _x) public pure returns (uint) {
4052 				string memory x = "some indirect reason";
4053 				require(_x, x);
4054 				return 8;
4055 			}
4056 			function f1(bool _x) public pure returns (uint) {
4057 				if (!_x) revert( /* */ "some reason" /* */ );
4058 				return 9;
4059 			}
4060 			function g1(bool _x) public pure returns (uint) {
4061 				string memory x = "some indirect reason";
4062 				if (!_x) revert(x);
4063 				return 10;
4064 			}
4065 		}
4066 	)";
4067 	ALSO_VIA_YUL(
4068 		DISABLE_EWASM_TESTRUN()
4069 		m_revertStrings = RevertStrings::Default;
4070 		compileAndRun(sourceCode, 0, "C");
4071 
4072 		if (
4073 			m_optimiserSettings == OptimiserSettings::minimal() ||
4074 			m_optimiserSettings == OptimiserSettings::none()
4075 		)
4076 			// check that the reason string IS part of the binary.
4077 			BOOST_CHECK(toHex(m_output).find("736f6d6520726561736f6e") != std::string::npos);
4078 
4079 		m_revertStrings = RevertStrings::Strip;
4080 		compileAndRun(sourceCode, 0, "C");
4081 		// check that the reason string is NOT part of the binary.
4082 		BOOST_CHECK(toHex(m_output).find("736f6d6520726561736f6e") == std::string::npos);
4083 
4084 		ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(7));
4085 		ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs());
4086 		ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(8));
4087 		ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs());
4088 		ABI_CHECK(callContractFunction("f1(bool)", true), encodeArgs(9));
4089 		ABI_CHECK(callContractFunction("f1(bool)", false), encodeArgs());
4090 		ABI_CHECK(callContractFunction("g1(bool)", true), encodeArgs(10));
4091 		ABI_CHECK(callContractFunction("g1(bool)", false), encodeArgs());
4092 	)
4093 }
4094 
4095 BOOST_AUTO_TEST_SUITE_END()
4096 
4097 } // end namespaces
4098