aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--docs/assembly.rst6
-rw-r--r--libevmasm/GasMeter.cpp3
-rw-r--r--libevmasm/Instruction.cpp2
-rw-r--r--libevmasm/Instruction.h1
-rw-r--r--libevmasm/SemanticInformation.cpp3
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp12
-rw-r--r--test/liblll/Compiler.cpp4
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp13
9 files changed, 42 insertions, 3 deletions
diff --git a/Changelog.md b/Changelog.md
index 7330f6d3..fbb41ece 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -91,6 +91,7 @@ Compiler Features:
* Build System: Support for Mojave version of macOS added.
* C API (``libsolc``): Export the ``solidity_license``, ``solidity_version`` and ``solidity_compile`` methods.
* Code Generator: ``CREATE2`` instruction has been updated to match EIP1014 (aka "Skinny CREATE2"). It also is accepted as part of Constantinople.
+ * Code Generator: ``EXTCODEHASH`` instruction has been added based on EIP1052.
* Type Checker: Nicer error message when trying to reference overloaded identifiers in inline assembly.
* Type Checker: Show named argument in case of error.
* Type System: IntegerType is split into IntegerType and AddressType internally.
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 5d723645..02a802a8 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -271,12 +271,14 @@ In the grammar, opcodes are represented as pre-defined identifiers.
+-------------------------+-----+---+-----------------------------------------------------------------+
| returndatacopy(t, f, s) | `-` | B | copy s bytes from returndata at position f to mem at position t |
+-------------------------+-----+---+-----------------------------------------------------------------+
+| extcodehash(a) | | C | code hash of address a |
++-------------------------+-----+---+-----------------------------------------------------------------+
| create(v, p, s) | | F | create new contract with code mem[p...(p+s)) and send v wei |
| | | | and return the new address |
+-------------------------+-----+---+-----------------------------------------------------------------+
| create2(v, n, p, s) | | C | create new contract with code mem[p...(p+s)) at address |
-| | | | keccak256(<address> . n . keccak256(mem[p...(p+s))) and send v |
-| | | | wei and return the new address |
+| | | | keccak256(0xff . <address> . n . keccak256(mem[p...(p+s))) |
+| | | | and send v wei and return the new address |
+-------------------------+-----+---+-----------------------------------------------------------------+
| call(g, a, v, in, | | F | call contract at address a with input mem[in...(in+insize)) |
| insize, out, outsize) | | | providing g gas and v wei and output area |
diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp
index b40617c1..d98b3efa 100644
--- a/libevmasm/GasMeter.cpp
+++ b/libevmasm/GasMeter.cpp
@@ -114,6 +114,9 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
case Instruction::EXTCODESIZE:
gas = GasCosts::extCodeGas(m_evmVersion);
break;
+ case Instruction::EXTCODEHASH:
+ gas = GasCosts::balanceGas(m_evmVersion);
+ break;
case Instruction::EXTCODECOPY:
gas = GasCosts::extCodeGas(m_evmVersion);
gas += memoryGas(-1, -3);
diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp
index d5b82e75..cf98c938 100644
--- a/libevmasm/Instruction.cpp
+++ b/libevmasm/Instruction.cpp
@@ -73,6 +73,7 @@ const std::map<std::string, Instruction> dev::solidity::c_instructions =
{ "EXTCODECOPY", Instruction::EXTCODECOPY },
{ "RETURNDATASIZE", Instruction::RETURNDATASIZE },
{ "RETURNDATACOPY", Instruction::RETURNDATACOPY },
+ { "EXTCODEHASH", Instruction::EXTCODEHASH },
{ "BLOCKHASH", Instruction::BLOCKHASH },
{ "COINBASE", Instruction::COINBASE },
{ "TIMESTAMP", Instruction::TIMESTAMP },
@@ -216,6 +217,7 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::ExtCode } },
{ Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } },
{ Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } },
+ { Instruction::EXTCODEHASH, { "EXTCODEHASH", 0, 1, 1, false, Tier::Balance } },
{ Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::Ext } },
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } },
{ Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } },
diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h
index 50c1f47d..63424eeb 100644
--- a/libevmasm/Instruction.h
+++ b/libevmasm/Instruction.h
@@ -82,6 +82,7 @@ enum class Instruction: uint8_t
EXTCODECOPY, ///< copy external code (from another contract)
RETURNDATASIZE = 0x3d, ///< get size of return data buffer
RETURNDATACOPY = 0x3e, ///< copy return data in current environment to memory
+ EXTCODEHASH = 0x3f, ///< get external code hash (from another contract)
BLOCKHASH = 0x40, ///< get hash of most recent complete block
COINBASE, ///< get the block's coinbase address
diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp
index 71267ee8..78f3c9c7 100644
--- a/libevmasm/SemanticInformation.cpp
+++ b/libevmasm/SemanticInformation.cpp
@@ -151,6 +151,7 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item)
case Instruction::MSIZE: // depends on previous writes and reads, not only on content
case Instruction::BALANCE: // depends on previous calls
case Instruction::EXTCODESIZE:
+ case Instruction::EXTCODEHASH:
case Instruction::RETURNDATACOPY: // depends on previous calls
case Instruction::RETURNDATASIZE:
return false;
@@ -172,6 +173,7 @@ bool SemanticInformation::movable(Instruction _instruction)
case Instruction::KECCAK256:
case Instruction::BALANCE:
case Instruction::EXTCODESIZE:
+ case Instruction::EXTCODEHASH:
case Instruction::RETURNDATASIZE:
case Instruction::SLOAD:
case Instruction::PC:
@@ -233,6 +235,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction)
case Instruction::GASPRICE:
case Instruction::EXTCODESIZE:
case Instruction::EXTCODECOPY:
+ case Instruction::EXTCODEHASH:
case Instruction::BLOCKHASH:
case Instruction::COINBASE:
case Instruction::TIMESTAMP:
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index 0f2c0f56..947b6d05 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -568,7 +568,17 @@ void AsmAnalyzer::warnOnInstructions(solidity::Instruction _instr, SourceLocatio
// Similarly we assume bitwise shifting and create2 go together.
solAssert(m_evmVersion.hasBitwiseShifting() == m_evmVersion.hasCreate2(), "");
- if ((
+ if (_instr == solidity::Instruction::EXTCODEHASH)
+ m_errorReporter.warning(
+ _location,
+ "The \"" +
+ boost::to_lower_copy(instructionInfo(_instr).name)
+ + "\" instruction is not supported by the VM version \"" +
+ "" + m_evmVersion.name() +
+ "\" you are currently compiling for. " +
+ "It will be interpreted as an invalid instruction on this VM."
+ );
+ else if ((
_instr == solidity::Instruction::RETURNDATACOPY ||
_instr == solidity::Instruction::RETURNDATASIZE ||
_instr == solidity::Instruction::STATICCALL
diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp
index be798dc8..a4394f54 100644
--- a/test/liblll/Compiler.cpp
+++ b/test/liblll/Compiler.cpp
@@ -186,6 +186,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_functional)
"60006000600060003c",
"3d",
"6000600060003e",
+ "60003f",
"600040",
"41",
"42",
@@ -291,6 +292,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_functional)
"{ (EXTCODECOPY 0 0 0 0) }",
"{ (RETURNDATASIZE) }",
"{ (RETURNDATACOPY 0 0 0) }",
+ "{ (EXTCODEHASH 0) }",
"{ (BLOCKHASH 0) }",
"{ (COINBASE) }",
"{ (TIMESTAMP) }",
@@ -409,6 +411,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_asm)
"3c",
"3d",
"3e",
+ "3f",
"40",
"41",
"42",
@@ -547,6 +550,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_asm)
"{ (asm EXTCODECOPY) }",
"{ (asm RETURNDATASIZE) }",
"{ (asm RETURNDATACOPY) }",
+ "{ (asm EXTCODEHASH) }",
"{ (asm BLOCKHASH) }",
"{ (asm COINBASE) }",
"{ (asm TIMESTAMP) }",
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index b2e2b63b..640bf4d0 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -415,6 +415,19 @@ BOOST_AUTO_TEST_CASE(create2_as_variable)
CHECK_ALLOW_MULTI(text, expectations);
}
+BOOST_AUTO_TEST_CASE(extcodehash_as_variable)
+{
+ char const* text = R"(
+ contract c { function f() public view { uint extcodehash; extcodehash; assembly { pop(extcodehash(0)) } }}
+ )";
+ // This needs special treatment, because the message mentions the EVM version,
+ // so cannot be run via isoltest.
+ CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
+ {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"},
+ {Error::Type::Warning, "The \"extcodehash\" instruction is not supported by the VM version"},
+ }));
+}
+
BOOST_AUTO_TEST_CASE(getter_is_memory_type)
{
char const* text = R"(