Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth
2020-04-07 11:14:28 +02:00
288 changed files with 6927 additions and 2129 deletions
+2
View File
@@ -154,6 +154,7 @@ set(yul_phaser_sources
yulPhaser/Phaser.cpp
yulPhaser/Population.cpp
yulPhaser/Program.cpp
yulPhaser/ProgramCache.cpp
yulPhaser/Selections.cpp
yulPhaser/SimulationRNG.cpp
@@ -170,6 +171,7 @@ set(yul_phaser_sources
../tools/yulPhaser/Phaser.cpp
../tools/yulPhaser/Population.cpp
../tools/yulPhaser/Program.cpp
../tools/yulPhaser/ProgramCache.cpp
../tools/yulPhaser/Selections.cpp
../tools/yulPhaser/SimulationRNG.cpp
)
+1 -1
View File
@@ -187,7 +187,7 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
if (solidity::test::CommonOptions::get().disableSMT)
removeTestSuite("SMTChecker");
return 0;
return nullptr;
}
// BOOST_TEST_DYN_LINK should be defined if user want to link against shared boost test library
@@ -0,0 +1,18 @@
{
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A { uint256 immutable x = 1; function f() public view returns (uint256) { return x; } }"
}
},
"settings": {
"evmVersion": "petersburg",
"outputSelection": {
"*": {
"A": [
"evm.deployedBytecode.immutableReferences"
]
}
}
}
}
@@ -0,0 +1,2 @@
{"contracts":{"a.sol":{"A":{"evm":{"deployedBytecode":{"immutableReferences":{"3":[{"length":32,"start":77}]},"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"0:96:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;0:96:0;;;;;;;;;;;;;;;;12:1:-1;9;2:12;38:56:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;72:7;90:1;83:8;;38:56;:::o"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"}],"sources":{"a.sol":{"id":0}}}
@@ -20,6 +20,7 @@ object \"C_6\" {
function fun_f_5() {
}
}
@@ -69,6 +70,7 @@ object \"C_6\" {
function fun_f_5() {
}
function shift_right_224_unsigned(value) -> newValue {
@@ -35,11 +35,18 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4_mpos {
let zero_value_for_type_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr()
vloc__4_mpos := zero_value_for_type_t_string_memory_ptr_1_mpos
vloc__4_mpos := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr()
leave
}
function zero_value_for_split_t_string_memory_ptr() -> ret {
ret := 96
}
}
object \"C_10_deployed\" {
code {
@@ -131,6 +138,9 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4_mpos {
let zero_value_for_type_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr()
vloc__4_mpos := zero_value_for_type_t_string_memory_ptr_1_mpos
vloc__4_mpos := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr()
leave
@@ -147,6 +157,10 @@ object \"C_10\" {
}
function zero_value_for_split_t_string_memory_ptr() -> ret {
ret := 96
}
}
}
}
@@ -23,11 +23,18 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4 {
let zero_value_for_type_t_bytes32_1 := zero_value_for_split_t_bytes32()
vloc__4 := zero_value_for_type_t_bytes32_1
vloc__4 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32()
leave
}
function zero_value_for_split_t_bytes32() -> ret {
ret := 0
}
}
object \"C_10_deployed\" {
code {
@@ -88,6 +95,9 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4 {
let zero_value_for_type_t_bytes32_1 := zero_value_for_split_t_bytes32()
vloc__4 := zero_value_for_type_t_bytes32_1
vloc__4 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32()
leave
@@ -100,6 +110,10 @@ object \"C_10\" {
}
function zero_value_for_split_t_bytes32() -> ret {
ret := 0
}
}
}
}
@@ -27,6 +27,9 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4 {
let zero_value_for_type_t_bytes4_1 := zero_value_for_split_t_bytes4()
vloc__4 := zero_value_for_type_t_bytes4_1
let expr_6 := 0x61626364
vloc__4 := convert_t_rational_1633837924_by_1_to_t_bytes4(expr_6)
leave
@@ -40,6 +43,10 @@ object \"C_10\" {
}
function zero_value_for_split_t_bytes4() -> ret {
ret := 0
}
}
object \"C_10_deployed\" {
code {
@@ -104,6 +111,9 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4 {
let zero_value_for_type_t_bytes4_1 := zero_value_for_split_t_bytes4()
vloc__4 := zero_value_for_type_t_bytes4_1
let expr_6 := 0x61626364
vloc__4 := convert_t_rational_1633837924_by_1_to_t_bytes4(expr_6)
leave
@@ -124,6 +134,10 @@ object \"C_10\" {
}
function zero_value_for_split_t_bytes4() -> ret {
ret := 0
}
}
}
}
@@ -39,11 +39,18 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4_mpos {
let zero_value_for_type_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr()
vloc__4_mpos := zero_value_for_type_t_string_memory_ptr_1_mpos
vloc__4_mpos := convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr()
leave
}
function zero_value_for_split_t_string_memory_ptr() -> ret {
ret := 96
}
}
object \"C_10_deployed\" {
code {
@@ -139,6 +146,9 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4_mpos {
let zero_value_for_type_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr()
vloc__4_mpos := zero_value_for_type_t_string_memory_ptr_1_mpos
vloc__4_mpos := convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr()
leave
@@ -155,6 +165,10 @@ object \"C_10\" {
}
function zero_value_for_split_t_string_memory_ptr() -> ret {
ret := 96
}
}
}
}
@@ -27,6 +27,9 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4 {
let zero_value_for_type_t_bytes4_1 := zero_value_for_split_t_bytes4()
vloc__4 := zero_value_for_type_t_bytes4_1
let expr_6 := 0xaabbccdd
vloc__4 := convert_t_rational_2864434397_by_1_to_t_bytes4(expr_6)
leave
@@ -40,6 +43,10 @@ object \"C_10\" {
}
function zero_value_for_split_t_bytes4() -> ret {
ret := 0
}
}
object \"C_10_deployed\" {
code {
@@ -104,6 +111,9 @@ object \"C_10\" {
}
function fun_f_9() -> vloc__4 {
let zero_value_for_type_t_bytes4_1 := zero_value_for_split_t_bytes4()
vloc__4 := zero_value_for_type_t_bytes4_1
let expr_6 := 0xaabbccdd
vloc__4 := convert_t_rational_2864434397_by_1_to_t_bytes4(expr_6)
leave
@@ -124,6 +134,10 @@ object \"C_10\" {
}
function zero_value_for_split_t_bytes4() -> ret {
ret := 0
}
}
}
}
+113 -4
View File
@@ -61,6 +61,8 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
Assembly _subAsm;
auto sub_asm = make_shared<CharStream>("lorem ipsum", "sub.asm");
_subAsm.setSourceLocation({6, 8, sub_asm});
// PushImmutable
_subAsm.appendImmutable("someImmutable");
_subAsm.append(Instruction::INVALID);
shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm);
@@ -86,6 +88,11 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
_assembly.pushSubroutineOffset(size_t(sub.data()));
// PushDeployTimeAddress
_assembly.append(PushDeployTimeAddress);
// AssignImmutable.
// Note that since there is no reference to "someOtherImmutable", this will compile to a simple POP in the hex output.
_assembly.appendImmutableAssignment("someOtherImmutable");
_assembly.append(u256(2));
_assembly.appendImmutableAssignment("someImmutable");
// Operation
_assembly.append(Instruction::STOP);
_assembly.appendAuxiliaryDataToEnd(bytes{0x42, 0x66});
@@ -95,8 +102,11 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
BOOST_CHECK_EQUAL(
_assembly.assemble().toHex(),
"5b6001600220604673__$bf005014d9d0f534b8fcb268bd84c491a2$__"
"600056603e6001603d73000000000000000000000000000000000000000000fe"
"5b6001600220606f73__$bf005014d9d0f534b8fcb268bd84c491a2$__"
"60005660676022604573000000000000000000000000000000000000000050"
"60028060015250"
"00fe"
"7f0000000000000000000000000000000000000000000000000000000000000000"
"fe010203044266eeaa"
);
BOOST_CHECK_EQUAL(
@@ -111,12 +121,16 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
" dataSize(sub_0)\n"
" dataOffset(sub_0)\n"
" deployTimeAddress()\n"
" assignImmutable(\"0xc3978657661c4d8e32e3d5f42597c009f0d3859e9f9d0d94325268f9799e2bfb\")\n"
" 0x02\n"
" assignImmutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n"
" stop\n"
"stop\n"
"data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b 01020304\n"
"\n"
"sub_0: assembly {\n"
" /* \"sub.asm\":6:8 */\n"
" immutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n"
" invalid\n"
"}\n"
"\n"
@@ -138,9 +152,104 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
"{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
"{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
"{\"begin\":1,\"end\":3,\"name\":\"PUSHDEPLOYADDRESS\",\"source\":0},"
"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someOtherImmutable\"},"
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"2\"},"
"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someImmutable\"},"
"{\"begin\":1,\"end\":3,\"name\":\"STOP\",\"source\":0}"
"],\".data\":{\"0\":{\".code\":[{\"begin\":6,\"end\":8,\"name\":\"INVALID\",\"source\":1}]},"
"\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"}}"
"],\".data\":{\"0\":{\".code\":["
"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"},"
"{\"begin\":6,\"end\":8,\"name\":\"INVALID\",\"source\":1}"
"]},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"}}"
);
}
BOOST_AUTO_TEST_CASE(immutable)
{
map<string, unsigned> indices = {
{ "root.asm", 0 },
{ "sub.asm", 1 }
};
Assembly _assembly;
auto root_asm = make_shared<CharStream>("lorem ipsum", "root.asm");
_assembly.setSourceLocation({1, 3, root_asm});
Assembly _subAsm;
auto sub_asm = make_shared<CharStream>("lorem ipsum", "sub.asm");
_subAsm.setSourceLocation({6, 8, sub_asm});
_subAsm.appendImmutable("someImmutable");
_subAsm.appendImmutable("someOtherImmutable");
_subAsm.appendImmutable("someImmutable");
shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm);
_assembly.append(u256(42));
_assembly.appendImmutableAssignment("someImmutable");
_assembly.append(u256(23));
_assembly.appendImmutableAssignment("someOtherImmutable");
auto sub = _assembly.appendSubroutine(_subAsmPtr);
_assembly.pushSubroutineOffset(size_t(sub.data()));
checkCompilation(_assembly);
BOOST_CHECK_EQUAL(
_assembly.assemble().toHex(),
// root.asm
// assign "someImmutable"
"602a" // PUSH1 42 - value for someImmutable
"80" // DUP1
"6001" // PUSH1 1 - offset of first someImmutable in sub_0
"52" // MSTORE
"80" // DUP1
"6043" // PUSH1 67 - offset of second someImmutable in sub_0
"52" // MSTORE
"50" // POP
// assign "someOtherImmutable"
"6017" // PUSH1 23 - value for someOtherImmutable
"80" // DUP1
"6022" // PUSH1 34 - offset of someOtherImmutable in sub_0
"52" // MSTORE
"50" // POP
"6063" // PUSH1 0x63 - dataSize(sub_0)
"6017" // PUSH1 0x17 - dataOffset(sub_0)
"fe" // INVALID
// end of root.asm
// sub.asm
"7f0000000000000000000000000000000000000000000000000000000000000000" // PUSHIMMUTABLE someImmutable - data at offset 1
"7f0000000000000000000000000000000000000000000000000000000000000000" // PUSHIMMUTABLE someOtherImmutable - data at offset 34
"7f0000000000000000000000000000000000000000000000000000000000000000" // PUSHIMMUTABLE someImmutable - data at offset 67
);
BOOST_CHECK_EQUAL(
_assembly.assemblyString(),
" /* \"root.asm\":1:3 */\n"
" 0x2a\n"
" assignImmutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n"
" 0x17\n"
" assignImmutable(\"0xc3978657661c4d8e32e3d5f42597c009f0d3859e9f9d0d94325268f9799e2bfb\")\n"
" dataSize(sub_0)\n"
" dataOffset(sub_0)\n"
"stop\n"
"\n"
"sub_0: assembly {\n"
" /* \"sub.asm\":6:8 */\n"
" immutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n"
" immutable(\"0xc3978657661c4d8e32e3d5f42597c009f0d3859e9f9d0d94325268f9799e2bfb\")\n"
" immutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n"
"}\n"
);
BOOST_CHECK_EQUAL(
util::jsonCompactPrint(_assembly.assemblyJSON(indices)),
"{\".code\":["
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"2A\"},"
"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someImmutable\"},"
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"17\"},"
"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someOtherImmutable\"},"
"{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
"{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}"
"],\".data\":{\"0\":{\".code\":["
"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"},"
"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someOtherImmutable\"},"
"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"}"
"]}}}"
);
}
+100
View File
@@ -112,6 +112,44 @@ namespace
BOOST_AUTO_TEST_SUITE(Optimiser)
BOOST_AUTO_TEST_CASE(cse_push_immutable_same)
{
AssemblyItem pushImmutable{PushImmutable, 0x1234};
checkCSE({pushImmutable, pushImmutable}, {pushImmutable, Instruction::DUP1});
}
BOOST_AUTO_TEST_CASE(cse_push_immutable_different)
{
AssemblyItems input{{PushImmutable, 0x1234},{PushImmutable, 0xABCD}};
checkCSE(input, input);
}
BOOST_AUTO_TEST_CASE(cse_assign_immutable)
{
{
AssemblyItems input{u256(0x42), {AssignImmutable, 0x1234}};
checkCSE(input, input);
}
{
AssemblyItems input{{AssignImmutable, 0x1234}};
checkCSE(input, input);
}
}
BOOST_AUTO_TEST_CASE(cse_assign_immutable_breaks)
{
AssemblyItems input = addDummyLocations(AssemblyItems{
u256(0x42),
{AssignImmutable, 0x1234},
Instruction::ORIGIN
});
evmasm::CommonSubexpressionEliminator cse{evmasm::KnownState()};
// Make sure CSE breaks after AssignImmutable.
BOOST_REQUIRE(cse.feedItems(input.begin(), input.end(), false) == input.begin() + 2);
}
BOOST_AUTO_TEST_CASE(cse_intermediate_swap)
{
evmasm::KnownState state;
@@ -798,6 +836,68 @@ BOOST_AUTO_TEST_CASE(block_deduplicator)
BOOST_CHECK_EQUAL(pushTags.size(), 2);
}
BOOST_AUTO_TEST_CASE(block_deduplicator_assign_immutable_same)
{
AssemblyItems blocks{
AssemblyItem(Tag, 1),
u256(42),
AssemblyItem{AssignImmutable, 0x1234},
Instruction::JUMP,
AssemblyItem(Tag, 2),
u256(42),
AssemblyItem{AssignImmutable, 0x1234},
Instruction::JUMP
};
AssemblyItems input = AssemblyItems{
AssemblyItem(PushTag, 2),
AssemblyItem(PushTag, 1),
} + blocks;
AssemblyItems output = AssemblyItems{
AssemblyItem(PushTag, 1),
AssemblyItem(PushTag, 1),
} + blocks;
BlockDeduplicator dedup(input);
dedup.deduplicate();
BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
}
BOOST_AUTO_TEST_CASE(block_deduplicator_assign_immutable_different_value)
{
AssemblyItems input{
AssemblyItem(PushTag, 2),
AssemblyItem(PushTag, 1),
AssemblyItem(Tag, 1),
u256(42),
AssemblyItem{AssignImmutable, 0x1234},
Instruction::JUMP,
AssemblyItem(Tag, 2),
u256(23),
AssemblyItem{AssignImmutable, 0x1234},
Instruction::JUMP
};
BlockDeduplicator dedup(input);
BOOST_CHECK(!dedup.deduplicate());
}
BOOST_AUTO_TEST_CASE(block_deduplicator_assign_immutable_different_hash)
{
AssemblyItems input{
AssemblyItem(PushTag, 2),
AssemblyItem(PushTag, 1),
AssemblyItem(Tag, 1),
u256(42),
AssemblyItem{AssignImmutable, 0x1234},
Instruction::JUMP,
AssemblyItem(Tag, 2),
u256(42),
AssemblyItem{AssignImmutable, 0xABCD},
Instruction::JUMP
};
BlockDeduplicator dedup(input);
BOOST_CHECK(!dedup.deduplicate());
}
BOOST_AUTO_TEST_CASE(block_deduplicator_loops)
{
AssemblyItems input{
+2 -2
View File
@@ -34,14 +34,14 @@ namespace solidity::frontend::test
class SMTCheckerFramework: public AnalysisFramework
{
protected:
virtual std::pair<SourceUnit const*, ErrorList>
std::pair<SourceUnit const*, ErrorList>
parseAnalyseAndReturnError(
std::string const& _source,
bool _reportWarnings = false,
bool _insertVersionPragma = true,
bool _allowMultipleErrors = false,
bool _allowRecoveryErrors = false
)
) override
{
return AnalysisFramework::parseAnalyseAndReturnError(
"pragma experimental SMTChecker;\n" + _source,
File diff suppressed because it is too large Load Diff
@@ -46,7 +46,7 @@ public:
ExecutionFramework(_evmVersion), m_showMetadata(solidity::test::CommonOptions::get().showMetadata)
{}
virtual bytes const& compileAndRunWithoutCheck(
bytes const& compileAndRunWithoutCheck(
std::string const& _sourceCode,
u256 const& _value = 0,
std::string const& _contractName = "",
+10 -14
View File
@@ -52,15 +52,15 @@ public:
FirstExpressionExtractor(ASTNode& _node): m_expression(nullptr) { _node.accept(*this); }
Expression* expression() const { return m_expression; }
private:
virtual bool visit(Assignment& _expression) override { return checkExpression(_expression); }
virtual bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); }
virtual bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); }
virtual bool visit(FunctionCall& _expression) override { return checkExpression(_expression); }
virtual bool visit(MemberAccess& _expression) override { return checkExpression(_expression); }
virtual bool visit(IndexAccess& _expression) override { return checkExpression(_expression); }
virtual bool visit(Identifier& _expression) override { return checkExpression(_expression); }
virtual bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); }
virtual bool visit(Literal& _expression) override { return checkExpression(_expression); }
bool visit(Assignment& _expression) override { return checkExpression(_expression); }
bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); }
bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); }
bool visit(FunctionCall& _expression) override { return checkExpression(_expression); }
bool visit(MemberAccess& _expression) override { return checkExpression(_expression); }
bool visit(IndexAccess& _expression) override { return checkExpression(_expression); }
bool visit(Identifier& _expression) override { return checkExpression(_expression); }
bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); }
bool visit(Literal& _expression) override { return checkExpression(_expression); }
bool checkExpression(Expression& _expression)
{
if (m_expression == nullptr)
@@ -119,13 +119,9 @@ bytes compileFirstExpression(
NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), scopes, errorReporter);
resolver.registerDeclarations(*sourceUnit);
vector<ContractDefinition const*> inheritanceHierarchy;
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{
BOOST_REQUIRE_MESSAGE(resolver.resolveNamesAndTypes(*contract), "Resolving names failed");
inheritanceHierarchy = vector<ContractDefinition const*>(1, contract);
}
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{
@@ -144,7 +140,7 @@ bytes compileFirstExpression(
RevertStrings::Default
);
context.resetVisitedNodes(contract);
context.setInheritanceHierarchy(inheritanceHierarchy);
context.setMostDerivedContract(*contract);
unsigned parametersSize = _localVariables.size(); // assume they are all one slot on the stack
context.adjustStackOffset(parametersSize);
for (vector<string> const& variable: _localVariables)
+1 -1
View File
@@ -672,7 +672,7 @@ BOOST_AUTO_TEST_CASE(inline_asm_end_location)
{
public:
bool visited = false;
virtual bool visit(InlineAssembly const& _inlineAsm)
bool visit(InlineAssembly const& _inlineAsm) override
{
auto loc = _inlineAsm.location();
auto asmStr = loc.source->source().substr(loc.start, loc.end - loc.start);
@@ -0,0 +1,11 @@
contract C {
function f(bytes calldata data)
external
pure
returns (uint256, bytes memory r)
{
return abi.decode(data, (uint256, bytes));
}
}
// ----
// f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg"
@@ -0,0 +1,7 @@
contract C {
function f(bytes memory data) public pure returns (uint256, bytes memory) {
return abi.decode(data, (uint256, bytes));
}
}
// ----
// f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg"
@@ -0,0 +1,10 @@
contract C {
bytes data;
function f(bytes memory _data) public returns (uint256, bytes memory) {
data = _data;
return abi.decode(data, (uint256, bytes));
}
}
// ----
// f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg"
@@ -0,0 +1,11 @@
// Tests that this will not end up using a "bytes0" type
// (which would assert)
contract C {
function f() public pure returns (bytes memory, bytes memory) {
return (abi.encode(""), abi.encodePacked(""));
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f() -> 0x40, 0xc0, 0x60, 0x20, 0x0, 0x0, 0x0
@@ -0,0 +1,18 @@
contract Test {
uint24[3][] public data;
function set(uint24[3][] memory _data) public returns (uint256) {
data = _data;
return data.length;
}
function get() public returns (uint24[3][] memory) {
return data;
}
}
// ----
// set(uint24[3][]): 0x20, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12 -> 0x06
// data(uint256,uint256): 0x02, 0x02 -> 0x09
// data(uint256,uint256): 0x05, 0x01 -> 0x11
// data(uint256,uint256): 0x06, 0x00 -> FAILURE
// get() -> 0x20, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12
@@ -0,0 +1,13 @@
contract Test {
function set(uint24[3][] memory _data, uint256 a, uint256 b)
public
returns (uint256 l, uint256 e)
{
l = _data.length;
e = _data[a][b];
}
}
// ====
// compileViaYul: also
// ----
// set(uint24[3][],uint256,uint256): 0x60, 0x03, 0x02, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12 -> 0x06, 0x0c
@@ -0,0 +1,13 @@
contract Test {
function set(bytes memory _data, uint256 i)
public
returns (uint256 l, bytes1 c)
{
l = _data.length;
c = _data[i];
}
}
// ====
// compileViaYul: also
// ----
// set(bytes,uint256): 0x40, 0x03, 0x08, "abcdefgh" -> 0x08, "d"
@@ -0,0 +1,24 @@
contract C {
function f() public returns (uint256) {
uint256 l = 2**256 / 32;
// This used to work without causing an error.
uint256[] memory x = new uint256[](l);
uint256[] memory y = new uint256[](1);
x[1] = 42;
// This used to overwrite the value written above.
y[0] = 23;
return x[1];
}
function g() public returns (uint256) {
uint256 l = 2**256 / 2 + 1;
// This used to work without causing an error.
uint16[] memory x = new uint16[](l);
uint16[] memory y = new uint16[](1);
x[2] = 42;
// This used to overwrite the value written above.
y[0] = 23;
return x[2];
}}
// ----
// f() -> FAILURE
// g() -> FAILURE
@@ -0,0 +1,45 @@
contract c {
struct Data {
uint256 x;
uint256 y;
}
Data[2**10] data;
uint256[2**10 + 3] ids;
function setIDStatic(uint256 id) public {
ids[2] = id;
}
function setID(uint256 index, uint256 id) public {
ids[index] = id;
}
function setData(uint256 index, uint256 x, uint256 y) public {
data[index].x = x;
data[index].y = y;
}
function getID(uint256 index) public returns (uint256) {
return ids[index];
}
function getData(uint256 index) public returns (uint256 x, uint256 y) {
x = data[index].x;
y = data[index].y;
}
function getLengths() public returns (uint256 l1, uint256 l2) {
l1 = data.length;
l2 = ids.length;
}
}
// ----
// setIDStatic(uint256): 0xb ->
// getID(uint256): 0x2 -> 0xb
// setID(uint256,uint256): 0x7, 0x8 ->
// getID(uint256): 0x7 -> 0x8
// setData(uint256,uint256,uint256): 0x7, 0x8, 0x9 ->
// setData(uint256,uint256,uint256): 0x8, 0xa, 0xb ->
// getData(uint256): 0x7 -> 0x8, 0x9
// getData(uint256): 0x8 -> 0xa, 0xb
// getLengths() -> 0x400, 0x403
@@ -0,0 +1,17 @@
contract C {
bytes16[] public data;
function f(bytes32 x) public returns (bytes1) {
return x[2];
}
function g(bytes32 x) public returns (uint256) {
data = [x[0], x[1], x[2]];
data[0] = "12345";
return uint256(uint8(data[0][4]));
}
}
// ----
// f(bytes32): "789" -> "9"
// g(bytes32): "789" -> 0x35
// data(uint256): 0x01 -> "8"
@@ -0,0 +1,19 @@
contract Test {
uint24[3][][4] data;
function set(uint24[3][][4] memory x)
internal
returns (uint24[3][][4] memory)
{
x[1][2][2] = 1;
x[1][3][2] = 7;
return x;
}
function f() public returns (uint24[3][] memory) {
while (data[1].length < 4) data[1].push();
return set(data)[1];
}
}
// ----
// f() -> 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07
@@ -0,0 +1,14 @@
contract Test {
function set(uint24[3][4] memory x) public {
x[2][2] = 1;
x[3][2] = 7;
}
function f() public returns (uint24[3][4] memory) {
uint24[3][4] memory data;
set(data);
return data;
}
}
// ----
// f() -> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07
@@ -0,0 +1,26 @@
// Invoke some features that use memory and test that they do not interfere with each other.
contract Helper {
uint256 public flag;
constructor(uint256 x) public {
flag = x;
}
}
contract Main {
mapping(uint256 => uint256) map;
function f(uint256 x) public returns (uint256) {
map[x] = x;
return
(new Helper(uint256(keccak256(abi.encodePacked(this.g(map[x]))))))
.flag();
}
function g(uint256 a) public returns (uint256) {
return map[a];
}
}
// ----
// f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1
@@ -0,0 +1,20 @@
contract Sample {
struct s {
uint16 x;
uint16 y;
string a;
string b;
}
s[2] public p;
constructor() public {
s memory m;
m.x = 0xbbbb;
m.y = 0xcccc;
m.a = "hello";
m.b = "world";
p[0] = m;
}
}
// ----
// p(uint256): 0x0 -> 0xbbbb, 0xcccc, 0x80, 0xc0, 0x05, "hello", 0x05, "world"
@@ -0,0 +1,17 @@
contract Test {
string s;
bytes b;
function f(string memory _s, uint256 n) public returns (bytes1) {
b = bytes(_s);
s = string(b);
return bytes(s)[n];
}
function l() public returns (uint256) {
return bytes(s).length;
}
}
// ----
// f(string,uint256): 0x40, 0x02, 0x06, "abcdef" -> "c"
// l() -> 0x06
@@ -0,0 +1,35 @@
contract buggystruct {
Buggy public bug;
struct Buggy {
uint256 first;
uint256 second;
uint256 third;
string last;
}
constructor() public {
bug = Buggy(10, 20, 30, "asdfghjkl");
}
function getFirst() public returns (uint256) {
return bug.first;
}
function getSecond() public returns (uint256) {
return bug.second;
}
function getThird() public returns (uint256) {
return bug.third;
}
function getLast() public returns (string memory) {
return bug.last;
}
}
// ----
// getFirst() -> 0x0a
// getSecond() -> 0x14
// getThird() -> 0x1e
// getLast() -> 0x20, 0x09, "asdfghjkl"
@@ -0,0 +1,9 @@
contract C {
bytes32 constant x = keccak256("abc");
function f() public returns (bytes32) {
return x;
}
}
// ----
// f() -> 0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45
@@ -0,0 +1,26 @@
contract C {
uint256 public x;
function f() public pure returns (bytes4) {
return this.f.selector;
}
function g() public returns (bytes4) {
function () pure external returns (bytes4) fun = this.f;
return fun.selector;
}
function h() public returns (bytes4) {
function () pure external returns (bytes4) fun = this.f;
return fun.selector;
}
function i() public pure returns (bytes4) {
return this.x.selector;
}
}
// ----
// f() -> 0x26121ff000000000000000000000000000000000000000000000000000000000
// g() -> 0x26121ff000000000000000000000000000000000000000000000000000000000
// h() -> 0x26121ff000000000000000000000000000000000000000000000000000000000
// i() -> 0x0c55699c00000000000000000000000000000000000000000000000000000000
@@ -0,0 +1,12 @@
contract c {
bytes data;
function foo() public returns (bytes32) {
data.push("x");
data.push("y");
data.push("z");
return keccak256(abi.encodePacked("b", keccak256(data), "a"));
}
}
// ----
// foo() -> 0xb338eefce206f9f57b83aa738deecd5326dc4b72dd81ee6a7c621a6facb7acdc
@@ -0,0 +1,7 @@
contract c {
function foo(uint256 a, uint256 b, uint256 c) public returns (bytes32 d) {
d = keccak256(abi.encodePacked(a, b, c));
}
}
// ----
// foo(uint256,uint256,uint256): 0xa, 0xc, 0xd -> 0xbc740a98aae5923e8f04c9aa798c9ee82f69e319997699f2782c40828db9fd81
@@ -0,0 +1,7 @@
contract c {
function foo(uint256 a, uint16 b) public returns (bytes32 d) {
d = keccak256(abi.encodePacked(a, b, uint8(145)));
}
}
// ----
// foo(uint256,uint16): 0xa, 0xc -> 0x88acd45f75907e7c560318bc1a5249850a0999c4896717b1167d05d116e6dbad
@@ -0,0 +1,12 @@
contract c {
function foo() public returns (bytes32 d) {
d = keccak256("foo");
}
function bar(uint256 a, uint16 b) public returns (bytes32 d) {
d = keccak256(abi.encodePacked(a, b, uint8(145), "foo"));
}
}
// ----
// foo() -> 0x41b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d
// bar(uint256,uint16): 0xa, 0xc -> 0x6990f36476dc412b1c4baa48e2d9f4aa4bb313f61fda367c8fdbbb2232dc6146
@@ -0,0 +1,9 @@
contract test {
function foo(uint256 a) public returns (bytes4 value) {
return msg.sig;
}
}
// ====
// compileViaYul: also
// ----
// foo(uint256): 0x0 -> 0x2fbebd3800000000000000000000000000000000000000000000000000000000
@@ -0,0 +1,13 @@
contract test {
function boo() public returns (bytes4 value) {
return msg.sig;
}
function foo(uint256 a) public returns (bytes4 value) {
return boo();
}
}
// ====
// compileViaYul: also
// ----
// foo(uint256): 0x0 -> 0x2fbebd3800000000000000000000000000000000000000000000000000000000
@@ -0,0 +1,74 @@
pragma experimental ABIEncoderV2;
contract C {
function f1(bytes[1] calldata a)
external
returns (uint256, uint256, uint256, uint256)
{
return (a[0].length, uint8(a[0][0]), uint8(a[0][1]), uint8(a[0][2]));
}
function f2(bytes[1] calldata a, bytes[1] calldata b)
external
returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256)
{
return (
a[0].length,
uint8(a[0][0]),
uint8(a[0][1]),
uint8(a[0][2]),
b[0].length,
uint8(b[0][0]),
uint8(b[0][1])
);
}
function g1(bytes[2] calldata a)
external
returns (
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
uint256
)
{
return (
a[0].length,
uint8(a[0][0]),
uint8(a[0][1]),
uint8(a[0][2]),
a[1].length,
uint8(a[1][0]),
uint8(a[1][1]),
uint8(a[1][2])
);
}
function g2(bytes[] calldata a) external returns (uint256[8] memory) {
return [
a.length,
a[0].length,
uint8(a[0][0]),
uint8(a[0][1]),
a[1].length,
uint8(a[1][0]),
uint8(a[1][1]),
uint8(a[1][2])
];
}
}
// found expectation comments:
// same offset for both arrays @ ABI_CHECK(
// ----
// f1(bytes[1]): 0x20, 0x20, 0x3, hex"0102030000000000000000000000000000000000000000000000000000000000" -> 0x3, 0x1, 0x2, 0x3
// f2(bytes[1],bytes[1]): 0x40, 0xa0, 0x20, 0x3, hex"0102030000000000000000000000000000000000000000000000000000000000", 0x20, 0x2, hex"0102000000000000000000000000000000000000000000000000000000000000" -> 0x3, 0x1, 0x2, 0x3, 0x2, 0x1, 0x2
// g1(bytes[2]): 0x20, 0x40, 0x80, 0x3, hex"0102030000000000000000000000000000000000000000000000000000000000", 0x3, hex"0405060000000000000000000000000000000000000000000000000000000000" -> 0x3, 0x1, 0x2, 0x3, 0x3, 0x4, 0x5, 0x6
// g1(bytes[2]): 0x20, 0x40, 0x40, 0x3, hex"0102030000000000000000000000000000000000000000000000000000000000" -> 0x3, 0x1, 0x2, 0x3, 0x3, 0x1, 0x2, 0x3
// g2(bytes[]): 0x20, 0x2, 0x40, 0x80, 0x2, hex"0102000000000000000000000000000000000000000000000000000000000000", 0x3, hex"0405060000000000000000000000000000000000000000000000000000000000" -> 0x2, 0x2, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6
@@ -0,0 +1,18 @@
pragma experimental ABIEncoderV2;
contract C {
function f(bytes[] calldata a)
external
returns (uint256, uint256, bytes memory)
{
bytes memory m = a[0];
return (a.length, m.length, m);
}
}
// ----
// f(bytes[]): 0x20, 0x1, 0x20, 0x2, hex"6162000000000000000000000000000000000000000000000000000000000000" -> 0x1, 0x2, 0x60, 0x2, hex"6162000000000000000000000000000000000000000000000000000000000000"
// f(bytes[]): 0x20, 0x1, 0x20, 0x20, hex"7878787878787878787878787878787878787878787878787878787878787878" -> 0x1, 0x20, 0x60, 0x20, hex"7878787878787878787878787878787878787878787878787878787878787878"
// f(bytes[]): 0x20, 0x1, 0x20, 0x20, hex"7800000000000000000000000000000000000000000000000000000000000061" -> 0x1, 0x20, 0x60, 0x20, hex"7800000000000000000000000000000000000000000000000000000000000061"
// f(bytes[]): 0x20, 0x1, 0x20, 0x20, hex"6100000000000000000000000000000000000000000000000000000000000078" -> 0x1, 0x20, 0x60, 0x20, hex"6100000000000000000000000000000000000000000000000000000000000078"
// f(bytes[]): 0x20, 0x1, 0x20, 0x20, hex"616d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d78" -> 0x1, 0x20, 0x60, 0x20, hex"616d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d78"
@@ -0,0 +1,15 @@
pragma experimental ABIEncoderV2;
contract C {
function f(string[] calldata a)
external
returns (uint256, uint256, uint256, string memory)
{
string memory s1 = a[0];
bytes memory m1 = bytes(s1);
return (a.length, m1.length, uint8(m1[0]), s1);
}
}
// ----
// f(string[]): 0x20, 0x1, 0x20, 0x2, hex"6162000000000000000000000000000000000000000000000000000000000000" -> 1, 2, 97, 0x80, 2, "ab"
@@ -0,0 +1,22 @@
pragma experimental ABIEncoderV2;
contract C {
struct S {
uint8 a;
bytes1 b;
}
function f(S calldata s) external pure returns (uint256 a, bytes32 b) {
uint8 tmp1 = s.a;
bytes1 tmp2 = s.b;
assembly {
a := tmp1
b := tmp2
}
}
}
// ----
// f((uint8,bytes1)): 0x12, hex"3400000000000000000000000000000000000000000000000000000000000000" -> 0x12, hex"3400000000000000000000000000000000000000000000000000000000000000" # double check that the valid case goes through #
// f((uint8,bytes1)): 0x1234, hex"5678000000000000000000000000000000000000000000000000000000000000" -> FAILURE
// f((uint8,bytes1)): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> FAILURE
@@ -0,0 +1,23 @@
contract C {
function f(bool _b) public returns (uint256) {
if (_b) return 1;
else return 0;
}
function g(bool _in) public returns (bool _out) {
_out = _in;
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f(bool): 0x0 -> 0x0
// f(bool): 0x1 -> 0x1
// f(bool): 0x2 -> 0x1
// f(bool): 0x3 -> 0x1
// f(bool): 0xff -> 0x1
// g(bool): 0x0 -> 0x0
// g(bool): 0x1 -> 0x1
// g(bool): 0x2 -> 0x1
// g(bool): 0x3 -> 0x1
// g(bool): 0xff -> 0x1
@@ -0,0 +1,24 @@
pragma experimental ABIEncoderV2;
contract C {
function f(bool _b) public returns (uint256) {
if (_b) return 1;
else return 0;
}
function g(bool _in) public returns (bool _out) {
_out = _in;
}
}
// ----
// f(bool): 0x0 -> 0x0
// f(bool): 0x1 -> 0x1
// f(bool): 0x2 -> FAILURE
// f(bool): 0x3 -> FAILURE
// f(bool): 0xff -> FAILURE
// g(bool): 0x0 -> 0x0
// g(bool): 0x1 -> 0x1
// g(bool): 0x2 -> FAILURE
// g(bool): 0x3 -> FAILURE
// g(bool): 0xff -> FAILURE
@@ -0,0 +1,17 @@
// Checks that address types are properly cleaned before they are compared.
contract C {
function f(address a) public returns (uint256) {
if (a != 0x1234567890123456789012345678901234567890) return 1;
return 0;
}
function g(address payable a) public returns (uint256) {
if (a != 0x1234567890123456789012345678901234567890) return 1;
return 0;
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f(address): 0xffff1234567890123456789012345678901234567890 -> 0x0 # We input longer data on purpose.#
// g(address): 0xffff1234567890123456789012345678901234567890 -> 0x0
@@ -0,0 +1,18 @@
pragma experimental ABIEncoderV2;
// Checks that address types are properly cleaned before they are compared.
contract C {
function f(address a) public returns (uint256) {
if (a != 0x1234567890123456789012345678901234567890) return 1;
return 0;
}
function g(address payable a) public returns (uint256) {
if (a != 0x1234567890123456789012345678901234567890) return 1;
return 0;
}
}
// ----
// f(address): 0xffff1234567890123456789012345678901234567890 -> FAILURE # We input longer data on purpose.#
// g(address): 0xffff1234567890123456789012345678901234567890 -> FAILURE
@@ -0,0 +1,13 @@
// Checks that bytesXX types are properly cleaned before they are compared.
contract C {
function f(bytes2 a, uint16 x) public returns (uint256) {
if (a != "ab") return 1;
if (x != 0x0102) return 2;
if (bytes3(uint24(x)) != 0x000102) return 3;
return 0;
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f(bytes2,uint16): "abc", 0x40102 -> 0x0 # We input longer data on purpose. #
@@ -0,0 +1,14 @@
pragma experimental ABIEncoderV2;
// Checks that bytesXX types are properly cleaned before they are compared.
contract C {
function f(bytes2 a, uint16 x) public returns (uint256) {
if (a != "ab") return 1;
if (x != 0x0102) return 2;
if (bytes3(uint24(x)) != 0x000102) return 3;
return 0;
}
}
// ----
// f(bytes2,uint16): "abc", 0x40102 -> FAILURE # We input longer data on purpose. #
@@ -0,0 +1,15 @@
contract C {
uint public i;
uint public k;
constructor(uint newI, uint newK) public {
i = newI;
k = newK;
}
}
// ====
// compileViaYul: also
// ----
// constructor(): 2, 0 ->
// i() -> 2
// k() -> 0
@@ -0,0 +1,37 @@
contract C {
uint256 value;
function set(uint256 _value) external {
value = _value;
}
function get() external view returns (uint256) {
return value;
}
function get_delegated() external returns (bool, bytes memory) {
return address(this).delegatecall(abi.encodeWithSignature("get()"));
}
function assert0() external view {
assert(value == 0);
}
function assert0_delegated() external returns (bool, bytes memory) {
return address(this).delegatecall(abi.encodeWithSignature("assert0()"));
}
}
// ====
// EVMVersion: >=byzantium
// ----
// get() -> 0x00
// assert0_delegated() -> 0x01, 0x40, 0x0
// get_delegated() -> 0x01, 0x40, 0x20, 0x0
// set(uint256): 0x01 ->
// get() -> 0x01
// assert0_delegated() -> 0x00, 0x40, 0x0
// get_delegated() -> 0x01, 0x40, 0x20, 0x1
// set(uint256): 0x2a ->
// get() -> 0x2a
// assert0_delegated() -> 0x00, 0x40, 0x0
// get_delegated() -> 0x01, 0x40, 0x20, 0x2a
@@ -0,0 +1,39 @@
contract C {
uint256 value;
function set(uint256 _value) external {
value = _value;
}
function get() external view returns (uint256) {
return value;
}
function get_delegated() external returns (bool) {
(bool success,) = address(this).delegatecall(abi.encodeWithSignature("get()"));
return success;
}
function assert0() external view {
assert(value == 0);
}
function assert0_delegated() external returns (bool) {
(bool success,) = address(this).delegatecall(abi.encodeWithSignature("assert0()"));
return success;
}
}
// ====
// EVMVersion: <byzantium
// ----
// get() -> 0x00
// assert0_delegated() -> true
// get_delegated() -> true
// set(uint256): 0x01 ->
// get() -> 0x01
// assert0_delegated() -> false
// get_delegated() -> true
// set(uint256): 0x2a ->
// get() -> 0x2a
// assert0_delegated() -> false
// get_delegated() -> true
@@ -0,0 +1,8 @@
contract A {
uint8 immutable a = 2;
function f() public view returns (uint) {
return a;
}
}
// ----
// f() -> 2
@@ -0,0 +1,5 @@
contract C {
uint immutable public x = 1;
}
// ----
// x() -> 1
@@ -0,0 +1,17 @@
contract A {
uint immutable public x = 1;
uint public y;
constructor() public {
y = this.x();
}
}
contract C {
function f() public returns (bool) {
try new A() { return false; }
catch { return true; }
}
}
// ====
// EVMVersion: >=tangerineWhistle
// ----
// f() -> true
@@ -0,0 +1,30 @@
contract A {
uint8 immutable a;
constructor() public {
a = 4;
}
}
contract B is A {
uint8 immutable b;
constructor() public {
b = 3;
}
}
contract C is A {
uint8 immutable c;
constructor() public {
c = 2;
}
}
contract D is B, C {
uint8 immutable d;
constructor() public {
d = 1;
}
function f() public view returns (uint256, uint256, uint, uint) {
return (a, b, c, d);
}
}
// ----
// f() -> 4, 3, 2, 1
@@ -0,0 +1,15 @@
contract C {
function() internal view returns(uint256) immutable z;
constructor() public {
z = f;
}
function f() public view returns (uint256) {
return 7;
}
function callZ() public view returns (uint) {
return z();
}
}
// ----
// f() -> 7
// callZ() -> 7
@@ -0,0 +1,31 @@
contract A {
uint immutable a;
constructor() public {
a = 7;
}
function f() public view returns (uint) { return a; }
}
contract B {
uint immutable a;
constructor() public {
a = 5;
}
function f() public view returns (uint) { return a; }
}
contract C {
uint immutable a;
uint public x;
uint public y;
constructor() public {
a = 3;
x = (new A()).f();
y = (new B()).f();
}
function f() public returns (uint256, uint, uint) {
return (a, (new A()).f(), (new B()).f());
}
}
// ----
// f() -> 3, 7, 5
// x() -> 7
// y() -> 5
@@ -0,0 +1,13 @@
contract C {
uint256 immutable x;
uint256 immutable y;
constructor() public {
x = 42;
y = 23;
}
function f() public view returns (uint256, uint256) {
return (x+x,y);
}
}
// ----
// f() -> 84, 23
@@ -0,0 +1,19 @@
contract C {
uint256 immutable x;
uint256 immutable y;
mapping(uint => uint) public m;
constructor(uint _a) public {
x = 42;
y = 23;
m[_a] = 7;
new uint[](4);
}
function f() public view returns (uint256, uint256) {
return (x+x,y);
}
}
// ----
// constructor(): 3 ->
// f() -> 84, 23
// m(uint256): 3 -> 7
@@ -0,0 +1,34 @@
contract C {
function shl(uint256 a, uint256 b) public returns (uint256 c) {
assembly {
c := shl(b, a)
}
}
function shr(uint256 a, uint256 b) public returns (uint256 c) {
assembly {
c := shr(b, a)
}
}
function sar(uint256 a, uint256 b) public returns (uint256 c) {
assembly {
c := sar(b, a)
}
}
}
// ====
// EVMVersion: >=constantinople
// compileViaYul: also
// ----
// shl(uint256,uint256): 0x01, 0x02 -> 0x04
// shl(uint256,uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0x01 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
// shl(uint256,uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0x100 -> 0x00
// shr(uint256,uint256): 0x03, 0x01 -> 0x01
// shr(uint256,uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0x01 -> 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// shr(uint256,uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0xff -> 0x01
// shr(uint256,uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0x100 -> 0x00
// sar(uint256,uint256): 0x03, 0x01 -> 0x01
// sar(uint256,uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0x01 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// sar(uint256,uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0xff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// sar(uint256,uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0x100 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -0,0 +1,122 @@
contract C {
function shl_zero(uint256 a) public returns (uint256 c) {
assembly {
c := shl(0, a)
}
}
function shr_zero(uint256 a) public returns (uint256 c) {
assembly {
c := shr(0, a)
}
}
function sar_zero(uint256 a) public returns (uint256 c) {
assembly {
c := sar(0, a)
}
}
function shl_large(uint256 a) public returns (uint256 c) {
assembly {
c := shl(0x110, a)
}
}
function shr_large(uint256 a) public returns (uint256 c) {
assembly {
c := shr(0x110, a)
}
}
function sar_large(uint256 a) public returns (uint256 c) {
assembly {
c := sar(0x110, a)
}
}
function shl_combined(uint256 a) public returns (uint256 c) {
assembly {
c := shl(4, shl(12, a))
}
}
function shr_combined(uint256 a) public returns (uint256 c) {
assembly {
c := shr(4, shr(12, a))
}
}
function sar_combined(uint256 a) public returns (uint256 c) {
assembly {
c := sar(4, sar(12, a))
}
}
function shl_combined_large(uint256 a) public returns (uint256 c) {
assembly {
c := shl(0xd0, shl(0x40, a))
}
}
function shl_combined_overflow(uint256 a) public returns (uint256 c) {
assembly {
c := shl(0x01, shl(not(0x00), a))
}
}
function shr_combined_large(uint256 a) public returns (uint256 c) {
assembly {
c := shr(0xd0, shr(0x40, a))
}
}
function shr_combined_overflow(uint256 a) public returns (uint256 c) {
assembly {
c := shr(0x01, shr(not(0x00), a))
}
}
function sar_combined_large(uint256 a) public returns (uint256 c) {
assembly {
c := sar(0xd0, sar(0x40, a))
}
}
}
// ====
// EVMVersion: >=constantinople
// compileViaYul: also
// ----
// shl_zero(uint256): 0x00 -> 0x00
// shl_zero(uint256): 0xffff -> 0xffff
// shl_zero(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// shr_zero(uint256): 0x00 -> 0x00
// shr_zero(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// sar_zero(uint256): 0x00 -> 0x00
// sar_zero(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// shl_large(uint256): 0x00 -> 0x00
// shl_large(uint256): 0xffff -> 0x00
// shl_large(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x00
// shr_large(uint256): 0x00 -> 0x00
// shr_large(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x00
// sar_large(uint256): 0x00 -> 0x00
// sar_large(uint256): 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x00
// sar_large(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// shl_combined(uint256): 0x00 -> 0x00
// shl_combined(uint256): 0xffff -> 0xffff0000
// shl_combined(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000
// shr_combined(uint256): 0x00 -> 0x00
// shr_combined(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// sar_combined(uint256): 0x00 -> 0x00
// sar_combined(uint256): 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// sar_combined(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// shl_combined_large(uint256): 0x00 -> 0x00
// shl_combined_large(uint256): 0xffff -> 0x00
// shl_combined_large(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x00
// shl_combined_overflow(uint256): 0x02 -> 0x00
// shr_combined_large(uint256): 0x00 -> 0x00
// shr_combined_large(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x00
// shr_combined_overflow(uint256): 0x02 -> 0x00
// sar_combined_large(uint256): 0x00 -> 0x00
// sar_combined_large(uint256): 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x00
// sar_combined_large(uint256): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -0,0 +1,83 @@
contract C {
function shl_1() public returns (bool) {
uint256 c;
assembly {
c := shl(2, 1)
}
assert(c == 4);
return true;
}
function shl_2() public returns (bool) {
uint256 c;
assembly {
c := shl(
1,
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
)
}
assert(
c ==
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
);
return true;
}
function shl_3() public returns (bool) {
uint256 c;
assembly {
c := shl(
256,
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
)
}
assert(c == 0);
return true;
}
function shr_1() public returns (bool) {
uint256 c;
assembly {
c := shr(1, 3)
}
assert(c == 1);
return true;
}
function shr_2() public returns (bool) {
uint256 c;
assembly {
c := shr(
1,
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
)
}
assert(
c ==
0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
);
return true;
}
function shr_3() public returns (bool) {
uint256 c;
assembly {
c := shr(
256,
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
)
}
assert(c == 0);
return true;
}
}
// ====
// EVMVersion: >=constantinople
// compileViaYul: also
// ----
// shl_1() -> 0x01
// shl_2() -> 0x01
// shl_3() -> 0x01
// shr_1() -> 0x01
// shr_2() -> 0x01
// shr_3() -> 0x01
@@ -0,0 +1,14 @@
contract C {
function f(uint8 a, uint8 b) public returns (uint256) {
assembly {
a := 0xffffffff
}
// Higher bits should be cleared before the shift
return a >> b;
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f(uint8,uint8): 0x00, 0x04 -> 0x0f
// f(uint8,uint8): 0x00, 0x1004 -> 0x0f
@@ -0,0 +1,30 @@
contract C {
function f(int8 a, uint8 b) public returns (int256) {
assembly {
a := 0xfffffff0
}
// Higher bits should be signextended before the shift
return a >> b;
}
function g(int8 a, uint8 b) public returns (int256) {
assembly {
a := 0xf0
}
// Higher bits should be signextended before the shift
return a >> b;
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f(int8,uint8): 0x00, 0x03 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
// f(int8,uint8): 0x00, 0x04 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// f(int8,uint8): 0x00, 0xff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// f(int8,uint8): 0x00, 0x1003 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
// f(int8,uint8): 0x00, 0x1004 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// g(int8,uint8): 0x00, 0x03 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
// g(int8,uint8): 0x00, 0x04 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// g(int8,uint8): 0x00, 0xff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// g(int8,uint8): 0x00, 0x1003 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
// g(int8,uint8): 0x00, 0x1004 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -0,0 +1,31 @@
pragma experimental ABIEncoderV2;
contract C {
function f(int8 a, uint8 b) public returns (int256) {
assembly {
a := 0xfffffff0
}
// Higher bits should be signextended before the shift
return a >> b;
}
function g(int8 a, uint8 b) public returns (int256) {
assembly {
a := 0xf0
}
// Higher bits should be signextended before the shift
return a >> b;
}
}
// ----
// f(int8,uint8): 0x00, 0x03 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
// f(int8,uint8): 0x00, 0x04 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// f(int8,uint8): 0x00, 0xff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// f(int8,uint8): 0x00, 0x1003 -> FAILURE
// f(int8,uint8): 0x00, 0x1004 -> FAILURE
// g(int8,uint8): 0x00, 0x03 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
// g(int8,uint8): 0x00, 0x04 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// g(int8,uint8): 0x00, 0xff -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// g(int8,uint8): 0x00, 0x1003 -> FAILURE
// g(int8,uint8): 0x00, 0x1004 -> FAILURE
@@ -0,0 +1,15 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint8 a, uint8 b) public returns (uint256) {
assembly {
a := 0xffffffff
}
// Higher bits should be cleared before the shift
return a >> b;
}
}
// ----
// f(uint8,uint8): 0x00, 0x04 -> 0x0f
// f(uint8,uint8): 0x00, 0x1004 -> FAILURE
@@ -0,0 +1,13 @@
contract C {
function f(int16 a, int16 b) public returns (int16) {
return a >> b;
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f(int16,int16): 0xff99, 0x00 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99
// f(int16,int16): 0xff99, 0x01 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcc
// f(int16,int16): 0xff99, 0x02 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6
// f(int16,int16): 0xff99, 0x04 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9
// f(int16,int16): 0xff99, 0x08 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -0,0 +1,14 @@
pragma experimental ABIEncoderV2;
contract C {
function f(int16 a, int16 b) public returns (int16) {
return a >> b;
}
}
// ----
// f(int16,int16): 0xff99, 0x00 -> FAILURE
// f(int16,int16): 0xff99, 0x01 -> FAILURE
// f(int16,int16): 0xff99, 0x02 -> FAILURE
// f(int16,int16): 0xff99, 0x04 -> FAILURE
// f(int16,int16): 0xff99, 0x08 -> FAILURE
@@ -0,0 +1,13 @@
contract C {
function f(int32 a, int32 b) public returns (int32) {
return a >> b;
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f(int32,int32): 0xffffff99, 0x00 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99
// f(int32,int32): 0xffffff99, 0x01 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcc
// f(int32,int32): 0xffffff99, 0x02 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6
// f(int32,int32): 0xffffff99, 0x04 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9
// f(int32,int32): 0xffffff99, 0x08 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -0,0 +1,14 @@
pragma experimental ABIEncoderV2;
contract C {
function f(int32 a, int32 b) public returns (int32) {
return a >> b;
}
}
// ----
// f(int32,int32): 0xffffff99, 0x00 -> FAILURE
// f(int32,int32): 0xffffff99, 0x01 -> FAILURE
// f(int32,int32): 0xffffff99, 0x02 -> FAILURE
// f(int32,int32): 0xffffff99, 0x04 -> FAILURE
// f(int32,int32): 0xffffff99, 0x08 -> FAILURE
@@ -0,0 +1,13 @@
contract C {
function f(int8 a, int8 b) public returns (int8) {
return a >> b;
}
}
// ====
// ABIEncoderV1Only: true
// ----
// f(int8,int8): 0x99, 0x00 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99
// f(int8,int8): 0x99, 0x01 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcc
// f(int8,int8): 0x99, 0x02 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6
// f(int8,int8): 0x99, 0x04 -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9
// f(int8,int8): 0x99, 0x08 -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -0,0 +1,14 @@
pragma experimental ABIEncoderV2;
contract C {
function f(int8 a, int8 b) public returns (int8) {
return a >> b;
}
}
// ----
// f(int8,int8): 0x99, 0x00 -> FAILURE
// f(int8,int8): 0x99, 0x01 -> FAILURE
// f(int8,int8): 0x99, 0x02 -> FAILURE
// f(int8,int8): 0x99, 0x04 -> FAILURE
// f(int8,int8): 0x99, 0x08 -> FAILURE
@@ -0,0 +1,69 @@
contract Test {
struct S {
uint8 x;
uint16 y;
uint256 z;
}
struct X {
uint8 x;
S s;
uint8[2] a;
}
X m_x;
function load()
public
returns (
uint256 a,
uint256 x,
uint256 y,
uint256 z,
uint256 a1,
uint256 a2
)
{
m_x.x = 1;
m_x.s.x = 2;
m_x.s.y = 3;
m_x.s.z = 4;
m_x.a[0] = 5;
m_x.a[1] = 6;
X memory d = m_x;
a = d.x;
x = d.s.x;
y = d.s.y;
z = d.s.z;
a1 = d.a[0];
a2 = d.a[1];
}
function store()
public
returns (
uint256 a,
uint256 x,
uint256 y,
uint256 z,
uint256 a1,
uint256 a2
)
{
X memory d;
d.x = 1;
d.s.x = 2;
d.s.y = 3;
d.s.z = 4;
d.a[0] = 5;
d.a[1] = 6;
m_x = d;
a = m_x.x;
x = m_x.s.x;
y = m_x.s.y;
z = m_x.s.z;
a1 = m_x.a[0];
a2 = m_x.a[1];
}
}
// ----
// load() -> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
// store() -> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
@@ -0,0 +1,30 @@
contract C {
struct X {
uint256 x1;
uint256 x2;
}
struct S {
uint256 s1;
uint256[3] s2;
X s3;
}
S s;
constructor() public {
uint256[3] memory s2;
s2[1] = 9;
s = S(1, s2, X(4, 5));
}
function get()
public
returns (uint256 s1, uint256[3] memory s2, uint256 x1, uint256 x2)
{
s1 = s.s1;
s2 = s.s2;
x1 = s.s3.x1;
x2 = s.s3.x2;
}
}
// ----
// get() -> 0x01, 0x00, 0x09, 0x00, 0x04, 0x05
@@ -0,0 +1,24 @@
contract test {
function f0() public returns(int, bool) {
int a;
bool b;
((a, b)) = (2, true);
return (a, b);
}
function f1() public returns(int) {
int a;
(((a, ), )) = ((1, 2) ,3);
return a;
}
function f2() public returns(int) {
int a;
(((, a),)) = ((1, 2), 3);
return a;
}
}
// ====
// compileViaYul: also
// ----
// f0() -> 2, true
// f1() -> 1
// f2() -> 2
@@ -0,0 +1,23 @@
// This triggered a bug in some version because the variable in the modifier was not
// unregistered correctly.
contract C {
uint256 public x;
modifier m1 {
address a1 = msg.sender;
x++;
_;
}
function f1() public m1() {
x += 7;
}
function f2() public m1() {
x += 3;
}
}
// ----
// f1() ->
// x() -> 0x08
// f2() ->
// x() -> 0x0c
@@ -0,0 +1,39 @@
contract C {
uint256 x;
function f() public returns (uint256) {
x = 3;
return 1;
}
}
interface CView {
function f() external view returns (uint256);
}
interface CPure {
function f() external pure returns (uint256);
}
contract D {
function f() public returns (uint256) {
return (new C()).f();
}
function fview() public returns (uint256) {
return (CView(address(new C()))).f();
}
function fpure() public returns (uint256) {
return (CPure(address(new C()))).f();
}
}
// ====
// EVMVersion: >=byzantium
// ----
// f() -> 0x1 # This should work, next should throw #
// fview() -> FAILURE
// fpure() -> FAILURE
@@ -0,0 +1,39 @@
contract C {
uint256 x;
function f() public returns (uint256) {
x = 3;
return 1;
}
}
interface CView {
function f() external view returns (uint256);
}
interface CPure {
function f() external pure returns (uint256);
}
contract D {
function f() public returns (uint256) {
return (new C()).f();
}
function fview() public returns (uint256) {
return (CView(address(new C()))).f();
}
function fpure() public returns (uint256) {
return (CPure(address(new C()))).f();
}
}
// ====
// EVMVersion: <byzantium
// ----
// f() -> 0x1
// fview() -> 1
// fpure() -> 1
@@ -0,0 +1,29 @@
contract C {
function f(uint n, uint m) public {
function() internal returns (uint)[] memory arr = new function() internal returns (uint)[](n);
arr[m]();
}
function f2(uint n, uint m, uint a, uint b) public {
function() internal returns (uint)[][] memory arr = new function() internal returns (uint)[][](n);
for (uint i = 0; i < n; ++i)
arr[i] = new function() internal returns (uint)[](m);
arr[a][b]();
}
function g(uint n, uint m) public {
function() external returns (uint)[] memory arr = new function() external returns (uint)[](n);
arr[m]();
}
function g2(uint n, uint m, uint a, uint b) public {
function() external returns (uint)[][] memory arr = new function() external returns (uint)[][](n);
for (uint i = 0; i < n; ++i)
arr[i] = new function() external returns (uint)[](m);
arr[a][b]();
}
}
// ====
// compileViaYul: also
// ----
// f(uint256,uint256): 1823621, 12323 -> FAILURE
// f2(uint256,uint256,uint256,uint256): 18723921, 1823621, 123, 12323 -> FAILURE
// g(uint256,uint256): 1823621, 12323 -> FAILURE
// g2(uint256,uint256,uint256,uint256): 18723921, 1823621, 123, 12323 -> FAILURE
@@ -0,0 +1,24 @@
contract C {
uint test1;
uint test2;
uint test3;
uint test4;
uint test5;
uint test6;
uint test7;
mapping (string => uint) map;
function set(string memory s, uint n, uint m, uint a, uint b) public returns (uint) {
map[s] = 0;
uint[][] memory x = new uint[][](n);
for (uint i = 0; i < n; ++i)
x[i] = new uint[](m);
return x[a][b];
}
}
// ====
// compileViaYul: also
// ----
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 0, 0, 32, "01234567890123456789012345678901" -> 0
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 1, 3, 32, "01234567890123456789012345678901" -> 0
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 3, 3, 32, "01234567890123456789012345678901" -> FAILURE
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 1, 5, 32, "01234567890123456789012345678901" -> FAILURE
@@ -0,0 +1,22 @@
contract C {
uint test1;
uint test2;
uint test3;
uint test4;
uint test5;
uint test6;
uint test7;
mapping (string => uint) map;
function set(string memory s, uint n, uint m) public returns (uint) {
map[s] = 0;
uint[4][] memory x = new uint[4][](n);
return x[m][0];
}
}
// ====
// compileViaYul: also
// ----
// set(string,uint256,uint256): 0x60, 2, 0, 32, "01234567890123456789012345678901" -> 0
// set(string,uint256,uint256): 0x60, 2, 1, 32, "01234567890123456789012345678901" -> 0
// set(string,uint256,uint256): 0x60, 2, 2, 32, "01234567890123456789012345678901" -> FAILURE
// set(string,uint256,uint256): 0x60, 200, 199, 32, "01234567890123456789012345678901" -> 0
@@ -0,0 +1,17 @@
contract C {
uint test1;
uint test2;
uint test3;
uint test4;
uint test5;
uint test6;
uint test7;
mapping (string => uint) map;
function set(string memory s) public returns (uint[3] memory x, uint[2] memory y, uint[] memory z, uint t) {
map[s] = 0;
}
}
// ====
// compileViaYul: also
// ----
// set(string): 0x20, 32, "01234567890123456789012345678901" -> 0, 0, 0, 0, 0, 0xe0, 0, 0
@@ -0,0 +1,19 @@
contract C {
uint test1;
uint test2;
uint test3;
uint test4;
uint test5;
uint test6;
uint test7;
mapping (string => uint) map;
function set(string memory s) public returns (uint) {
map[s] = 0;
uint[3] memory x;
return x[2];
}
}
// ====
// compileViaYul: also
// ----
// set(string): 0x20, 32, "01234567890123456789012345678901" -> 0
@@ -0,0 +1,22 @@
contract C {
uint test1;
uint test2;
uint test3;
uint test4;
uint test5;
uint test6;
uint test7;
mapping (string => uint) map;
function set(string memory s, uint n, uint a) public returns (uint) {
map[s] = 0;
uint[] memory x = new uint[](n);
return x[a];
}
}
// ====
// compileViaYul: also
// ----
// set(string,uint256,uint256): 0x60, 5, 0, 32, "01234567890123456789012345678901" -> 0
// set(string,uint256,uint256): 0x60, 5, 1, 32, "01234567890123456789012345678901" -> 0
// set(string,uint256,uint256): 0x60, 5, 4, 32, "01234567890123456789012345678901" -> 0
// set(string,uint256,uint256): 0x60, 5, 5, 32, "01234567890123456789012345678901" -> FAILURE
@@ -0,0 +1,25 @@
contract C {
function f() public {
function() internal returns (uint) _f;
_f();
}
function g() public {
function() external returns (uint) _g;
_g();
}
function h1() internal returns (function() internal returns (uint) _h) {}
function h2() public {
h1()();
}
function k1() internal returns (function() external returns (uint) _k) {}
function k2() public {
k1()();
}
}
// ====
// compileViaYul: also
// ----
// f() -> FAILURE
// g() -> FAILURE
// h2() -> FAILURE
// k2() -> FAILURE
@@ -0,0 +1,16 @@
contract C {
uint[] arr1;
uint[][] arr2;
function f() internal returns (uint[] storage ptr1, uint[][] storage ptr2) {
ptr1 = arr1;
ptr2 = arr2;
}
function g() public returns (uint, uint) {
return (arr1.length, arr2.length);
}
}
// ====
// compileViaYul: also
// ----
// g() -> 0, 0
@@ -0,0 +1,20 @@
pragma experimental SMTChecker;
contract C {
function c() public pure returns (uint) { return 42; }
}
contract B is C {
function b() public pure returns (uint) { return c(); }
}
contract A is B {
uint public x;
function a() public {
x = b();
assert(x < 40);
}
}
// ----
// Warning: (254-268): Assertion violation happens here
@@ -0,0 +1,24 @@
pragma experimental SMTChecker;
contract C {
uint y;
function c(uint _y) public returns (uint) {
y = _y;
return y;
}
}
contract B is C {
function b() public returns (uint) { return c(42); }
}
contract A is B {
uint public x;
function a() public {
x = b();
assert(x < 40);
}
}
// ----
// Warning: (274-288): Assertion violation happens here
@@ -2,8 +2,10 @@ contract C {
function f() public {
uint[] storage x;
uint[10] storage y;
x;
y;
}
}
// ----
// DeclarationError: (38-54): Uninitialized storage pointer.
// DeclarationError: (58-76): Uninitialized storage pointer.
// TypeError: (80-81): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
// TypeError: (85-86): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
@@ -0,0 +1,38 @@
contract C {
struct S { bool f; }
S s;
function f() internal pure {
S storage c;
assembly {
for {} eq(0,0) { c_slot := s_slot } {}
}
c;
}
function g() internal pure {
S storage c;
assembly {
for {} eq(0,1) { c_slot := s_slot } {}
}
c;
}
function h() internal pure {
S storage c;
assembly {
for {} eq(0,0) {} { c_slot := s_slot }
}
c;
}
function i() internal pure {
S storage c;
assembly {
for {} eq(0,1) {} { c_slot := s_slot }
}
c;
}
}
// ----
// TypeError: (189-190): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
// TypeError: (340-341): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
// TypeError: (491-492): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
// TypeError: (642-643): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
@@ -0,0 +1,19 @@
contract C {
struct S { bool f; }
S s;
function f() internal pure {
S storage c;
assembly {
for { c_slot := s_slot } iszero(0) {} {}
}
c;
}
function g() internal pure {
S storage c;
assembly {
for { c_slot := s_slot } iszero(1) {} {}
}
c;
}
}
// ----
@@ -0,0 +1,13 @@
contract C {
struct S { bool f; }
S s;
function f(bool flag) internal pure {
S storage c;
assembly {
if flag { c_slot := s_slot }
}
c;
}
}
// ----
// TypeError: (188-189): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
@@ -0,0 +1,15 @@
contract C {
struct S { bool f; }
S s;
function f() internal pure {
S storage c;
// this should warn about unreachable code, but currently function flow is ignored
assembly {
function f() { return(0, 0) }
f()
c_slot := s_slot
}
c;
}
}
// ----
@@ -0,0 +1,15 @@
contract C {
struct S { bool f; }
S s;
function f() internal pure {
S storage c;
// this could be allowed, but currently control flow for functions is not analysed
assembly {
function f() { revert(0, 0) }
f()
}
c;
}
}
// ----
// TypeError: (287-288): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
@@ -0,0 +1,12 @@
contract C {
struct S { bool f; }
S s;
function f() internal pure {
S storage c;
assembly {
c_slot := s_slot
}
c;
}
}
// ----
@@ -0,0 +1,33 @@
contract C {
struct S { bool f; }
S s;
function f(uint256 a) internal pure {
S storage c;
assembly {
switch a
case 0 { c_slot := s_slot }
}
c;
}
function g(bool flag) internal pure {
S storage c;
assembly {
switch flag
case 0 { c_slot := s_slot }
case 1 { c_slot := s_slot }
}
c;
}
function h(uint256 a) internal pure {
S storage c;
assembly {
switch a
case 0 { c_slot := s_slot }
default { return(0,0) }
}
c;
}
}
// ----
// TypeError: (208-209): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
// TypeError: (421-422): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
@@ -0,0 +1,31 @@
contract C {
struct S { bool f; }
S s;
function f(uint256 a) internal pure {
S storage c;
assembly {
switch a
default { c_slot := s_slot }
}
c;
}
function g(bool flag) internal pure {
S storage c;
assembly {
switch flag
case 0 { c_slot := s_slot }
default { c_slot := s_slot }
}
c;
}
function h(uint256 a) internal pure {
S storage c;
assembly {
switch a
case 0 { revert(0, 0) }
default { c_slot := s_slot }
}
c;
}
}
// ----

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