diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | docs/assembly.rst | 6 | ||||
-rw-r--r-- | libevmasm/GasMeter.cpp | 3 | ||||
-rw-r--r-- | libevmasm/Instruction.cpp | 2 | ||||
-rw-r--r-- | libevmasm/Instruction.h | 1 | ||||
-rw-r--r-- | libevmasm/SemanticInformation.cpp | 3 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 12 | ||||
-rw-r--r-- | test/liblll/Compiler.cpp | 4 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 13 |
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"( |