mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	
						commit
						be02db4950
					
				| @ -1462,13 +1462,14 @@ string YulUtilFunctions::clearStorageStructFunction(StructType const& _type) | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string YulUtilFunctions::copyArrayToStorage(ArrayType const& _fromType, ArrayType const& _toType) | string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, ArrayType const& _toType) | ||||||
| { | { | ||||||
| 	solAssert( | 	solAssert( | ||||||
| 		*_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast<ReferenceType const&>(_toType), | 		*_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast<ReferenceType const&>(_toType), | ||||||
| 		"" | 		"" | ||||||
| 	); | 	); | ||||||
| 	solUnimplementedAssert(!_fromType.isByteArray(), ""); | 	if (_fromType.isByteArray()) | ||||||
|  | 		return copyByteArrayToStorageFunction(_fromType, _toType); | ||||||
| 	solUnimplementedAssert(!_fromType.dataStoredIn(DataLocation::Storage), ""); | 	solUnimplementedAssert(!_fromType.dataStoredIn(DataLocation::Storage), ""); | ||||||
| 
 | 
 | ||||||
| 	string functionName = "copy_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier(); | 	string functionName = "copy_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier(); | ||||||
| @ -1561,6 +1562,84 @@ string YulUtilFunctions::copyArrayToStorage(ArrayType const& _fromType, ArrayTyp | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromType, ArrayType const& _toType) | ||||||
|  | { | ||||||
|  | 	solAssert( | ||||||
|  | 		*_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast<ReferenceType const&>(_toType), | ||||||
|  | 		"" | ||||||
|  | 	); | ||||||
|  | 	solAssert(_fromType.isByteArray(), ""); | ||||||
|  | 	solAssert(_toType.isByteArray(), ""); | ||||||
|  | 	solUnimplementedAssert(!_fromType.dataStoredIn(DataLocation::Storage), ""); | ||||||
|  | 
 | ||||||
|  | 	string functionName = "copy_byte_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier(); | ||||||
|  | 	return m_functionCollector.createFunction(functionName, [&](){ | ||||||
|  | 		Whiskers templ(R"( | ||||||
|  | 			function <functionName>(slot, src<?fromCalldata>, len</fromCalldata>) { | ||||||
|  | 				let newLen := <arrayLength>(src<?fromCalldata>, len</fromCalldata>) | ||||||
|  | 				// Make sure array length is sane
 | ||||||
|  | 				if gt(newLen, 0xffffffffffffffff) { <panic>() } | ||||||
|  | 
 | ||||||
|  | 				let oldLen := <byteArrayLength>(sload(slot)) | ||||||
|  | 
 | ||||||
|  | 				<?fromMemory> | ||||||
|  | 					src := add(src, 0x20) | ||||||
|  | 				</fromMemory> | ||||||
|  | 
 | ||||||
|  | 				// This is not needed in all branches.
 | ||||||
|  | 				let dstDataArea | ||||||
|  | 				if or(gt(oldLen, 31), gt(newLen, 31)) { | ||||||
|  | 					dstDataArea := <dstDataLocation>(slot) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if gt(oldLen, 31) { | ||||||
|  | 					// potentially truncate data
 | ||||||
|  | 					let deleteStart := add(dstDataArea, div(add(newLen, 31), 32)) | ||||||
|  | 					if lt(newLen, 32) { deleteStart := dstDataArea } | ||||||
|  | 					<clearStorageRange>(deleteStart, add(dstDataArea, div(add(oldLen, 31), 32))) | ||||||
|  | 				} | ||||||
|  | 				switch gt(newLen, 31) | ||||||
|  | 				case 1 { | ||||||
|  | 					let loopEnd := and(newLen, not(0x1f)) | ||||||
|  | 					let dstPtr := dstDataArea | ||||||
|  | 					let i := 0 | ||||||
|  | 					for { } lt(i, loopEnd) { i := add(i, 32) } { | ||||||
|  | 						sstore(dstPtr, <readFromCalldataOrMemory>(add(src, i))) | ||||||
|  | 						dstPtr := add(dstPtr, 1) | ||||||
|  | 					} | ||||||
|  | 					if lt(loopEnd, newLen) { | ||||||
|  | 						let lastValue := <readFromCalldataOrMemory>(add(src, i)) | ||||||
|  | 						sstore(dstPtr, <maskBytes>(lastValue, and(newLen, 0x1f))) | ||||||
|  | 					} | ||||||
|  | 					sstore(slot, add(mul(newLen, 2), 1)) | ||||||
|  | 				} | ||||||
|  | 				default { | ||||||
|  | 					let value := 0 | ||||||
|  | 					if newLen { | ||||||
|  | 						value := <readFromCalldataOrMemory>(src) | ||||||
|  | 					} | ||||||
|  | 					sstore(slot, <byteArrayCombineShort>(value, newLen)) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		)"); | ||||||
|  | 		templ("functionName", functionName); | ||||||
|  | 		bool fromCalldata = _fromType.dataStoredIn(DataLocation::CallData); | ||||||
|  | 		templ("fromMemory", _fromType.dataStoredIn(DataLocation::Memory)); | ||||||
|  | 		templ("fromCalldata", fromCalldata); | ||||||
|  | 		templ("arrayLength", arrayLengthFunction(_fromType)); | ||||||
|  | 		templ("panic", panicFunction()); | ||||||
|  | 		templ("byteArrayLength", extractByteArrayLengthFunction()); | ||||||
|  | 		templ("dstDataLocation", arrayDataAreaFunction(_toType)); | ||||||
|  | 		templ("clearStorageRange", clearStorageRangeFunction(*_toType.baseType())); | ||||||
|  | 		templ("readFromCalldataOrMemory", readFromMemoryOrCalldata(*TypeProvider::uint256(), fromCalldata)); | ||||||
|  | 		templ("maskBytes", maskBytesFunctionDynamic()); | ||||||
|  | 		templ("byteArrayCombineShort", shortByteArrayEncodeUsedAreaSetLengthFunction()); | ||||||
|  | 
 | ||||||
|  | 		return templ.render(); | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| string YulUtilFunctions::arrayConvertLengthToSize(ArrayType const& _type) | string YulUtilFunctions::arrayConvertLengthToSize(ArrayType const& _type) | ||||||
| { | { | ||||||
| 	string functionName = "array_convert_length_to_size_" + _type.identifier(); | 	string functionName = "array_convert_length_to_size_" + _type.identifier(); | ||||||
| @ -2154,7 +2233,7 @@ string YulUtilFunctions::updateStorageValueFunction( | |||||||
| 				)"); | 				)"); | ||||||
| 				templ("functionName", functionName); | 				templ("functionName", functionName); | ||||||
| 				templ("value", suffixedVariableNameList("value_", 0, _fromType.sizeOnStack())); | 				templ("value", suffixedVariableNameList("value_", 0, _fromType.sizeOnStack())); | ||||||
| 				templ("copyArrayToStorage", copyArrayToStorage( | 				templ("copyArrayToStorage", copyArrayToStorageFunction( | ||||||
| 					dynamic_cast<ArrayType const&>(_fromType), | 					dynamic_cast<ArrayType const&>(_fromType), | ||||||
| 					dynamic_cast<ArrayType const&>(_toType) | 					dynamic_cast<ArrayType const&>(_toType) | ||||||
| 				)); | 				)); | ||||||
|  | |||||||
| @ -188,7 +188,11 @@ public: | |||||||
| 
 | 
 | ||||||
| 	/// @returns the name of a function that will copy array from calldata or memory to storage
 | 	/// @returns the name of a function that will copy array from calldata or memory to storage
 | ||||||
| 	/// signature (to_slot, from_ptr) ->
 | 	/// signature (to_slot, from_ptr) ->
 | ||||||
| 	std::string copyArrayToStorage(ArrayType const& _fromType, ArrayType const& _toType); | 	std::string copyArrayToStorageFunction(ArrayType const& _fromType, ArrayType const& _toType); | ||||||
|  | 
 | ||||||
|  | 	/// @returns the name of a function that will copy a byte array from calldata or memory to storage
 | ||||||
|  | 	/// signature (to_slot, from_ptr) ->
 | ||||||
|  | 	std::string copyByteArrayToStorageFunction(ArrayType const& _fromType, ArrayType const& _toType); | ||||||
| 
 | 
 | ||||||
| 	/// Returns the name of a function that will convert a given length to the
 | 	/// Returns the name of a function that will convert a given length to the
 | ||||||
| 	/// size in memory (number of storage slots or calldata/memory bytes) it
 | 	/// size in memory (number of storage slots or calldata/memory bytes) it
 | ||||||
|  | |||||||
| @ -2857,11 +2857,14 @@ BOOST_AUTO_TEST_CASE(delete_removes_bytes_data) | |||||||
| 			bytes data; | 			bytes data; | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	ABI_CHECK(callContractFunction("---", 7), bytes()); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	BOOST_CHECK(!storageEmpty(m_contractAddress)); | 		compileAndRun(sourceCode); | ||||||
| 	ABI_CHECK(callContractFunction("del()", 7), encodeArgs(true)); | 		ABI_CHECK(callContractFunction("---", 7), bytes()); | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		BOOST_CHECK(!storageEmpty(m_contractAddress)); | ||||||
|  | 		ABI_CHECK(callContractFunction("del()", 7), encodeArgs(true)); | ||||||
|  | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) | BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) | ||||||
| @ -2873,13 +2876,16 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) | |||||||
| 			bytes data; | 			bytes data; | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	BOOST_CHECK(!storageEmpty(m_contractAddress)); | 		compileAndRun(sourceCode); | ||||||
| 	sendMessage(bytes(), false); | 		ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); | ||||||
| 	BOOST_CHECK(m_transactionSuccessful); | 		BOOST_CHECK(!storageEmpty(m_contractAddress)); | ||||||
| 	BOOST_CHECK(m_output.empty()); | 		sendMessage(bytes(), false); | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		BOOST_CHECK(m_transactionSuccessful); | ||||||
|  | 		BOOST_CHECK(m_output.empty()); | ||||||
|  | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(copy_removes_bytes_data) | BOOST_AUTO_TEST_CASE(copy_removes_bytes_data) | ||||||
| @ -3125,17 +3131,21 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
|  | 		DISABLE_EWASM_TESTRUN() | ||||||
| 
 | 
 | ||||||
| 	string innercalldata1 = asString(FixedHash<4>(util::keccak256("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9)); | 		compileAndRun(sourceCode); | ||||||
| 	string innercalldata2 = asString(FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + encodeArgs(3)); | 
 | ||||||
| 	bytes calldata = encodeArgs( | 		string innercalldata1 = asString(FixedHash<4>(util::keccak256("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9)); | ||||||
| 		12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13, | 		string innercalldata2 = asString(FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + encodeArgs(3)); | ||||||
| 		u256(innercalldata1.length()), innercalldata1, | 		bytes calldata = encodeArgs( | ||||||
| 		u256(innercalldata2.length()), innercalldata2); | 			12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13, | ||||||
| 	ABI_CHECK( | 			u256(innercalldata1.length()), innercalldata1, | ||||||
| 		callContractFunction("test(uint256,bytes,bytes,uint256)", calldata), | 			u256(innercalldata2.length()), innercalldata2); | ||||||
| 		encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length())) | 		ABI_CHECK( | ||||||
|  | 			callContractFunction("test(uint256,bytes,bytes,uint256)", calldata), | ||||||
|  | 			encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length())) | ||||||
|  | 		); | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -3239,12 +3249,16 @@ BOOST_AUTO_TEST_CASE(dynamic_multi_array_cleanup) | |||||||
| 			function clear() public { delete data; } | 			function clear() public { delete data; } | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	ABI_CHECK(callContractFunction("fill()"), encodeArgs(8)); | 
 | ||||||
| 	BOOST_CHECK(!storageEmpty(m_contractAddress)); | 		compileAndRun(sourceCode); | ||||||
| 	ABI_CHECK(callContractFunction("clear()"), bytes()); | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		ABI_CHECK(callContractFunction("fill()"), encodeArgs(8)); | ||||||
|  | 		BOOST_CHECK(!storageEmpty(m_contractAddress)); | ||||||
|  | 		ABI_CHECK(callContractFunction("clear()"), bytes()); | ||||||
|  | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(array_copy_storage_storage_dyn_dyn) | BOOST_AUTO_TEST_CASE(array_copy_storage_storage_dyn_dyn) | ||||||
| @ -3361,20 +3375,24 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	bytes valueSequence; | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	for (size_t i = 0; i < 101; ++i) | 
 | ||||||
| 		valueSequence += toBigEndian(u256(i)); | 		compileAndRun(sourceCode); | ||||||
| 	ABI_CHECK(callContractFunction("test1()"), encodeArgs(0x20, 101) + valueSequence); | 		bytes valueSequence; | ||||||
| 	ABI_CHECK(callContractFunction("test2()"), encodeArgs(0x20, 101) + valueSequence); | 		for (size_t i = 0; i < 101; ++i) | ||||||
| 	ABI_CHECK(callContractFunction("test3()"), encodeArgs(0x20, 101) + valueSequence); | 			valueSequence += toBigEndian(u256(i)); | ||||||
| 	ABI_CHECK(callContractFunction("test4()"), | 		ABI_CHECK(callContractFunction("test1()"), encodeArgs(0x20, 101) + valueSequence); | ||||||
| 		encodeArgs(0x20, 5, 0xa0, 0xa0 + 102 * 32 * 1, 0xa0 + 102 * 32 * 2, 0xa0 + 102 * 32 * 3, 0xa0 + 102 * 32 * 4) + | 		ABI_CHECK(callContractFunction("test2()"), encodeArgs(0x20, 101) + valueSequence); | ||||||
| 		encodeArgs(101) + valueSequence + | 		ABI_CHECK(callContractFunction("test3()"), encodeArgs(0x20, 101) + valueSequence); | ||||||
| 		encodeArgs(101) + valueSequence + | 		ABI_CHECK(callContractFunction("test4()"), | ||||||
| 		encodeArgs(101) + valueSequence + | 			encodeArgs(0x20, 5, 0xa0, 0xa0 + 102 * 32 * 1, 0xa0 + 102 * 32 * 2, 0xa0 + 102 * 32 * 3, 0xa0 + 102 * 32 * 4) + | ||||||
| 		encodeArgs(101) + valueSequence + | 			encodeArgs(101) + valueSequence + | ||||||
| 		encodeArgs(101) + valueSequence | 			encodeArgs(101) + valueSequence + | ||||||
|  | 			encodeArgs(101) + valueSequence + | ||||||
|  | 			encodeArgs(101) + valueSequence + | ||||||
|  | 			encodeArgs(101) + valueSequence | ||||||
|  | 		); | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -3400,9 +3418,12 @@ BOOST_AUTO_TEST_CASE(array_pop_uint16_transition) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	ABI_CHECK(callContractFunction("test()"), encodeArgs(38, 28, 18)); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		compileAndRun(sourceCode); | ||||||
|  | 		ABI_CHECK(callContractFunction("test()"), encodeArgs(38, 28, 18)); | ||||||
|  | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(array_pop_uint24_transition) | BOOST_AUTO_TEST_CASE(array_pop_uint24_transition) | ||||||
| @ -3427,9 +3448,12 @@ BOOST_AUTO_TEST_CASE(array_pop_uint24_transition) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	ABI_CHECK(callContractFunction("test()"), encodeArgs(20, 10)); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		compileAndRun(sourceCode); | ||||||
|  | 		ABI_CHECK(callContractFunction("test()"), encodeArgs(20, 10)); | ||||||
|  | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(array_pop_array_transition) | BOOST_AUTO_TEST_CASE(array_pop_array_transition) | ||||||
| @ -3475,9 +3499,12 @@ BOOST_AUTO_TEST_CASE(array_pop_storage_empty) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	ABI_CHECK(callContractFunction("test()"), encodeArgs()); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		compileAndRun(sourceCode); | ||||||
|  | 		ABI_CHECK(callContractFunction("test()"), encodeArgs()); | ||||||
|  | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(byte_array_pop_storage_empty) | BOOST_AUTO_TEST_CASE(byte_array_pop_storage_empty) | ||||||
| @ -3495,9 +3522,12 @@ BOOST_AUTO_TEST_CASE(byte_array_pop_storage_empty) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	ABI_CHECK(callContractFunction("test()"), encodeArgs()); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		compileAndRun(sourceCode); | ||||||
|  | 		ABI_CHECK(callContractFunction("test()"), encodeArgs()); | ||||||
|  | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty) | BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty) | ||||||
| @ -3520,9 +3550,12 @@ BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); | 	ALSO_VIA_YUL( | ||||||
| 	ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 		compileAndRun(sourceCode); | ||||||
|  | 		ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); | ||||||
|  | 		BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty_garbage_ref) | BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty_garbage_ref) | ||||||
| @ -3598,15 +3631,19 @@ BOOST_AUTO_TEST_CASE(bytes_index_access) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode); |  | ||||||
| 	string array{ | 	string array{ | ||||||
| 		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | 		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | ||||||
| 		10, 11, 12, 13, 14, 15, 16, 17, 18, 19, | 		10, 11, 12, 13, 14, 15, 16, 17, 18, 19, | ||||||
| 		20, 21, 22, 23, 24, 25, 26, 27, 28, 29, | 		20, 21, 22, 23, 24, 25, 26, 27, 28, 29, | ||||||
| 		30, 31, 32, 33}; | 		30, 31, 32, 33}; | ||||||
| 	ABI_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); | 	ALSO_VIA_YUL( | ||||||
| 	ABI_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); | 		DISABLE_EWASM_TESTRUN() | ||||||
| 	ABI_CHECK(callContractFunction("storageWrite()"), encodeArgs(0x193)); | 
 | ||||||
|  | 		compileAndRun(sourceCode); | ||||||
|  | 		ABI_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); | ||||||
|  | 		ABI_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); | ||||||
|  | 		ABI_CHECK(callContractFunction("storageWrite()"), encodeArgs(0x193)); | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) | BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) | ||||||
|  | |||||||
| @ -20,5 +20,7 @@ contract C { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb | // f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb | ||||||
|  | |||||||
| @ -7,5 +7,7 @@ contract C { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg" | // f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg" | ||||||
|  | |||||||
| @ -14,5 +14,7 @@ contract c { | |||||||
|             uint8(data[97]) == 97; |             uint8(data[97]) == 97; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // test1() -> true | // test1() -> true | ||||||
|  | |||||||
| @ -10,6 +10,8 @@ contract c { | |||||||
| 
 | 
 | ||||||
|     bytes data; |     bytes data; | ||||||
| } | } | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // getLength() -> 0 | // getLength() -> 0 | ||||||
| // set(): 1, 2 -> true | // set(): 1, 2 -> true | ||||||
|  | |||||||
| @ -6,5 +6,7 @@ contract C { | |||||||
|     return s[0]; |     return s[0]; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // f() -> "a" | // f() -> "a" | ||||||
|  | |||||||
| @ -5,5 +5,7 @@ contract C { | |||||||
|     return s[0]; |     return s[0]; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // f(bytes): 0x20, 0x08, "abcdefgh" -> "a" | // f(bytes): 0x20, 0x08, "abcdefgh" -> "a" | ||||||
|  | |||||||
| @ -0,0 +1,42 @@ | |||||||
|  | pragma experimental ABIEncoderV2; | ||||||
|  | struct S { | ||||||
|  |     uint16 x; | ||||||
|  |     bytes a; | ||||||
|  |     uint16 y; | ||||||
|  |     bytes b; | ||||||
|  | } | ||||||
|  | contract C { | ||||||
|  |     uint padding; | ||||||
|  |     S data; | ||||||
|  | 
 | ||||||
|  |     function f() public returns (bytes memory, bytes memory) { | ||||||
|  |         S memory x; | ||||||
|  |         x.x = 7; | ||||||
|  |         x.b = "1234567890123456789012345678901 1234567890123456789012345678901 123456789"; | ||||||
|  |         x.a = "abcdef"; | ||||||
|  |         x.y = 9; | ||||||
|  |         data = x; | ||||||
|  |         return (data.a, data.b); | ||||||
|  |     } | ||||||
|  |     function g() public returns (bytes memory, bytes memory) { | ||||||
|  |         S memory x; | ||||||
|  |         x.x = 7; | ||||||
|  |         x.b = "12345678923456789"; | ||||||
|  |         x.a = "1234567890123456789012345678901 1234567890123456789012345678901 123456789"; | ||||||
|  |         x.y = 9; | ||||||
|  |         data = x; | ||||||
|  |         return (data.a, data.b); | ||||||
|  |     } | ||||||
|  |     function h() public returns (bytes memory, bytes memory) { | ||||||
|  |         S memory x; | ||||||
|  |         data = x; | ||||||
|  |         return (data.a, data.b); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
|  | // ---- | ||||||
|  | // f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000 | ||||||
|  | // g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000 | ||||||
|  | // h() -> 0x40, 0x60, 0x00, 0x00 | ||||||
|  | // storage: empty | ||||||
| @ -0,0 +1,50 @@ | |||||||
|  | function dataslot() pure returns (bytes32) { | ||||||
|  |     return keccak256(abi.encode(1)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function readDataSlot(uint offset) view returns (bytes32 r) { | ||||||
|  |     bytes32 s = dataslot(); | ||||||
|  |     assembly { r := sload(add(s, offset)) } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function readDataSlot() view returns (bytes32) { | ||||||
|  |     return readDataSlot(0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function readHead() view returns (bytes32 r) { | ||||||
|  |     assembly { r := sload(1) } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | contract C { | ||||||
|  |     uint padding; | ||||||
|  |     bytes data; | ||||||
|  | 
 | ||||||
|  |     function f() public returns (uint) { | ||||||
|  |         bytes32 zero; | ||||||
|  |         if (!(readDataSlot() == zero)) return 1; | ||||||
|  |         data = "abc"; | ||||||
|  |         if (!(readDataSlot() == zero)) return 2; | ||||||
|  |         data = "1234567890123456789012345678901234567890123456789012345678901234567890"; | ||||||
|  |         if (!(readDataSlot() != zero)) return 3; | ||||||
|  |         if (!(readDataSlot(1) != zero)) return 4; | ||||||
|  |         if (!(readDataSlot(2) != zero)) return 5; | ||||||
|  |         if (!(readDataSlot(3) == zero)) return 6; | ||||||
|  |         if (!(readDataSlot(4) == zero)) return 7; | ||||||
|  |         data = "abc"; | ||||||
|  |         if (!(readDataSlot() == zero)) return 8; | ||||||
|  |         if (!(readDataSlot(1) == zero)) return 9; | ||||||
|  |         if (!(readDataSlot(2) == zero)) return 10; | ||||||
|  |         if (!(readDataSlot(3) == zero)) return 11; | ||||||
|  |         data = "1234567890123456789012345678901234567890123456789012345678901234567890"; | ||||||
|  |         data = "123456789012345678901234567890123456"; | ||||||
|  |         if (!(readDataSlot() != zero)) return 12; | ||||||
|  |         if (!(readDataSlot(1) != zero)) return 13; | ||||||
|  |         if (!(readDataSlot(2) == zero)) return 14; | ||||||
|  |         if (!(readDataSlot(3) == zero)) return 15; | ||||||
|  |         return 0xff; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
|  | // ---- | ||||||
|  | // f() -> 0xff | ||||||
| @ -2,6 +2,8 @@ contract Test { | |||||||
|     bytes x; |     bytes x; | ||||||
|     function set(bytes memory _a) public { x = _a; } |     function set(bytes memory _a) public { x = _a; } | ||||||
| } | } | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // set(bytes): 0x20, 3, "abc" | // set(bytes): 0x20, 3, "abc" | ||||||
| // storage: nonempty | // storage: nonempty | ||||||
|  | |||||||
| @ -32,5 +32,7 @@ contract C { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // f(bytes): 0x20, 0x5, "abcde" -> 0 | // f(bytes): 0x20, 0x5, "abcde" -> 0 | ||||||
|  | |||||||
| @ -8,6 +8,8 @@ contract C { | |||||||
| 
 | 
 | ||||||
|     bytes savedData; |     bytes savedData; | ||||||
| } | } | ||||||
|  | // ==== | ||||||
|  | // compileViaYul: also | ||||||
| // ---- | // ---- | ||||||
| // save() -> 24 # empty copy loop # | // save() -> 24 # empty copy loop # | ||||||
| // save(): "abcdefg" -> 24 | // save(): "abcdefg" -> 24 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user