mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #4676 from jwasinger/extcodehash
Add support for EXTCODEHASH
This commit is contained in:
commit
c4b5101b9d
@ -91,6 +91,7 @@ Compiler Features:
|
|||||||
* Build System: Support for Mojave version of macOS added.
|
* Build System: Support for Mojave version of macOS added.
|
||||||
* C API (``libsolc``): Export the ``solidity_license``, ``solidity_version`` and ``solidity_compile`` methods.
|
* 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: ``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: Nicer error message when trying to reference overloaded identifiers in inline assembly.
|
||||||
* Type Checker: Show named argument in case of error.
|
* Type Checker: Show named argument in case of error.
|
||||||
* Type System: IntegerType is split into IntegerType and AddressType internally.
|
* Type System: IntegerType is split into IntegerType and AddressType internally.
|
||||||
|
@ -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 |
|
| 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 |
|
| create(v, p, s) | | F | create new contract with code mem[p...(p+s)) and send v wei |
|
||||||
| | | | and return the new address |
|
| | | | and return the new address |
|
||||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||||
| create2(v, n, p, s) | | C | create new contract with code mem[p...(p+s)) at 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 |
|
| | | | keccak256(0xff . <address> . n . keccak256(mem[p...(p+s))) |
|
||||||
| | | | wei and return the new address |
|
| | | | 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)) |
|
| 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 |
|
| insize, out, outsize) | | | providing g gas and v wei and output area |
|
||||||
|
@ -114,6 +114,9 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
|
|||||||
case Instruction::EXTCODESIZE:
|
case Instruction::EXTCODESIZE:
|
||||||
gas = GasCosts::extCodeGas(m_evmVersion);
|
gas = GasCosts::extCodeGas(m_evmVersion);
|
||||||
break;
|
break;
|
||||||
|
case Instruction::EXTCODEHASH:
|
||||||
|
gas = GasCosts::balanceGas(m_evmVersion);
|
||||||
|
break;
|
||||||
case Instruction::EXTCODECOPY:
|
case Instruction::EXTCODECOPY:
|
||||||
gas = GasCosts::extCodeGas(m_evmVersion);
|
gas = GasCosts::extCodeGas(m_evmVersion);
|
||||||
gas += memoryGas(-1, -3);
|
gas += memoryGas(-1, -3);
|
||||||
|
@ -73,6 +73,7 @@ const std::map<std::string, Instruction> dev::solidity::c_instructions =
|
|||||||
{ "EXTCODECOPY", Instruction::EXTCODECOPY },
|
{ "EXTCODECOPY", Instruction::EXTCODECOPY },
|
||||||
{ "RETURNDATASIZE", Instruction::RETURNDATASIZE },
|
{ "RETURNDATASIZE", Instruction::RETURNDATASIZE },
|
||||||
{ "RETURNDATACOPY", Instruction::RETURNDATACOPY },
|
{ "RETURNDATACOPY", Instruction::RETURNDATACOPY },
|
||||||
|
{ "EXTCODEHASH", Instruction::EXTCODEHASH },
|
||||||
{ "BLOCKHASH", Instruction::BLOCKHASH },
|
{ "BLOCKHASH", Instruction::BLOCKHASH },
|
||||||
{ "COINBASE", Instruction::COINBASE },
|
{ "COINBASE", Instruction::COINBASE },
|
||||||
{ "TIMESTAMP", Instruction::TIMESTAMP },
|
{ "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::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::ExtCode } },
|
||||||
{ Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } },
|
{ Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } },
|
||||||
{ Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } },
|
{ 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::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::Ext } },
|
||||||
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } },
|
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } },
|
||||||
{ Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } },
|
{ Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } },
|
||||||
|
@ -82,6 +82,7 @@ enum class Instruction: uint8_t
|
|||||||
EXTCODECOPY, ///< copy external code (from another contract)
|
EXTCODECOPY, ///< copy external code (from another contract)
|
||||||
RETURNDATASIZE = 0x3d, ///< get size of return data buffer
|
RETURNDATASIZE = 0x3d, ///< get size of return data buffer
|
||||||
RETURNDATACOPY = 0x3e, ///< copy return data in current environment to memory
|
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
|
BLOCKHASH = 0x40, ///< get hash of most recent complete block
|
||||||
COINBASE, ///< get the block's coinbase address
|
COINBASE, ///< get the block's coinbase address
|
||||||
|
@ -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::MSIZE: // depends on previous writes and reads, not only on content
|
||||||
case Instruction::BALANCE: // depends on previous calls
|
case Instruction::BALANCE: // depends on previous calls
|
||||||
case Instruction::EXTCODESIZE:
|
case Instruction::EXTCODESIZE:
|
||||||
|
case Instruction::EXTCODEHASH:
|
||||||
case Instruction::RETURNDATACOPY: // depends on previous calls
|
case Instruction::RETURNDATACOPY: // depends on previous calls
|
||||||
case Instruction::RETURNDATASIZE:
|
case Instruction::RETURNDATASIZE:
|
||||||
return false;
|
return false;
|
||||||
@ -172,6 +173,7 @@ bool SemanticInformation::movable(Instruction _instruction)
|
|||||||
case Instruction::KECCAK256:
|
case Instruction::KECCAK256:
|
||||||
case Instruction::BALANCE:
|
case Instruction::BALANCE:
|
||||||
case Instruction::EXTCODESIZE:
|
case Instruction::EXTCODESIZE:
|
||||||
|
case Instruction::EXTCODEHASH:
|
||||||
case Instruction::RETURNDATASIZE:
|
case Instruction::RETURNDATASIZE:
|
||||||
case Instruction::SLOAD:
|
case Instruction::SLOAD:
|
||||||
case Instruction::PC:
|
case Instruction::PC:
|
||||||
@ -233,6 +235,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction)
|
|||||||
case Instruction::GASPRICE:
|
case Instruction::GASPRICE:
|
||||||
case Instruction::EXTCODESIZE:
|
case Instruction::EXTCODESIZE:
|
||||||
case Instruction::EXTCODECOPY:
|
case Instruction::EXTCODECOPY:
|
||||||
|
case Instruction::EXTCODEHASH:
|
||||||
case Instruction::BLOCKHASH:
|
case Instruction::BLOCKHASH:
|
||||||
case Instruction::COINBASE:
|
case Instruction::COINBASE:
|
||||||
case Instruction::TIMESTAMP:
|
case Instruction::TIMESTAMP:
|
||||||
|
@ -568,7 +568,17 @@ void AsmAnalyzer::warnOnInstructions(solidity::Instruction _instr, SourceLocatio
|
|||||||
// Similarly we assume bitwise shifting and create2 go together.
|
// Similarly we assume bitwise shifting and create2 go together.
|
||||||
solAssert(m_evmVersion.hasBitwiseShifting() == m_evmVersion.hasCreate2(), "");
|
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::RETURNDATACOPY ||
|
||||||
_instr == solidity::Instruction::RETURNDATASIZE ||
|
_instr == solidity::Instruction::RETURNDATASIZE ||
|
||||||
_instr == solidity::Instruction::STATICCALL
|
_instr == solidity::Instruction::STATICCALL
|
||||||
|
@ -186,6 +186,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_functional)
|
|||||||
"60006000600060003c",
|
"60006000600060003c",
|
||||||
"3d",
|
"3d",
|
||||||
"6000600060003e",
|
"6000600060003e",
|
||||||
|
"60003f",
|
||||||
"600040",
|
"600040",
|
||||||
"41",
|
"41",
|
||||||
"42",
|
"42",
|
||||||
@ -291,6 +292,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_functional)
|
|||||||
"{ (EXTCODECOPY 0 0 0 0) }",
|
"{ (EXTCODECOPY 0 0 0 0) }",
|
||||||
"{ (RETURNDATASIZE) }",
|
"{ (RETURNDATASIZE) }",
|
||||||
"{ (RETURNDATACOPY 0 0 0) }",
|
"{ (RETURNDATACOPY 0 0 0) }",
|
||||||
|
"{ (EXTCODEHASH 0) }",
|
||||||
"{ (BLOCKHASH 0) }",
|
"{ (BLOCKHASH 0) }",
|
||||||
"{ (COINBASE) }",
|
"{ (COINBASE) }",
|
||||||
"{ (TIMESTAMP) }",
|
"{ (TIMESTAMP) }",
|
||||||
@ -409,6 +411,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_asm)
|
|||||||
"3c",
|
"3c",
|
||||||
"3d",
|
"3d",
|
||||||
"3e",
|
"3e",
|
||||||
|
"3f",
|
||||||
"40",
|
"40",
|
||||||
"41",
|
"41",
|
||||||
"42",
|
"42",
|
||||||
@ -547,6 +550,7 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_asm)
|
|||||||
"{ (asm EXTCODECOPY) }",
|
"{ (asm EXTCODECOPY) }",
|
||||||
"{ (asm RETURNDATASIZE) }",
|
"{ (asm RETURNDATASIZE) }",
|
||||||
"{ (asm RETURNDATACOPY) }",
|
"{ (asm RETURNDATACOPY) }",
|
||||||
|
"{ (asm EXTCODEHASH) }",
|
||||||
"{ (asm BLOCKHASH) }",
|
"{ (asm BLOCKHASH) }",
|
||||||
"{ (asm COINBASE) }",
|
"{ (asm COINBASE) }",
|
||||||
"{ (asm TIMESTAMP) }",
|
"{ (asm TIMESTAMP) }",
|
||||||
|
@ -415,6 +415,19 @@ BOOST_AUTO_TEST_CASE(create2_as_variable)
|
|||||||
CHECK_ALLOW_MULTI(text, expectations);
|
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)
|
BOOST_AUTO_TEST_CASE(getter_is_memory_type)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
|
Loading…
Reference in New Issue
Block a user