mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into breaking
This commit is contained in:
@@ -118,7 +118,7 @@ function test_solc_behaviour()
|
||||
# Remove bytecode (but not linker references).
|
||||
sed -i.bak -E -e 's/(\"object\":\")[0-9a-f]+([^"]*\")/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
|
||||
sed -i.bak -E -e 's/(\"object\":\"[^"]+\$__)[0-9a-f]+(\")/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
|
||||
sed -i.bak -E -e 's/(__\$[0-9a-f]{34}\$__)[0-9a-f]+(__\$[0-9a-f]{34}\$__)/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
|
||||
sed -i.bak -E -e 's/([0-9a-f]{34}\$__)[0-9a-f]+(__\$[0-9a-f]{17})/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
|
||||
|
||||
# Replace escaped newlines by actual newlines for readability
|
||||
sed -i.bak -E -e 's/\\n/\'$'\n/g' "$stdout_path"
|
||||
@@ -128,7 +128,7 @@ function test_solc_behaviour()
|
||||
sed -i.bak -e '/^Warning (3805): This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
|
||||
sed -i.bak -e 's/\(^[ ]*auxdata: \)0x[0-9a-f]*$/\1<AUXDATA REMOVED>/' "$stdout_path"
|
||||
sed -i.bak -e 's/ Consider adding "pragma .*$//' "$stderr_path"
|
||||
sed -i.bak -e 's/\(Unimplemented feature error: .* in \).*$/\1<FILENAME REMOVED>/' "$stderr_path"
|
||||
sed -i.bak -e 's/\(Unimplemented feature error.* in \).*$/\1<FILENAME REMOVED>/' "$stderr_path"
|
||||
sed -i.bak -e 's/"version": "[^"]*"/"version": "<VERSION REMOVED>"/' "$stdout_path"
|
||||
|
||||
# Remove bytecode (but not linker references). Since non-JSON output is unstructured,
|
||||
@@ -137,7 +137,7 @@ function test_solc_behaviour()
|
||||
# 64697066735822 = hex encoding of 0x64 'i' 'p' 'f' 's' 0x58 0x22
|
||||
# 64736f6c63 = hex encoding of 0x64 's' 'o' 'l' 'c'
|
||||
sed -i.bak -E -e 's/[0-9a-f]*64697066735822[0-9a-f]+64736f6c63[0-9a-f]+/<BYTECODE REMOVED>/g' "$stdout_path"
|
||||
sed -i.bak -E -e 's/(__\$[0-9a-f]{34}\$__)[0-9a-f]+(__\$[0-9a-f]{34}\$__)/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
|
||||
sed -i.bak -E -e 's/([0-9a-f]{17}\$__)[0-9a-f]+(__\$[0-9a-f]{17})/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
|
||||
sed -i.bak -E -e 's/[0-9a-f]+((__\$[0-9a-f]{34}\$__)*<BYTECODE REMOVED>)/<BYTECODE REMOVED>\1/g' "$stdout_path"
|
||||
|
||||
# Remove trailing empty lines. Needs a line break to make OSX sed happy.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"settings": {
|
||||
"libraries": {
|
||||
"contract/test.sol": {
|
||||
"A": {
|
||||
"L": "0x1234567890123456789012345678901234567890"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources": {
|
||||
"A": {
|
||||
"A\"B": {
|
||||
"content": "
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0;
|
||||
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"settings": {
|
||||
"libraries": {
|
||||
"contract/test\"test.sol": {
|
||||
"A\"B": {
|
||||
"L": "0x1234567890123456789012345678901234567890"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"sources":{"A":{"id":0}}}
|
||||
{"contracts":{"A\"B":{"C":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"sources":{"A\"B":{"id":0}}}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
},
|
||||
"settings": {
|
||||
"libraries": {
|
||||
"contract/test.sol": {
|
||||
"A": {
|
||||
"L1": "0x1234567890123456789012345678901234567890"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
--strict-assembly --libraries library.sol:L:0x1234567890123456789012345678901234567890,library.sol:L:0x0987654321098765432109876543210987654321
|
||||
@@ -0,0 +1 @@
|
||||
Address specified more than once for library "library.sol:L".
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
object "a" {
|
||||
code {
|
||||
let addr := linkersymbol("library.sol:L")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
--strict-assembly --libraries L:0x1234567890123456789012345678901234567890
|
||||
@@ -0,0 +1 @@
|
||||
Warning: Yul is still experimental. Please use the output with care.
|
||||
@@ -0,0 +1,5 @@
|
||||
object "a" {
|
||||
code {
|
||||
let addr := linkersymbol("L")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
======= linking_strict_assembly_no_file_name_in_link_reference/input.yul (EVM) =======
|
||||
|
||||
Pretty printed source:
|
||||
object "a" {
|
||||
code { let addr := linkersymbol("L") }
|
||||
}
|
||||
|
||||
|
||||
Binary representation:
|
||||
73123456789012345678901234567890123456789050
|
||||
|
||||
Text representation:
|
||||
linkerSymbol("8aa64f937099b65a4febc243a5ae0f2d6416bb9e473c30dd29c1ee498fb7c5a8")
|
||||
/* "linking_strict_assembly_no_file_name_in_link_reference/input.yul":22:67 */
|
||||
pop
|
||||
@@ -0,0 +1 @@
|
||||
--strict-assembly --libraries library1.sol:L:0x1111111111111111111111111111111111111111,library2.sol:L:0x2222222222222222222222222222222222222222
|
||||
@@ -0,0 +1 @@
|
||||
Warning: Yul is still experimental. Please use the output with care.
|
||||
@@ -0,0 +1,6 @@
|
||||
object "a" {
|
||||
code {
|
||||
let addr1 := linkersymbol("library1.sol:L")
|
||||
let addr2 := linkersymbol("library2.sol:L")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
======= linking_strict_assembly_same_library_name_different_files/input.yul (EVM) =======
|
||||
|
||||
Pretty printed source:
|
||||
object "a" {
|
||||
code {
|
||||
let addr1 := linkersymbol("library1.sol:L")
|
||||
let addr2 := linkersymbol("library2.sol:L")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary representation:
|
||||
7311111111111111111111111111111111111111117322222222222222222222222222222222222222225050
|
||||
|
||||
Text representation:
|
||||
linkerSymbol("f3ffc10c396a7cc41ae954b050792839d20947bf73497d30c49a9fda1ea477ec")
|
||||
/* "linking_strict_assembly_same_library_name_different_files/input.yul":32:75 */
|
||||
linkerSymbol("c3523432985587641d17c68161d2f700c57aaf4ed21cda4f25d76193c831f97f")
|
||||
/* "linking_strict_assembly_same_library_name_different_files/input.yul":22:133 */
|
||||
pop
|
||||
pop
|
||||
+1
@@ -0,0 +1 @@
|
||||
--strict-assembly --libraries library1.sol:L:0x1234567890123456789012345678901234567890
|
||||
+1
@@ -0,0 +1 @@
|
||||
Warning: Yul is still experimental. Please use the output with care.
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
object "a" {
|
||||
code {
|
||||
let addr1 := linkersymbol("library1.sol:L")
|
||||
let addr2 := linkersymbol("library2.sol:L")
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
|
||||
======= linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul (EVM) =======
|
||||
|
||||
Pretty printed source:
|
||||
object "a" {
|
||||
code {
|
||||
let addr1 := linkersymbol("library1.sol:L")
|
||||
let addr2 := linkersymbol("library2.sol:L")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary representation:
|
||||
73123456789012345678901234567890123456789073__$c3523432985587641d17c68161d2f700c5$__5050
|
||||
|
||||
Text representation:
|
||||
linkerSymbol("f3ffc10c396a7cc41ae954b050792839d20947bf73497d30c49a9fda1ea477ec")
|
||||
/* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":32:75 */
|
||||
linkerSymbol("c3523432985587641d17c68161d2f700c57aaf4ed21cda4f25d76193c831f97f")
|
||||
/* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":22:133 */
|
||||
pop
|
||||
pop
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"outputSelection":
|
||||
{
|
||||
"*": { "*": ["ewasm.wast"] }
|
||||
"*": { "*": ["ewasm.wast", "ewasm.wasm"] }
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
{"contracts":{"A":{"C":{"ewasm":{"wast":"(module
|
||||
{"contracts":{"A":{"C":{"ewasm":{"wasm":"0061736d01000000013a0860000060017e017e60047e7e7e7e017f60087e7e7e7e7e7e7e7e00600c7e7e7e7e7e7e7e7e7e7e7e7e0060017f0060027f7f0060037f7f7f0002510408657468657265756d08636f6465436f7079000708657468657265756d06726576657274000608657468657265756d0c67657443616c6c56616c7565000508657468657265756d0666696e6973680006030a090002020401010103030503010001060100071102066d656d6f72790200046d61696e0004009d030c435f325f6465706c6f7965640061736d0100000001160460000060017e017e60047e7e7e7e017f60027f7f0002130108657468657265756d067265766572740003030504000201010503010001060100071102066d656d6f72790200046d61696e00010ab60204ca0104017e027f057e037f02404200210020002000200042c00010022101200141c0006a210220022001490440000b20001003421086210320032000421088100384422086210420042000422088100484210520022005370000200241086a2005370000200241106a20053700004280011003421086210620064280014210881003844220862107200241186a2007428001422088100484370000200020002000200010022108200020002000200010022109200941c0006a210a200a2009490440000b200a200810000b0b2901017f024042002000200184200284520440000b42002003422088520440000b2003a721040b20040b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100342108621022002200042108810038421010b20010b0aec0309dc0103017e027f057e02404200210020002000200042c00010052101200141c0006a210220022001490440000b2000100a210320022003370000200241086a2003370000200241106a2003370000200241186a428001100a370000410010024100290000100a2104410041086a290000100a2105410041106a290000100a210620042005842006410041186a290000100a84845045044020002000200020002000200020002000100c0b4290032107200020002000200020002000200042ce012000200020002007100720002000200020002000200020002007100b0b0b2901017f024042002000200184200284520440000b42002003422088520440000b2003a721040b20040b2601027f0240200020012002200310052105200541c0006a210420042005490440000b0b20040b25000240200020012002200310062004200520062007100520082009200a200b100510000b0b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100842108621022002200042108810088421010b20010b1e01027e02402000100942208621022002200042208810098421010b20010b1b000240200020012002200310062004200520062007100510030b0b1b000240200020012002200310062004200520062007100510010b0b","wast":"(module
|
||||
;; custom section for sub-module
|
||||
;; The Keccak-256 hash of the text representation of \"C_2_deployed\": f03f5b9154b9eb6803a947177e38e92e2860de95e90ba0e75eb71a58f18ed589
|
||||
;; (@custom \"C_2_deployed\" \"0061736d0100000001160460000060017e017e60047e7e7e7e017f60027f7f0002130108657468657265756d067265766572740003030504000201010503010001060100071102066d656d6f72790200046d61696e00010ab60204ca0104017e027f057e037f02404200210020002000200042c00010022101200141c0006a210220022001490440000b20001003421086210320032000421088100384422086210420042000422088100484210520022005370000200241086a2005370000200241106a20053700004280011003421086210620064280014210881003844220862107200241186a2007428001422088100484370000200020002000200010022108200020002000200010022109200941c0006a210a200a2009490440000b200a200810000b0b2901017f024042002000200184200284520440000b42002003422088520440000b2003a721040b20040b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100342108621022002200042108810038421010b20010b\")
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; abstract contract C { }"
|
||||
}
|
||||
},
|
||||
"settings":
|
||||
{
|
||||
"optimizer":
|
||||
{
|
||||
"enabled": true,
|
||||
"details": {"yul": true}
|
||||
},
|
||||
"outputSelection":
|
||||
{
|
||||
"*": { "*": ["ewasm.wast", "ewasm.wasm"] }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"contracts":{"A":{"C":{"ewasm":{"wasm":"","wast":""}}}},"sources":{"A":{"id":0}}}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C {} contract D { function f() public { C c = new C(); } }"
|
||||
}
|
||||
},
|
||||
"settings":
|
||||
{
|
||||
"optimizer": {
|
||||
"enabled": true
|
||||
},
|
||||
"outputSelection":
|
||||
{
|
||||
"*": { "*": ["ir", "evm.bytecode.object", "evm.bytecode.generatedSources", "evm.deployedBytecode.object"] }
|
||||
},
|
||||
"viaIR": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":""},"deployedBytecode":{"generatedSources":[],"immutableReferences":{},"linkReferences":{},"object":"","opcodes":"","sourceMap":""}},"ir":"/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
|
||||
object \"C_2\" {
|
||||
code {
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
|
||||
constructor_C_2()
|
||||
|
||||
codecopy(0, dataoffset(\"C_2_deployed\"), datasize(\"C_2_deployed\"))
|
||||
|
||||
return(0, datasize(\"C_2_deployed\"))
|
||||
|
||||
function constructor_C_2() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
object \"C_2_deployed\" {
|
||||
code {
|
||||
mstore(64, 128)
|
||||
|
||||
if iszero(lt(calldatasize(), 4))
|
||||
{
|
||||
let selector := shift_right_224_unsigned(calldataload(0))
|
||||
switch selector
|
||||
|
||||
default {}
|
||||
}
|
||||
if iszero(calldatasize()) { }
|
||||
revert(0, 0)
|
||||
|
||||
function shift_right_224_unsigned(value) -> newValue {
|
||||
newValue :=
|
||||
|
||||
shr(224, value)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"},"D":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":""},"deployedBytecode":{"generatedSources":[],"immutableReferences":{},"linkReferences":{},"object":"","opcodes":"","sourceMap":""}},"ir":"/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
|
||||
object \"D_13\" {
|
||||
code {
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
|
||||
constructor_D_13()
|
||||
|
||||
codecopy(0, dataoffset(\"D_13_deployed\"), datasize(\"D_13_deployed\"))
|
||||
|
||||
return(0, datasize(\"D_13_deployed\"))
|
||||
|
||||
function constructor_D_13() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
object \"D_13_deployed\" {
|
||||
code {
|
||||
mstore(64, 128)
|
||||
|
||||
if iszero(lt(calldatasize(), 4))
|
||||
{
|
||||
let selector := shift_right_224_unsigned(calldataload(0))
|
||||
switch selector
|
||||
|
||||
case 0x26121ff0
|
||||
{
|
||||
// f()
|
||||
if callvalue() { revert(0, 0) }
|
||||
abi_decode_tuple_(4, calldatasize())
|
||||
fun_f_12()
|
||||
let memPos := allocateMemory(0)
|
||||
let memEnd := abi_encode_tuple__to__fromStack(memPos )
|
||||
return(memPos, sub(memEnd, memPos))
|
||||
}
|
||||
|
||||
default {}
|
||||
}
|
||||
if iszero(calldatasize()) { }
|
||||
revert(0, 0)
|
||||
|
||||
function abi_decode_tuple_(headStart, dataEnd) {
|
||||
if slt(sub(dataEnd, headStart), 0) { revert(0, 0) }
|
||||
|
||||
}
|
||||
|
||||
function abi_encode_tuple__to__fromStack(headStart ) -> tail {
|
||||
tail := add(headStart, 0)
|
||||
|
||||
}
|
||||
|
||||
function allocateMemory(size) -> memPtr {
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
// protect against overflow
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
|
||||
function allocateTemporaryMemory() -> memPtr {
|
||||
memPtr := mload(64)
|
||||
}
|
||||
|
||||
function fun_f_12() {
|
||||
|
||||
let _1 := allocateTemporaryMemory()
|
||||
let _2 := add(_1, datasize(\"C_2\"))
|
||||
if or(gt(_2, 0xffffffffffffffff), lt(_2, _1)) { panic_error() }
|
||||
datacopy(_1, dataoffset(\"C_2\"), datasize(\"C_2\"))
|
||||
_2 := abi_encode_tuple__to__fromStack(_2)
|
||||
|
||||
let expr_9_address := create(0, _1, sub(_2, _1))
|
||||
|
||||
releaseTemporaryMemory()
|
||||
let vloc_c_6_address := expr_9_address
|
||||
|
||||
}
|
||||
|
||||
function panic_error() {
|
||||
invalid()
|
||||
}
|
||||
|
||||
function releaseTemporaryMemory() {
|
||||
}
|
||||
|
||||
function shift_right_224_unsigned(value) -> newValue {
|
||||
newValue :=
|
||||
|
||||
shr(224, value)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
object \"C_2\" {
|
||||
code {
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
|
||||
constructor_C_2()
|
||||
|
||||
codecopy(0, dataoffset(\"C_2_deployed\"), datasize(\"C_2_deployed\"))
|
||||
|
||||
return(0, datasize(\"C_2_deployed\"))
|
||||
|
||||
function constructor_C_2() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
object \"C_2_deployed\" {
|
||||
code {
|
||||
mstore(64, 128)
|
||||
|
||||
if iszero(lt(calldatasize(), 4))
|
||||
{
|
||||
let selector := shift_right_224_unsigned(calldataload(0))
|
||||
switch selector
|
||||
|
||||
default {}
|
||||
}
|
||||
if iszero(calldatasize()) { }
|
||||
revert(0, 0)
|
||||
|
||||
function shift_right_224_unsigned(value) -> newValue {
|
||||
newValue :=
|
||||
|
||||
shr(224, value)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"}}},"errors":[{"component":"general","errorCode":"2072","formattedMessage":"A:2:73: Warning: Unused local variable.
|
||||
pragma solidity >=0.0; contract C {} contract D { function f() public { C c = new C(); } }
|
||||
^-^
|
||||
","message":"Unused local variable.","severity":"warning","sourceLocation":{"end":111,"file":"A","start":108},"type":"Warning"}],"sources":{"A":{"id":0}}}
|
||||
@@ -0,0 +1 @@
|
||||
--ir-optimized --experimental-via-ir --optimize --bin --bin-runtime
|
||||
@@ -0,0 +1,5 @@
|
||||
Warning: Unused local variable.
|
||||
--> viair_subobjects/input.sol:7:9:
|
||||
|
|
||||
7 | C c = new C();
|
||||
| ^^^
|
||||
@@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.6.0;
|
||||
|
||||
contract C {}
|
||||
contract D {
|
||||
function f() public {
|
||||
C c = new C();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
|
||||
======= viair_subobjects/input.sol:C =======
|
||||
Binary:
|
||||
60806040523415600f5760006000fd5b600a80601e600039806000f350fe608060405260006000fd
|
||||
Binary of the runtime part:
|
||||
|
||||
Optimized IR:
|
||||
/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
object "C_2" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("C_2_deployed")
|
||||
codecopy(0, dataoffset("C_2_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "C_2_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
======= viair_subobjects/input.sol:D =======
|
||||
Binary:
|
||||
608060405234156100105760006000fd5b60d380610020600039806000f350fe6080604052600436101515610074576000803560e01c6326121ff0141561007257341561002a578081fd5b806003193601121561003a578081fd5b6028806080016080811067ffffffffffffffff8211171561005757fe5b50806100ab60803980608083f05050806100708261007e565bf35b505b60006000fd6100a9565b6000604051905081810181811067ffffffffffffffff8211171561009e57fe5b80604052505b919050565bfe60806040523415600f5760006000fd5b600a80601e600039806000f350fe608060405260006000fd
|
||||
Binary of the runtime part:
|
||||
|
||||
Optimized IR:
|
||||
/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
object "D_13" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("D_13_deployed")
|
||||
codecopy(0, dataoffset("D_13_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "D_13_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if iszero(lt(calldatasize(), 4))
|
||||
{
|
||||
let _1 := 0
|
||||
if eq(0x26121ff0, shr(224, calldataload(_1)))
|
||||
{
|
||||
if callvalue() { revert(_1, _1) }
|
||||
if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) }
|
||||
let _2 := datasize("C_2")
|
||||
let _3 := add(128, _2)
|
||||
if or(gt(_3, 0xffffffffffffffff), lt(_3, 128)) { invalid() }
|
||||
datacopy(128, dataoffset("C_2"), _2)
|
||||
pop(create(_1, 128, _2))
|
||||
return(allocateMemory(_1), _1)
|
||||
}
|
||||
}
|
||||
revert(0, 0)
|
||||
}
|
||||
function allocateMemory(size) -> memPtr
|
||||
{
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { invalid() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
}
|
||||
object "C_2" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("C_2_deployed")
|
||||
codecopy(0, dataoffset("C_2_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "C_2_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Error (1834): Unimplemented feature error: Copying from storage to storage is not yet implemented. in <FILENAME REMOVED>
|
||||
--> yul_unimplemented/input.sol:7:9:
|
||||
Error (1834): Unimplemented feature error in <FILENAME REMOVED>
|
||||
--> yul_unimplemented/input.sol:8:9:
|
||||
|
|
||||
7 | a = b;
|
||||
8 | x.f();
|
||||
| ^^^^^
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0;
|
||||
library L { function f(uint) public {} }
|
||||
contract test {
|
||||
bytes a;
|
||||
bytes b;
|
||||
using L for uint;
|
||||
function f() public {
|
||||
a = b;
|
||||
uint x;
|
||||
x.f();
|
||||
}
|
||||
}
|
||||
@@ -282,6 +282,38 @@ BOOST_AUTO_TEST_CASE(metadata_useLiteralContent)
|
||||
check(sourceCode, false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(metadata_viair)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
pragma solidity >=0.0;
|
||||
contract test {
|
||||
}
|
||||
)";
|
||||
|
||||
auto check = [](char const* _src, bool _viair)
|
||||
{
|
||||
CompilerStack compilerStack;
|
||||
compilerStack.setSources({{"", std::string(_src)}});
|
||||
compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
|
||||
compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
|
||||
compilerStack.setViaIR(_viair);
|
||||
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
|
||||
string metadata_str = compilerStack.metadata("test");
|
||||
Json::Value metadata;
|
||||
util::jsonParseStrict(metadata_str, metadata);
|
||||
BOOST_CHECK(solidity::test::isValidMetadata(metadata_str));
|
||||
BOOST_CHECK(metadata.isMember("settings"));
|
||||
if (_viair)
|
||||
{
|
||||
BOOST_CHECK(metadata["settings"].isMember("viaIR"));
|
||||
BOOST_CHECK(metadata["settings"]["viaIR"].asBool());
|
||||
}
|
||||
};
|
||||
|
||||
check(sourceCode, true);
|
||||
check(sourceCode, false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(metadata_revert_strings)
|
||||
{
|
||||
CompilerStack compilerStack;
|
||||
|
||||
@@ -2500,25 +2500,6 @@ BOOST_AUTO_TEST_CASE(copying_bytes_multiassign)
|
||||
ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(delete_removes_bytes_data)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
fallback() external { data = msg.data; }
|
||||
function del() public returns (bool) { delete data; return true; }
|
||||
bytes data;
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("---", 7), bytes());
|
||||
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)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
@@ -2540,83 +2521,6 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(copy_removes_bytes_data)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
function set() public returns (bool) { data1 = msg.data; return true; }
|
||||
function reset() public returns (bool) { data1 = data2; return true; }
|
||||
bytes data1;
|
||||
bytes data2;
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true));
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("reset()"), encodeArgs(true));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bytes_inside_mappings)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
function set(uint key) public returns (bool) { data[key] = msg.data; return true; }
|
||||
function copy(uint from, uint to) public returns (bool) { data[to] = data[from]; return true; }
|
||||
mapping(uint => bytes) data;
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
// store a short byte array at 1 and a longer one at 2
|
||||
ABI_CHECK(callContractFunction("set(uint256)", 1, 2), encodeArgs(true));
|
||||
ABI_CHECK(callContractFunction("set(uint256)", 2, 2, 3, 4, 5), encodeArgs(true));
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
// copy shorter to longer
|
||||
ABI_CHECK(callContractFunction("copy(uint256,uint256)", 1, 2), encodeArgs(true));
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
// copy empty to both
|
||||
ABI_CHECK(callContractFunction("copy(uint256,uint256)", 99, 1), encodeArgs(true));
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("copy(uint256,uint256)", 99, 2), encodeArgs(true));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
struct Struct { uint a; bytes data; uint b; }
|
||||
Struct data1;
|
||||
Struct data2;
|
||||
function set(uint _a, bytes calldata _data, uint _b) external returns (bool) {
|
||||
data1.a = _a;
|
||||
data1.b = _b;
|
||||
data1.data = _data;
|
||||
return true;
|
||||
}
|
||||
function copy() public returns (bool) {
|
||||
data1 = data2;
|
||||
return true;
|
||||
}
|
||||
function del() public returns (bool) {
|
||||
delete data1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
string data = "123456789012345678901234567890123";
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true));
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("copy()"), encodeArgs(true));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true));
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("del()"), encodeArgs(true));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(storing_invalid_boolean)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
@@ -2801,197 +2705,6 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_array_cleanup)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint spacer1;
|
||||
uint spacer2;
|
||||
uint[20] data;
|
||||
function fill() public {
|
||||
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
|
||||
}
|
||||
function clear() public { delete data; }
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("fill()"), bytes());
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("clear()"), bytes());
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(short_fixed_array_cleanup)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint spacer1;
|
||||
uint spacer2;
|
||||
uint[3] data;
|
||||
function fill() public {
|
||||
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
|
||||
}
|
||||
function clear() public { delete data; }
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("fill()"), bytes());
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("clear()"), bytes());
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dynamic_array_cleanup)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint[20] spacer;
|
||||
uint[] dynamic;
|
||||
function fill() public {
|
||||
for (uint i = 0; i < 21; ++i)
|
||||
dynamic.push(i + 1);
|
||||
}
|
||||
function halfClear() public {
|
||||
while (dynamic.length > 5)
|
||||
dynamic.pop();
|
||||
}
|
||||
function fullClear() public { delete dynamic; }
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("fill()"), bytes());
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("halfClear()"), bytes());
|
||||
BOOST_CHECK(!storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("fullClear()"), bytes());
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dynamic_multi_array_cleanup)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
struct s { uint[][] d; }
|
||||
s[] data;
|
||||
function fill() public returns (uint) {
|
||||
while (data.length < 3)
|
||||
data.push();
|
||||
while (data[2].d.length < 4)
|
||||
data[2].d.push();
|
||||
while (data[2].d[3].length < 5)
|
||||
data[2].d[3].push();
|
||||
data[2].d[3][4] = 8;
|
||||
return data[2].d[3][4];
|
||||
}
|
||||
function clear() public { delete data; }
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
|
||||
compileAndRun(sourceCode);
|
||||
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)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint[] data1;
|
||||
uint[] data2;
|
||||
function setData1(uint length, uint index, uint value) public {
|
||||
data1 = new uint[](length);
|
||||
if (index < length)
|
||||
data1[index] = value;
|
||||
}
|
||||
function copyStorageStorage() public { data2 = data1; }
|
||||
function getData2(uint index) public returns (uint len, uint val) {
|
||||
len = data2.length; if (index < len) val = data2[index];
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 10, 5, 4), bytes());
|
||||
ABI_CHECK(callContractFunction("copyStorageStorage()"), bytes());
|
||||
ABI_CHECK(callContractFunction("getData2(uint256)", 5), encodeArgs(10, 4));
|
||||
ABI_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 0, 0, 0), bytes());
|
||||
ABI_CHECK(callContractFunction("copyStorageStorage()"), bytes());
|
||||
ABI_CHECK(callContractFunction("getData2(uint256)", 0), encodeArgs(0, 0));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_copy_target_leftover)
|
||||
{
|
||||
// test that leftover elements in the last slot of target are correctly cleared during assignment
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
byte[10] data1;
|
||||
bytes2[32] data2;
|
||||
function test() public returns (uint check, uint res1, uint res2) {
|
||||
uint i;
|
||||
for (i = 0; i < data2.length; ++i)
|
||||
data2[i] = 0xffff;
|
||||
check = uint(uint16(data2[31])) * 0x10000 | uint(uint16(data2[14]));
|
||||
for (i = 0; i < data1.length; ++i)
|
||||
data1[i] = byte(uint8(1 + i));
|
||||
data2 = data1;
|
||||
for (i = 0; i < 16; ++i)
|
||||
res1 |= uint(uint16(data2[i])) * 0x10000**i;
|
||||
for (i = 0; i < 16; ++i)
|
||||
res2 |= uint(uint16(data2[16 + i])) * 0x10000**i;
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs(u256("0xffffffff"), asString(fromHex("0000000000000000000000000a00090008000700060005000400030002000100")), asString(fromHex("0000000000000000000000000000000000000000000000000000000000000000"))));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
struct Data { uint x; uint y; }
|
||||
Data[] data1;
|
||||
Data[] data2;
|
||||
function test() public returns (uint x, uint y) {
|
||||
while (data1.length < 9)
|
||||
data1.push();
|
||||
data1[8].x = 4;
|
||||
data1[8].y = 5;
|
||||
data2 = data1;
|
||||
x = data2[8].x;
|
||||
y = data2[8].y;
|
||||
while (data1.length > 0)
|
||||
data1.pop();
|
||||
data2 = data1;
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs(4, 5));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_copy_storage_abi)
|
||||
{
|
||||
// NOTE: This does not really test copying from storage to ABI directly,
|
||||
@@ -3048,331 +2761,6 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_pop_uint16_transition)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint16[] data;
|
||||
function test() public returns (uint16 x, uint16 y, uint16 z) {
|
||||
for (uint i = 1; i <= 48; i++)
|
||||
data.push(uint16(i));
|
||||
for (uint j = 1; j <= 10; j++)
|
||||
data.pop();
|
||||
x = data[data.length - 1];
|
||||
for (uint k = 1; k <= 10; k++)
|
||||
data.pop();
|
||||
y = data[data.length - 1];
|
||||
for (uint l = 1; l <= 10; l++)
|
||||
data.pop();
|
||||
z = data[data.length - 1];
|
||||
for (uint m = 1; m <= 18; m++)
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs(38, 28, 18));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_pop_uint24_transition)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
uint256 c;
|
||||
uint24[] data;
|
||||
function test() public returns (uint24 x, uint24 y) {
|
||||
for (uint i = 1; i <= 30; i++)
|
||||
data.push(uint24(i));
|
||||
for (uint j = 1; j <= 10; j++)
|
||||
data.pop();
|
||||
x = data[data.length - 1];
|
||||
for (uint k = 1; k <= 10; k++)
|
||||
data.pop();
|
||||
y = data[data.length - 1];
|
||||
for (uint l = 1; l <= 10; l++)
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs(20, 10));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_pop_array_transition)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
uint256 c;
|
||||
uint16[] inner = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
||||
uint16[][] data;
|
||||
function test() public returns (uint x, uint y, uint z) {
|
||||
for (uint i = 1; i <= 48; i++)
|
||||
data.push(inner);
|
||||
for (uint j = 1; j <= 10; j++)
|
||||
data.pop();
|
||||
x = data[data.length - 1][0];
|
||||
for (uint k = 1; k <= 10; k++)
|
||||
data.pop();
|
||||
y = data[data.length - 1][1];
|
||||
for (uint l = 1; l <= 10; l++)
|
||||
data.pop();
|
||||
z = data[data.length - 1][2];
|
||||
for (uint m = 1; m <= 18; m++)
|
||||
data.pop();
|
||||
delete inner;
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs(1, 2, 3));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_pop_storage_empty)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint[] data;
|
||||
function test() public {
|
||||
data.push(7);
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs());
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(byte_array_pop_storage_empty)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
bytes data;
|
||||
function test() public {
|
||||
data.push(0x07);
|
||||
data.push(0x05);
|
||||
data.push(0x03);
|
||||
data.pop();
|
||||
data.pop();
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs());
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
uint256 c;
|
||||
bytes data;
|
||||
function test() public returns (bool) {
|
||||
for (uint8 i = 0; i <= 40; i++)
|
||||
data.push(byte(i+1));
|
||||
for (int8 j = 40; j >= 0; j--) {
|
||||
require(data[uint8(j)] == byte(j+1));
|
||||
require(data.length == uint8(j+1));
|
||||
data.pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
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)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
bytes data;
|
||||
function test() public {
|
||||
for (uint8 i = 0; i <= 40; i++)
|
||||
data.push(0x03);
|
||||
for (uint8 j = 0; j <= 40; j++) {
|
||||
assembly {
|
||||
mstore(0, "garbage")
|
||||
}
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs());
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(external_array_args)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
function test(uint[8] calldata a, uint[] calldata b, uint[5] calldata c, uint a_index, uint b_index, uint c_index)
|
||||
external returns (uint av, uint bv, uint cv) {
|
||||
av = a[a_index];
|
||||
bv = b[b_index];
|
||||
cv = c[c_index];
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
bytes params = encodeArgs(
|
||||
1, 2, 3, 4, 5, 6, 7, 8, // a
|
||||
32 * (8 + 1 + 5 + 1 + 1 + 1), // offset to b
|
||||
21, 22, 23, 24, 25, // c
|
||||
0, 1, 2, // (a,b,c)_index
|
||||
3, // b.length
|
||||
11, 12, 13 // b
|
||||
);
|
||||
ABI_CHECK(callContractFunction("test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256)", params), encodeArgs(1, 12, 23));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bytes_index_access)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
bytes data;
|
||||
function direct(bytes calldata arg, uint index) external returns (uint) {
|
||||
return uint(uint8(arg[index]));
|
||||
}
|
||||
function storageCopyRead(bytes calldata arg, uint index) external returns (uint) {
|
||||
data = arg;
|
||||
return uint(uint8(data[index]));
|
||||
}
|
||||
function storageWrite() external returns (uint) {
|
||||
data = new bytes(35);
|
||||
data[31] = 0x77;
|
||||
data[32] = 0x14;
|
||||
|
||||
data[31] = 0x01;
|
||||
data[31] |= 0x08;
|
||||
data[30] = 0x01;
|
||||
data[32] = 0x03;
|
||||
return uint(uint8(data[30])) * 0x100 | uint(uint8(data[31])) * 0x10 | uint(uint8(data[32]));
|
||||
}
|
||||
}
|
||||
)";
|
||||
string array{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||
30, 31, 32, 33};
|
||||
ALSO_VIA_YUL(
|
||||
DISABLE_EWASM_TESTRUN()
|
||||
|
||||
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)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint[9] m_data;
|
||||
uint[] m_data_dyn;
|
||||
uint8[][] m_byte_data;
|
||||
function store(uint[9] calldata a, uint8[3][] calldata b) external returns (uint8) {
|
||||
m_data = a;
|
||||
m_data_dyn = a;
|
||||
m_byte_data = b;
|
||||
return b[3][1]; // note that access and declaration are reversed to each other
|
||||
}
|
||||
function retrieve() public returns (uint a, uint b, uint c, uint d, uint e, uint f, uint g) {
|
||||
a = m_data.length;
|
||||
b = m_data[7];
|
||||
c = m_data_dyn.length;
|
||||
d = m_data_dyn[7];
|
||||
e = m_byte_data.length;
|
||||
f = m_byte_data[3].length;
|
||||
g = m_byte_data[3][1];
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("store(uint256[9],uint8[3][])", encodeArgs(21, 22, 23, 24, 25, 26, 27, 28, 29, u256(32 * (9 + 1)), 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 )), encodeArgs(32));
|
||||
ABI_CHECK(callContractFunction("retrieve()"), encodeArgs(9, 28, 9, 28, 4, 3, 32));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_copy_including_array)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract c {
|
||||
uint[3][90][] large;
|
||||
uint[3][3][] small;
|
||||
function test() public returns (uint r) {
|
||||
for (uint i = 0; i < 7; i++) {
|
||||
large.push();
|
||||
small.push();
|
||||
}
|
||||
large[3][2][0] = 2;
|
||||
large[1] = large[3];
|
||||
small[3][2][0] = 2;
|
||||
small[1] = small[2];
|
||||
r = ((
|
||||
small[3][2][0] * 0x100 |
|
||||
small[1][2][0]) * 0x100 |
|
||||
large[3][2][0]) * 0x100 |
|
||||
large[1][2][0];
|
||||
delete small;
|
||||
delete large;
|
||||
|
||||
}
|
||||
function clear() public returns (uint, uint) {
|
||||
for (uint i = 0; i < 7; i++) {
|
||||
large.push();
|
||||
small.push();
|
||||
}
|
||||
small[3][2][0] = 0;
|
||||
large[3][2][0] = 0;
|
||||
while (small.length > 0)
|
||||
small.pop();
|
||||
while (large.length > 0)
|
||||
large.pop();
|
||||
return (small.length, large.length);
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("test()"), encodeArgs(0x02000202));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
ABI_CHECK(callContractFunction("clear()"), encodeArgs(0, 0));
|
||||
BOOST_CHECK(storageEmpty(m_contractAddress));
|
||||
}
|
||||
|
||||
//BOOST_AUTO_TEST_CASE(assignment_to_const_array_vars)
|
||||
//{
|
||||
// char const* sourceCode = R"(
|
||||
@@ -3684,159 +3072,6 @@ BOOST_AUTO_TEST_CASE(return_bytes_internal)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bytes_index_access_memory)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Main {
|
||||
function f(bytes memory _s1, uint i1, uint i2, uint i3) public returns (byte c1, byte c2, byte c3) {
|
||||
c1 = _s1[i1];
|
||||
c2 = intern(_s1, i2);
|
||||
c3 = internIndirect(_s1)[i3];
|
||||
}
|
||||
function intern(bytes memory _s1, uint i) public returns (byte c) {
|
||||
return _s1[i];
|
||||
}
|
||||
function internIndirect(bytes memory _s1) public returns (bytes memory) {
|
||||
return _s1;
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "Main");
|
||||
string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
|
||||
bytes dyn1 = encodeArgs(u256(s1.length()), s1);
|
||||
bytes args1 = encodeArgs(u256(0x80), u256(3), u256(4), u256(5)) + dyn1;
|
||||
BOOST_REQUIRE(
|
||||
callContractFunction("f(bytes,uint256,uint256,uint256)", asString(args1)) ==
|
||||
encodeArgs(string{s1[3]}, string{s1[4]}, string{s1[5]})
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bytes_in_constructors_unpacker)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Test {
|
||||
uint public m_x;
|
||||
bytes public m_s;
|
||||
constructor(uint x, bytes memory s) {
|
||||
m_x = x;
|
||||
m_s = s;
|
||||
}
|
||||
}
|
||||
)";
|
||||
string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
|
||||
bytes dyn1 = encodeArgs(u256(s1.length()), s1);
|
||||
u256 x = 7;
|
||||
bytes args1 = encodeArgs(x, u256(0x40)) + dyn1;
|
||||
compileAndRun(sourceCode, 0, "Test", args1);
|
||||
BOOST_REQUIRE(callContractFunction("m_x()") == encodeArgs(x));
|
||||
BOOST_REQUIRE(callContractFunction("m_s()") == encodeArgs(u256(0x20)) + dyn1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bytes_in_constructors_packer)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Base {
|
||||
uint public m_x;
|
||||
bytes m_s;
|
||||
constructor(uint x, bytes memory s) {
|
||||
m_x = x;
|
||||
m_s = s;
|
||||
}
|
||||
function part(uint i) public returns (byte) {
|
||||
return m_s[i];
|
||||
}
|
||||
}
|
||||
contract Main is Base {
|
||||
constructor(bytes memory s, uint x) Base(x, f(s)) {}
|
||||
function f(bytes memory s) public returns (bytes memory) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
contract Creator {
|
||||
function f(uint x, bytes memory s) public returns (uint r, byte ch) {
|
||||
Main c = new Main(s, x);
|
||||
r = c.m_x();
|
||||
ch = c.part(x);
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "Creator");
|
||||
string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
|
||||
bytes dyn1 = encodeArgs(u256(s1.length()), s1);
|
||||
u256 x = 7;
|
||||
bytes args1 = encodeArgs(x, u256(0x40)) + dyn1;
|
||||
BOOST_REQUIRE(
|
||||
callContractFunction("f(uint256,bytes)", asString(args1)) ==
|
||||
encodeArgs(x, string{s1[unsigned(x)]})
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(arrays_in_constructors)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Base {
|
||||
uint public m_x;
|
||||
address[] m_s;
|
||||
constructor(uint x, address[] memory s) {
|
||||
m_x = x;
|
||||
m_s = s;
|
||||
}
|
||||
function part(uint i) public returns (address) {
|
||||
return m_s[i];
|
||||
}
|
||||
}
|
||||
contract Main is Base {
|
||||
constructor(address[] memory s, uint x) Base(x, f(s)) {}
|
||||
function f(address[] memory s) public returns (address[] memory) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
contract Creator {
|
||||
function f(uint x, address[] memory s) public returns (uint r, address ch) {
|
||||
Main c = new Main(s, x);
|
||||
r = c.m_x();
|
||||
ch = c.part(x);
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "Creator");
|
||||
vector<u256> s1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
bytes dyn1 = encodeArgs(u256(s1.size()), s1);
|
||||
u256 x = 7;
|
||||
bytes args1 = encodeArgs(x, u256(0x40)) + dyn1;
|
||||
BOOST_REQUIRE(
|
||||
callContractFunction("f(uint256,address[])", asString(args1)) ==
|
||||
encodeArgs(x, s1[unsigned(x)])
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(arrays_from_and_to_storage)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Test {
|
||||
uint24[] public data;
|
||||
function set(uint24[] memory _data) public returns (uint) {
|
||||
data = _data;
|
||||
return data.length;
|
||||
}
|
||||
function get() public returns (uint24[] memory) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "Test");
|
||||
|
||||
vector<u256> data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
|
||||
BOOST_REQUIRE(
|
||||
callContractFunction("set(uint24[])", u256(0x20), u256(data.size()), data) ==
|
||||
encodeArgs(u256(data.size()))
|
||||
);
|
||||
ABI_CHECK(callContractFunction("data(uint256)", u256(7)), encodeArgs(u256(8)));
|
||||
ABI_CHECK(callContractFunction("data(uint256)", u256(15)), encodeArgs(u256(16)));
|
||||
ABI_CHECK(callContractFunction("data(uint256)", u256(18)), encodeArgs());
|
||||
ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0x20), u256(data.size()), data));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(memory_types_initialisation)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
@@ -3859,35 +3094,6 @@ BOOST_AUTO_TEST_CASE(memory_types_initialisation)
|
||||
ABI_CHECK(callContractFunction("nestedStat()"), encodeArgs(vector<u256>(3 * 7)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(memory_arrays_delete)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Test {
|
||||
function del() public returns (uint24[3][4] memory) {
|
||||
uint24[3][4] memory x;
|
||||
for (uint24 i = 0; i < x.length; i ++)
|
||||
for (uint24 j = 0; j < x[i].length; j ++)
|
||||
x[i][j] = i * 0x10 + j;
|
||||
delete x[1];
|
||||
delete x[3][2];
|
||||
return x;
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "Test");
|
||||
|
||||
vector<u256> data(3 * 4);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
for (unsigned j = 0; j < 3; j++)
|
||||
{
|
||||
u256 v = 0;
|
||||
if (!(i == 1 || (i == 3 && j == 2)))
|
||||
v = i * 0x10 + j;
|
||||
data[i * 3 + j] = v;
|
||||
}
|
||||
ABI_CHECK(callContractFunction("del()"), encodeArgs(data));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(calldata_struct_short)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
@@ -3936,84 +3142,6 @@ BOOST_AUTO_TEST_CASE(calldata_struct_function_type)
|
||||
ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_h), encodeArgs(23));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(calldata_bytes_array_bounds)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
function f(bytes[] calldata a, uint256 i) external returns (uint) {
|
||||
return uint8(a[0][i]);
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes[],uint256)", 0x40, 0, 1, 0x20, 2, bytes{'a', 'b'} + bytes(30, 0)),
|
||||
encodeArgs('a')
|
||||
);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes[],uint256)", 0x40, 1, 1, 0x20, 2, bytes{'a', 'b'} + bytes(30, 0)),
|
||||
encodeArgs('b')
|
||||
);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes[],uint256)", 0x40, 2, 1, 0x20, 2, bytes{'a', 'b'} + bytes(30, 0)),
|
||||
panicData(PanicCode::ArrayOutOfBounds)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(calldata_array_two_dimensional)
|
||||
{
|
||||
vector<vector<u256>> data {
|
||||
{ 0x0A01, 0x0A02, 0x0A03 },
|
||||
{ 0x0B01, 0x0B02, 0x0B03, 0x0B04 }
|
||||
};
|
||||
|
||||
for (bool outerDynamicallySized: { true, false })
|
||||
{
|
||||
string arrayType = outerDynamicallySized ? "uint256[][]" : "uint256[][2]";
|
||||
string sourceCode = R"(
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
function test()" + arrayType + R"( calldata a) external returns (uint256) {
|
||||
return a.length;
|
||||
}
|
||||
function test()" + arrayType + R"( calldata a, uint256 i) external returns (uint256) {
|
||||
return a[i].length;
|
||||
}
|
||||
function test()" + arrayType + R"( calldata a, uint256 i, uint256 j) external returns (uint256) {
|
||||
return a[i][j];
|
||||
}
|
||||
function reenc()" + arrayType + R"( calldata a, uint256 i, uint256 j) external returns (uint256) {
|
||||
return this.test(a, i, j);
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
|
||||
bytes encoding = encodeArray(
|
||||
outerDynamicallySized,
|
||||
true,
|
||||
data | boost::adaptors::transformed([&](vector<u256> const& _values) {
|
||||
return encodeArray(true, false, _values);
|
||||
})
|
||||
);
|
||||
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ")", 0x20, encoding), encodeArgs(data.size()));
|
||||
for (size_t i = 0; i < data.size(); i++)
|
||||
{
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, i, encoding), encodeArgs(data[i].size()));
|
||||
for (size_t j = 0; j < data[i].size(); j++)
|
||||
{
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, j, encoding), encodeArgs(data[i][j]));
|
||||
ABI_CHECK(callContractFunction("reenc(" + arrayType + ",uint256,uint256)", 0x60, i, j, encoding), encodeArgs(data[i][j]));
|
||||
}
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, data[i].size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
|
||||
}
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, data.size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(calldata_array_dynamic_three_dimensional)
|
||||
{
|
||||
vector<vector<vector<u256>>> data {
|
||||
@@ -6591,59 +5719,6 @@ BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(try_catch_library_call)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
library L {
|
||||
struct S { uint x; }
|
||||
function integer(uint t, bool b) public view returns (uint) {
|
||||
if (b) {
|
||||
return t;
|
||||
} else {
|
||||
revert("failure");
|
||||
}
|
||||
}
|
||||
function stru(S storage t, bool b) public view returns (uint) {
|
||||
if (b) {
|
||||
return t.x;
|
||||
} else {
|
||||
revert("failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
contract C {
|
||||
using L for L.S;
|
||||
L.S t;
|
||||
function f(bool b) public returns (uint, string memory) {
|
||||
uint x = 8;
|
||||
try L.integer(x, b) returns (uint _x) {
|
||||
return (_x, "");
|
||||
} catch Error(string memory message) {
|
||||
return (18, message);
|
||||
}
|
||||
}
|
||||
function g(bool b) public returns (uint, string memory) {
|
||||
t.x = 9;
|
||||
try t.stru(b) returns (uint x) {
|
||||
return (x, "");
|
||||
} catch Error(string memory message) {
|
||||
return (19, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
if (solidity::test::CommonOptions::get().evmVersion().supportsReturndata())
|
||||
{
|
||||
compileAndRun(sourceCode, 0, "L", bytes());
|
||||
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}});
|
||||
|
||||
ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(8, 0x40, 0));
|
||||
ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(18, 0x40, 7, "failure"));
|
||||
ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(9, 0x40, 0));
|
||||
ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs(19, 0x40, 7, "failure"));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(strip_reason_strings)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
|
||||
@@ -1748,6 +1748,7 @@ BOOST_AUTO_TEST_CASE(user_explicit_inherit_partial2)
|
||||
checkNatspec(sourceCode, "ERC20", natspec, true);
|
||||
checkNatspec(sourceCode, "Token", natspec2, true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dev_explicit_inherit_partial)
|
||||
{
|
||||
char const *sourceCode = R"(
|
||||
@@ -2022,6 +2023,230 @@ BOOST_AUTO_TEST_CASE(dev_explicit_inehrit_complex)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dev_different_return_name)
|
||||
{
|
||||
char const *sourceCode = R"(
|
||||
contract A {
|
||||
/// @return y value
|
||||
function g(int x) public pure virtual returns (int y) { return x; }
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
function g(int x) public pure override returns (int z) { return x; }
|
||||
}
|
||||
)";
|
||||
|
||||
char const *natspec = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"y": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
char const *natspec2 = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"z": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
checkNatspec(sourceCode, "A", natspec, false);
|
||||
checkNatspec(sourceCode, "B", natspec2, false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dev_different_return_name_multiple)
|
||||
{
|
||||
char const *sourceCode = R"(
|
||||
contract A {
|
||||
/// @return a value A
|
||||
/// @return b value B
|
||||
function g(int x) public pure virtual returns (int a, int b) { return (1, 2); }
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
function g(int x) public pure override returns (int z, int y) { return (1, 2); }
|
||||
}
|
||||
)";
|
||||
|
||||
char const *natspec = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"a": "value A",
|
||||
"b": "value B"
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
char const *natspec2 = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"z": "value A",
|
||||
"y": "value B"
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
checkNatspec(sourceCode, "A", natspec, false);
|
||||
checkNatspec(sourceCode, "B", natspec2, false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dev_different_return_name_multiple_partly_unnamed)
|
||||
{
|
||||
char const *sourceCode = R"(
|
||||
contract A {
|
||||
/// @return value A
|
||||
/// @return b value B
|
||||
function g(int x) public pure virtual returns (int, int b) { return (1, 2); }
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
function g(int x) public pure override returns (int z, int) { return (1, 2); }
|
||||
}
|
||||
)";
|
||||
|
||||
char const *natspec = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"_0": "value A",
|
||||
"b": "value B"
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
char const *natspec2 = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"z": "value A",
|
||||
"_1": "value B"
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
checkNatspec(sourceCode, "A", natspec, false);
|
||||
checkNatspec(sourceCode, "B", natspec2, false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dev_different_return_name_multiple_unnamed)
|
||||
{
|
||||
char const *sourceCode = R"(
|
||||
contract A {
|
||||
/// @return value A
|
||||
/// @return value B
|
||||
function g(int x) public pure virtual returns (int, int) { return (1, 2); }
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
function g(int x) public pure override returns (int z, int y) { return (1, 2); }
|
||||
}
|
||||
)";
|
||||
|
||||
char const *natspec = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"_0": "value A",
|
||||
"_1": "value B"
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
char const *natspec2 = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"z": "value A",
|
||||
"y": "value B"
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
checkNatspec(sourceCode, "A", natspec, false);
|
||||
checkNatspec(sourceCode, "B", natspec2, false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dev_return_name_no_description)
|
||||
{
|
||||
char const *sourceCode = R"(
|
||||
contract A {
|
||||
/// @return a
|
||||
function g(int x) public pure virtual returns (int a) { return 2; }
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
function g(int x) public pure override returns (int b) { return 2; }
|
||||
}
|
||||
)";
|
||||
|
||||
char const *natspec = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"a": "a",
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
char const *natspec2 = R"ABCDEF({
|
||||
"methods":
|
||||
{
|
||||
"g(int256)":
|
||||
{
|
||||
"returns":
|
||||
{
|
||||
"b": "a",
|
||||
}
|
||||
}
|
||||
}
|
||||
})ABCDEF";
|
||||
|
||||
checkNatspec(sourceCode, "A", natspec, false);
|
||||
checkNatspec(sourceCode, "B", natspec2, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -86,6 +86,48 @@ Json::Value getContractResult(Json::Value const& _compilerResult, string const&
|
||||
return _compilerResult["contracts"][_file][_name];
|
||||
}
|
||||
|
||||
void checkLinkReferencesSchema(Json::Value const& _contractResult)
|
||||
{
|
||||
BOOST_TEST_REQUIRE(_contractResult.isObject());
|
||||
BOOST_TEST_REQUIRE(_contractResult["evm"]["bytecode"].isObject());
|
||||
|
||||
Json::Value const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"];
|
||||
BOOST_TEST_REQUIRE(linkReferenceResult.isObject());
|
||||
|
||||
for (string const& fileName: linkReferenceResult.getMemberNames())
|
||||
{
|
||||
BOOST_TEST_REQUIRE(linkReferenceResult[fileName].isObject());
|
||||
for (string const& libraryName: linkReferenceResult[fileName].getMemberNames())
|
||||
{
|
||||
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName].isArray());
|
||||
BOOST_TEST_REQUIRE(!linkReferenceResult[fileName][libraryName].empty());
|
||||
for (int i = 0; i < static_cast<int>(linkReferenceResult.size()); ++i)
|
||||
{
|
||||
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i].isObject());
|
||||
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i].size() == 2);
|
||||
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i]["length"].isUInt());
|
||||
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i]["start"].isUInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void expectLinkReferences(Json::Value const& _contractResult, map<string, set<string>> const& _expectedLinkReferences)
|
||||
{
|
||||
checkLinkReferencesSchema(_contractResult);
|
||||
|
||||
Json::Value const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"];
|
||||
BOOST_TEST(linkReferenceResult.size() == _expectedLinkReferences.size());
|
||||
|
||||
for (auto const& [fileName, libraries]: _expectedLinkReferences)
|
||||
{
|
||||
BOOST_TEST(linkReferenceResult.isMember(fileName));
|
||||
BOOST_TEST(linkReferenceResult[fileName].size() == libraries.size());
|
||||
for (string const& libraryName: libraries)
|
||||
BOOST_TEST(linkReferenceResult[fileName].isMember(libraryName));
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value compile(string _input)
|
||||
{
|
||||
StandardCompiler compiler;
|
||||
@@ -710,11 +752,7 @@ BOOST_AUTO_TEST_CASE(library_filename_with_colon)
|
||||
BOOST_CHECK(containsAtMostWarnings(result));
|
||||
Json::Value contract = getContractResult(result, "fileA", "A");
|
||||
BOOST_CHECK(contract.isObject());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"].isObject());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"].isObject());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["git:library.sol"].isObject());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["git:library.sol"]["L"].isArray());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["git:library.sol"]["L"][0].isObject());
|
||||
expectLinkReferences(contract, {{"git:library.sol", {"L"}}});
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(libraries_invalid_top_level)
|
||||
@@ -860,15 +898,137 @@ BOOST_AUTO_TEST_CASE(library_linking)
|
||||
}
|
||||
)";
|
||||
Json::Value result = compile(input);
|
||||
BOOST_CHECK(containsAtMostWarnings(result));
|
||||
Json::Value contract = getContractResult(result, "fileA", "A");
|
||||
BOOST_CHECK(contract.isObject());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"].isObject());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"].isObject());
|
||||
BOOST_CHECK(!contract["evm"]["bytecode"]["linkReferences"]["library.sol"].isObject());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"].isObject());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"]["L2"].isArray());
|
||||
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"]["L2"][0].isObject());
|
||||
BOOST_TEST(containsAtMostWarnings(result));
|
||||
Json::Value contractResult = getContractResult(result, "fileA", "A");
|
||||
expectLinkReferences(contractResult, {{"library2.sol", {"L2"}}});
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(linking_yul)
|
||||
{
|
||||
char const* input = R"(
|
||||
{
|
||||
"language": "Yul",
|
||||
"settings": {
|
||||
"libraries": {
|
||||
"fileB": {
|
||||
"L": "0x4200000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
"outputSelection": {
|
||||
"fileA": {
|
||||
"*": [
|
||||
"evm.bytecode.linkReferences"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources": {
|
||||
"fileA": {
|
||||
"content": "object \"a\" { code { let addr := linkersymbol(\"fileB:L\") } }"
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
Json::Value result = compile(input);
|
||||
BOOST_TEST(containsAtMostWarnings(result));
|
||||
Json::Value contractResult = getContractResult(result, "fileA", "a");
|
||||
expectLinkReferences(contractResult, {});
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(linking_yul_empty_link_reference)
|
||||
{
|
||||
char const* input = R"(
|
||||
{
|
||||
"language": "Yul",
|
||||
"settings": {
|
||||
"libraries": {
|
||||
"": {
|
||||
"": "0x4200000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
"outputSelection": {
|
||||
"fileA": {
|
||||
"*": [
|
||||
"evm.bytecode.linkReferences"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources": {
|
||||
"fileA": {
|
||||
"content": "object \"a\" { code { let addr := linkersymbol(\"\") } }"
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
Json::Value result = compile(input);
|
||||
BOOST_TEST(containsAtMostWarnings(result));
|
||||
Json::Value contractResult = getContractResult(result, "fileA", "a");
|
||||
expectLinkReferences(contractResult, {{"", {""}}});
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(linking_yul_no_filename_in_link_reference)
|
||||
{
|
||||
char const* input = R"(
|
||||
{
|
||||
"language": "Yul",
|
||||
"settings": {
|
||||
"libraries": {
|
||||
"": {
|
||||
"L": "0x4200000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
"outputSelection": {
|
||||
"fileA": {
|
||||
"*": [
|
||||
"evm.bytecode.linkReferences"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources": {
|
||||
"fileA": {
|
||||
"content": "object \"a\" { code { let addr := linkersymbol(\"L\") } }"
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
Json::Value result = compile(input);
|
||||
BOOST_TEST(containsAtMostWarnings(result));
|
||||
Json::Value contractResult = getContractResult(result, "fileA", "a");
|
||||
expectLinkReferences(contractResult, {{"", {"L"}}});
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(linking_yul_same_library_name_different_files)
|
||||
{
|
||||
char const* input = R"(
|
||||
{
|
||||
"language": "Yul",
|
||||
"settings": {
|
||||
"libraries": {
|
||||
"fileB": {
|
||||
"L": "0x4200000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
"outputSelection": {
|
||||
"fileA": {
|
||||
"*": [
|
||||
"evm.bytecode.linkReferences"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources": {
|
||||
"fileA": {
|
||||
"content": "object \"a\" { code { let addr := linkersymbol(\"fileC:L\") } }"
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
Json::Value result = compile(input);
|
||||
BOOST_TEST(containsAtMostWarnings(result));
|
||||
Json::Value contractResult = getContractResult(result, "fileA", "a");
|
||||
expectLinkReferences(contractResult, {{"fileC", {"L"}}});
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(evm_version)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
function test(uint256[][2] calldata a) external returns (uint256) {
|
||||
return a.length;
|
||||
}
|
||||
function test(uint256[][2] calldata a, uint256 i) external returns (uint256) {
|
||||
return a[i].length;
|
||||
}
|
||||
function test(uint256[][2] calldata a, uint256 i, uint256 j) external returns (uint256) {
|
||||
return a[i][j];
|
||||
}
|
||||
function reenc(uint256[][2] calldata a, uint256 i, uint256 j) external returns (uint256) {
|
||||
return this.test(a, i, j);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test(uint256[][2]): 0x20, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 2
|
||||
// test(uint256[][2],uint256): 0x40, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 3
|
||||
// test(uint256[][2],uint256): 0x40, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 4
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 0, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A01
|
||||
// reenc(uint256[][2],uint256,uint256): 0x60, 0, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A01
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 0, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A02
|
||||
// reenc(uint256[][2],uint256,uint256): 0x60, 0, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A02
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A03
|
||||
// reenc(uint256[][2],uint256,uint256): 0x60, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A03
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 1, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B01
|
||||
// reenc(uint256[][2],uint256,uint256): 0x60, 1, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B01
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 1, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B02
|
||||
// reenc(uint256[][2],uint256,uint256): 0x60, 1, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B02
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B03
|
||||
// reenc(uint256[][2],uint256,uint256): 0x60, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B03
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 1, 3, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B04
|
||||
// reenc(uint256[][2],uint256,uint256): 0x60, 1, 3, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B04
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 0, 3, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE
|
||||
// test(uint256[][2],uint256,uint256): 0x60, 1, 4, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE
|
||||
// test(uint256[][2],uint256): 0x40, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE
|
||||
@@ -0,0 +1,38 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
function test(uint256[][] calldata a) external returns (uint256) {
|
||||
return a.length;
|
||||
}
|
||||
function test(uint256[][] calldata a, uint256 i) external returns (uint256) {
|
||||
return a[i].length;
|
||||
}
|
||||
function test(uint256[][] calldata a, uint256 i, uint256 j) external returns (uint256) {
|
||||
return a[i][j];
|
||||
}
|
||||
function reenc(uint256[][] calldata a, uint256 i, uint256 j) external returns (uint256) {
|
||||
return this.test(a, i, j);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test(uint256[][]): 0x20, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 2
|
||||
// test(uint256[][],uint256): 0x40, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 3
|
||||
// test(uint256[][],uint256): 0x40, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 4
|
||||
// test(uint256[][],uint256,uint256): 0x60, 0, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A01
|
||||
// reenc(uint256[][],uint256,uint256): 0x60, 0, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A01
|
||||
// test(uint256[][],uint256,uint256): 0x60, 0, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A02
|
||||
// reenc(uint256[][],uint256,uint256): 0x60, 0, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A02
|
||||
// test(uint256[][],uint256,uint256): 0x60, 0, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A03
|
||||
// reenc(uint256[][],uint256,uint256): 0x60, 0, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A03
|
||||
// test(uint256[][],uint256,uint256): 0x60, 1, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B01
|
||||
// reenc(uint256[][],uint256,uint256): 0x60, 1, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B01
|
||||
// test(uint256[][],uint256,uint256): 0x60, 1, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B02
|
||||
// reenc(uint256[][],uint256,uint256): 0x60, 1, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B02
|
||||
// test(uint256[][],uint256,uint256): 0x60, 1, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B03
|
||||
// reenc(uint256[][],uint256,uint256): 0x60, 1, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B03
|
||||
// test(uint256[][],uint256,uint256): 0x60, 1, 3, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B04
|
||||
// reenc(uint256[][],uint256,uint256): 0x60, 1, 3, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B04
|
||||
// test(uint256[][],uint256,uint256): 0x60, 0, 3, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE
|
||||
// test(uint256[][],uint256,uint256): 0x60, 1, 4, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE
|
||||
// test(uint256[][],uint256): 0x40, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE
|
||||
@@ -0,0 +1,12 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
function f(bytes[] calldata a, uint256 i) external returns (uint) {
|
||||
return uint8(a[0][i]);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(bytes[],uint256): 0x40, 0, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> 0x61
|
||||
// f(bytes[],uint256): 0x40, 1, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> 0x62
|
||||
// f(bytes[],uint256): 0x40, 2, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> FAILURE
|
||||
@@ -0,0 +1,25 @@
|
||||
contract c {
|
||||
uint[9] m_data;
|
||||
uint[] m_data_dyn;
|
||||
uint8[][] m_byte_data;
|
||||
function store(uint[9] calldata a, uint8[3][] calldata b) external returns (uint8) {
|
||||
m_data = a;
|
||||
m_data_dyn = a;
|
||||
m_byte_data = b;
|
||||
return b[3][1]; // note that access and declaration are reversed to each other
|
||||
}
|
||||
function retrieve() public returns (uint a, uint b, uint c, uint d, uint e, uint f, uint g) {
|
||||
a = m_data.length;
|
||||
b = m_data[7];
|
||||
c = m_data_dyn.length;
|
||||
d = m_data_dyn[7];
|
||||
e = m_byte_data.length;
|
||||
f = m_byte_data[3].length;
|
||||
g = m_byte_data[3][1];
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// store(uint256[9],uint8[3][]): 21, 22, 23, 24, 25, 26, 27, 28, 29, 0x140, 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 -> 32
|
||||
// retrieve() -> 9, 28, 9, 28, 4, 3, 32
|
||||
@@ -0,0 +1,42 @@
|
||||
contract c {
|
||||
uint[3][90][] large;
|
||||
uint[3][3][] small;
|
||||
function test() public returns (uint r) {
|
||||
for (uint i = 0; i < 7; i++) {
|
||||
large.push();
|
||||
small.push();
|
||||
}
|
||||
large[3][2][0] = 2;
|
||||
large[1] = large[3];
|
||||
small[3][2][0] = 2;
|
||||
small[1] = small[2];
|
||||
r = ((
|
||||
small[3][2][0] * 0x100 |
|
||||
small[1][2][0]) * 0x100 |
|
||||
large[3][2][0]) * 0x100 |
|
||||
large[1][2][0];
|
||||
delete small;
|
||||
delete large;
|
||||
|
||||
}
|
||||
function clear() public returns (uint, uint) {
|
||||
for (uint i = 0; i < 7; i++) {
|
||||
large.push();
|
||||
small.push();
|
||||
}
|
||||
small[3][2][0] = 0;
|
||||
large[3][2][0] = 0;
|
||||
while (small.length > 0)
|
||||
small.pop();
|
||||
while (large.length > 0)
|
||||
large.pop();
|
||||
return (small.length, large.length);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 0x02000202
|
||||
// storage: empty
|
||||
// clear() -> 0, 0
|
||||
// storage: empty
|
||||
@@ -11,5 +11,7 @@ contract c {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test(uint256[2][]): 32, 3, 7, 8, 9, 10, 11, 12 -> 10
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
contract c {
|
||||
uint[] data1;
|
||||
uint[] data2;
|
||||
function setData1(uint length, uint index, uint value) public {
|
||||
data1 = new uint[](length);
|
||||
if (index < length)
|
||||
data1[index] = value;
|
||||
}
|
||||
function copyStorageStorage() public { data2 = data1; }
|
||||
function getData2(uint index) public returns (uint len, uint val) {
|
||||
len = data2.length; if (index < len) val = data2[index];
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// setData1(uint256,uint256,uint256): 10, 5, 4 ->
|
||||
// copyStorageStorage() ->
|
||||
// getData2(uint256): 5 -> 10, 4
|
||||
// setData1(uint256,uint256,uint256): 0, 0, 0 ->
|
||||
// copyStorageStorage() ->
|
||||
// getData2(uint256): 0 -> 0, 0
|
||||
// storage: empty
|
||||
+2
@@ -10,5 +10,7 @@ contract c {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 9, 4
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
contract c {
|
||||
struct Data { uint x; uint y; }
|
||||
Data[] data1;
|
||||
Data[] data2;
|
||||
function test() public returns (uint x, uint y) {
|
||||
while (data1.length < 9)
|
||||
data1.push();
|
||||
data1[8].x = 4;
|
||||
data1[8].y = 5;
|
||||
data2 = data1;
|
||||
x = data2[8].x;
|
||||
y = data2[8].y;
|
||||
while (data1.length > 0)
|
||||
data1.pop();
|
||||
data2 = data1;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 4, 5
|
||||
// storage: empty
|
||||
@@ -0,0 +1,19 @@
|
||||
contract c {
|
||||
byte[10] data1;
|
||||
bytes2[32] data2;
|
||||
function test() public returns (uint check, uint res1, uint res2) {
|
||||
uint i;
|
||||
for (i = 0; i < data2.length; ++i)
|
||||
data2[i] = 0xffff;
|
||||
check = uint(uint16(data2[31])) * 0x10000 | uint(uint16(data2[14]));
|
||||
for (i = 0; i < data1.length; ++i)
|
||||
data1[i] = byte(uint8(1 + i));
|
||||
data2 = data1;
|
||||
for (i = 0; i < 16; ++i)
|
||||
res1 |= uint(uint16(data2[i])) * 0x10000**i;
|
||||
for (i = 0; i < 16; ++i)
|
||||
res2 |= uint(uint16(data2[16 + i])) * 0x10000**i;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// test() -> 0xffffffff, 0x0000000000000000000000000a00090008000700060005000400030002000100, 0x0000000000000000000000000000000000000000000000000000000000000000
|
||||
@@ -0,0 +1,18 @@
|
||||
contract Test {
|
||||
uint24[] public data;
|
||||
function set(uint24[] memory _data) public returns (uint) {
|
||||
data = _data;
|
||||
return data.length;
|
||||
}
|
||||
function get() public returns (uint24[] memory) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// set(uint24[]): 0x20, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 -> 18
|
||||
// data(uint256): 7 -> 8
|
||||
// data(uint256): 15 -> 16
|
||||
// data(uint256): 18 -> FAILURE
|
||||
// get() -> 0x20, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18
|
||||
@@ -0,0 +1,17 @@
|
||||
contract c {
|
||||
function set(uint key) public returns (bool) { data[key] = msg.data; return true; }
|
||||
function copy(uint from, uint to) public returns (bool) { data[to] = data[from]; return true; }
|
||||
mapping(uint => bytes) data;
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// set(uint256): 1, 2 -> true
|
||||
// set(uint256): 2, 2, 3, 4, 5 -> true
|
||||
// storage: nonempty
|
||||
// copy(uint256,uint256): 1, 2 -> true
|
||||
// storage: nonempty
|
||||
// copy(uint256,uint256): 99, 1 -> true
|
||||
// storage: nonempty
|
||||
// copy(uint256,uint256): 99, 2 -> true
|
||||
// storage: empty
|
||||
@@ -14,5 +14,7 @@ contract C {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 7
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
contract c {
|
||||
function set() public returns (bool) { data1 = msg.data; return true; }
|
||||
function reset() public returns (bool) { data1 = data2; return true; }
|
||||
bytes data1;
|
||||
bytes data2;
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// set(): 1, 2, 3, 4, 5 -> true
|
||||
// storage: nonempty
|
||||
// reset() -> true
|
||||
// storage: empty
|
||||
@@ -0,0 +1,12 @@
|
||||
contract c {
|
||||
fallback() external { data = msg.data; }
|
||||
function del() public returns (bool) { delete data; return true; }
|
||||
bytes data;
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// (): 7 ->
|
||||
// storage: nonempty
|
||||
// del(): 7 -> true
|
||||
// storage: empty
|
||||
@@ -0,0 +1,15 @@
|
||||
contract Test {
|
||||
function del() public returns (uint24[3][4] memory) {
|
||||
uint24[3][4] memory x;
|
||||
for (uint24 i = 0; i < x.length; i ++)
|
||||
for (uint24 j = 0; j < x[i].length; j ++)
|
||||
x[i][j] = i * 0x10 + j;
|
||||
delete x[1];
|
||||
delete x[3][2];
|
||||
return x;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// del() -> 0, 1, 2, 0, 0, 0, 0x20, 0x21, 0x22, 0x30, 0x31, 0
|
||||
@@ -0,0 +1,23 @@
|
||||
contract c {
|
||||
uint[20] spacer;
|
||||
uint[] dynamic;
|
||||
function fill() public {
|
||||
for (uint i = 0; i < 21; ++i)
|
||||
dynamic.push(i + 1);
|
||||
}
|
||||
function halfClear() public {
|
||||
while (dynamic.length > 5)
|
||||
dynamic.pop();
|
||||
}
|
||||
function fullClear() public { delete dynamic; }
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// fill() ->
|
||||
// storage: nonempty
|
||||
// halfClear() ->
|
||||
// storage: nonempty
|
||||
// fullClear() ->
|
||||
// storage: empty
|
||||
@@ -0,0 +1,23 @@
|
||||
contract c {
|
||||
struct s { uint[][] d; }
|
||||
s[] data;
|
||||
function fill() public returns (uint) {
|
||||
while (data.length < 3)
|
||||
data.push();
|
||||
while (data[2].d.length < 4)
|
||||
data[2].d.push();
|
||||
while (data[2].d[3].length < 5)
|
||||
data[2].d[3].push();
|
||||
data[2].d[3][4] = 8;
|
||||
return data[2].d[3][4];
|
||||
}
|
||||
function clear() public { delete data; }
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// fill() -> 8
|
||||
// storage: nonempty
|
||||
// clear() ->
|
||||
// storage: empty
|
||||
@@ -0,0 +1,12 @@
|
||||
contract c {
|
||||
function test(uint[8] calldata a, uint[] calldata b, uint[5] calldata c, uint a_index, uint b_index, uint c_index)
|
||||
external returns (uint av, uint bv, uint cv) {
|
||||
av = a[a_index];
|
||||
bv = b[b_index];
|
||||
cv = c[c_index];
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256): 1, 2, 3, 4, 5, 6, 7, 8, 0x220, 21, 22, 23, 24, 25, 0, 1, 2, 3, 11, 12, 13 -> 1, 12, 23
|
||||
@@ -0,0 +1,17 @@
|
||||
contract c {
|
||||
uint spacer1;
|
||||
uint spacer2;
|
||||
uint[20] data;
|
||||
function fill() public {
|
||||
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
|
||||
}
|
||||
function clear() public { delete data; }
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// fill() ->
|
||||
// storage: nonempty
|
||||
// clear() ->
|
||||
// storage: empty
|
||||
@@ -0,0 +1,27 @@
|
||||
contract c {
|
||||
bytes data;
|
||||
function direct(bytes calldata arg, uint index) external returns (uint) {
|
||||
return uint(uint8(arg[index]));
|
||||
}
|
||||
function storageCopyRead(bytes calldata arg, uint index) external returns (uint) {
|
||||
data = arg;
|
||||
return uint(uint8(data[index]));
|
||||
}
|
||||
function storageWrite() external returns (uint) {
|
||||
data = new bytes(35);
|
||||
data[31] = 0x77;
|
||||
data[32] = 0x14;
|
||||
|
||||
data[31] = 0x01;
|
||||
data[31] |= 0x08;
|
||||
data[30] = 0x01;
|
||||
data[32] = 0x03;
|
||||
return uint(uint8(data[30])) * 0x100 | uint(uint8(data[31])) * 0x10 | uint(uint8(data[32]));
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// direct(bytes,uint256): 0x40, 33, 34, 0x000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F, left(0x2021) -> 0x21
|
||||
// storageCopyRead(bytes,uint256): 0x40, 33, 34, 0x000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F, left(0x2021) -> 0x21
|
||||
// storageWrite() -> 0x193
|
||||
@@ -0,0 +1,17 @@
|
||||
contract Main {
|
||||
function f(bytes memory _s1, uint i1, uint i2, uint i3) public returns (byte c1, byte c2, byte c3) {
|
||||
c1 = _s1[i1];
|
||||
c2 = intern(_s1, i2);
|
||||
c3 = internIndirect(_s1)[i3];
|
||||
}
|
||||
function intern(bytes memory _s1, uint i) public returns (byte c) {
|
||||
return _s1[i];
|
||||
}
|
||||
function internIndirect(bytes memory _s1) public returns (bytes memory) {
|
||||
return _s1;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(bytes,uint256,uint256,uint256): 0x80, 3, 4, 5, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> "d", "e", "f"
|
||||
@@ -0,0 +1,28 @@
|
||||
contract c {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
uint256 c;
|
||||
uint16[] inner = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
||||
uint16[][] data;
|
||||
function test() public returns (uint x, uint y, uint z) {
|
||||
for (uint i = 1; i <= 48; i++)
|
||||
data.push(inner);
|
||||
for (uint j = 1; j <= 10; j++)
|
||||
data.pop();
|
||||
x = data[data.length - 1][0];
|
||||
for (uint k = 1; k <= 10; k++)
|
||||
data.pop();
|
||||
y = data[data.length - 1][1];
|
||||
for (uint l = 1; l <= 10; l++)
|
||||
data.pop();
|
||||
z = data[data.length - 1][2];
|
||||
for (uint m = 1; m <= 18; m++)
|
||||
data.pop();
|
||||
delete inner;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 1, 2, 3
|
||||
// storage: empty
|
||||
@@ -0,0 +1,12 @@
|
||||
contract c {
|
||||
uint[] data;
|
||||
function test() public {
|
||||
data.push(7);
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() ->
|
||||
// storage: empty
|
||||
@@ -0,0 +1,23 @@
|
||||
contract c {
|
||||
uint16[] data;
|
||||
function test() public returns (uint16 x, uint16 y, uint16 z) {
|
||||
for (uint i = 1; i <= 48; i++)
|
||||
data.push(uint16(i));
|
||||
for (uint j = 1; j <= 10; j++)
|
||||
data.pop();
|
||||
x = data[data.length - 1];
|
||||
for (uint k = 1; k <= 10; k++)
|
||||
data.pop();
|
||||
y = data[data.length - 1];
|
||||
for (uint l = 1; l <= 10; l++)
|
||||
data.pop();
|
||||
z = data[data.length - 1];
|
||||
for (uint m = 1; m <= 18; m++)
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 38, 28, 18
|
||||
// storage: empty
|
||||
@@ -0,0 +1,23 @@
|
||||
contract c {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
uint256 c;
|
||||
uint24[] data;
|
||||
function test() public returns (uint24 x, uint24 y) {
|
||||
for (uint i = 1; i <= 30; i++)
|
||||
data.push(uint24(i));
|
||||
for (uint j = 1; j <= 10; j++)
|
||||
data.pop();
|
||||
x = data[data.length - 1];
|
||||
for (uint k = 1; k <= 10; k++)
|
||||
data.pop();
|
||||
y = data[data.length - 1];
|
||||
for (uint l = 1; l <= 10; l++)
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 20, 10
|
||||
// storage: empty
|
||||
@@ -0,0 +1,21 @@
|
||||
contract c {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
uint256 c;
|
||||
bytes data;
|
||||
function test() public returns (bool) {
|
||||
for (uint8 i = 0; i <= 40; i++)
|
||||
data.push(byte(i+1));
|
||||
for (int8 j = 40; j >= 0; j--) {
|
||||
require(data[uint8(j)] == byte(j+1));
|
||||
require(data.length == uint8(j+1));
|
||||
data.pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> true
|
||||
// storage: empty
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
contract c {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
bytes data;
|
||||
function test() public {
|
||||
for (uint8 i = 0; i <= 40; i++)
|
||||
data.push(0x03);
|
||||
for (uint8 j = 0; j <= 40; j++) {
|
||||
assembly {
|
||||
mstore(0, "garbage")
|
||||
}
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() ->
|
||||
// storage: empty
|
||||
@@ -0,0 +1,16 @@
|
||||
contract c {
|
||||
bytes data;
|
||||
function test() public {
|
||||
data.push(0x07);
|
||||
data.push(0x05);
|
||||
data.push(0x03);
|
||||
data.pop();
|
||||
data.pop();
|
||||
data.pop();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() ->
|
||||
// storage: empty
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user