diff options
Diffstat (limited to 'libevmasm')
-rw-r--r-- | libevmasm/Assembly.cpp | 19 | ||||
-rw-r--r-- | libevmasm/Assembly.h | 11 | ||||
-rw-r--r-- | libevmasm/GasMeter.cpp | 7 | ||||
-rw-r--r-- | libevmasm/Instruction.cpp | 2 | ||||
-rw-r--r-- | libevmasm/Instruction.h | 7 | ||||
-rw-r--r-- | libevmasm/SemanticInformation.cpp | 2 |
6 files changed, 30 insertions, 18 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ea061a30..92a4c2a4 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -40,7 +40,7 @@ void Assembly::append(Assembly const& _a) auto newDeposit = m_deposit + _a.deposit(); for (AssemblyItem i: _a.m_items) { - if (i.type() == Tag || (i.type() == PushTag && i != errorTag())) + if (i.type() == Tag || i.type() == PushTag) i.setData(i.data() + m_usedTags); else if (i.type() == PushSub || i.type() == PushSubSize) i.setData(i.data() + m_subs.size()); @@ -72,13 +72,6 @@ void Assembly::append(Assembly const& _a, int _deposit) } } -string Assembly::out() const -{ - stringstream ret; - stream(ret); - return ret.str(); -} - unsigned Assembly::bytesRequired(unsigned subTagSize) const { for (unsigned tagSize = subTagSize; true; ++tagSize) @@ -216,6 +209,9 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con } } + if (m_auxiliaryData.size() > 0) + _out << endl << _prefix << "auxdata: 0x" << toHex(m_auxiliaryData) << endl; + return _out; } @@ -315,8 +311,13 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes data[hexStr.str()] = m_subs[i]->stream(_out, "", _sourceCodes, true); } root[".data"] = data; - _out << root; } + + if (m_auxiliaryData.size() > 0) + root[".auxdata"] = toHex(m_auxiliaryData); + + _out << root; + return root; } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 528c9e74..13d82e1a 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -69,7 +69,13 @@ public: AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(solidity::Instruction::JUMPI); return ret; } AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(solidity::Instruction::JUMP); return ret; } AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(solidity::Instruction::JUMPI); return ret; } - AssemblyItem errorTag() { return AssemblyItem(PushTag, 0); } + + /// Adds a subroutine to the code (in the data section) and pushes its size (via a tag) + /// on the stack. @returns the pushsub assembly item. + AssemblyItem appendSubroutine(AssemblyPointer const& _assembly) { auto sub = newSub(_assembly); append(newPushSubSize(size_t(sub.data()))); return sub; } + void pushSubroutineSize(size_t _subRoutine) { append(newPushSubSize(_subRoutine)); } + /// Pushes the offset of the subroutine. + void pushSubroutineOffset(size_t _subRoutine) { append(AssemblyItem(PushSub, _subRoutine)); } /// Appends @a _data literally to the very end of the bytecode. void appendAuxiliaryDataToEnd(bytes const& _data) { m_auxiliaryData += _data; } @@ -85,10 +91,7 @@ public: void ignored() { m_baseDeposit = m_deposit; } void endIgnored() { m_deposit = m_baseDeposit; m_baseDeposit = 0; } - void popTo(int _deposit) { while (m_deposit > _deposit) append(solidity::Instruction::POP); } - void injectStart(AssemblyItem const& _i); - std::string out() const; int deposit() const { return m_deposit; } void adjustDeposit(int _adjustment) { m_deposit += _adjustment; if (asserts(m_deposit >= 0)) BOOST_THROW_EXCEPTION(InvalidDeposit()); } void setDeposit(int _deposit) { m_deposit = _deposit; if (asserts(m_deposit >= 0)) BOOST_THROW_EXCEPTION(InvalidDeposit()); } diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index c2e4f01d..c96c6ca5 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -129,6 +129,7 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _ case Instruction::CALL: case Instruction::CALLCODE: case Instruction::DELEGATECALL: + case Instruction::STATICCALL: { if (_includeExternalCosts) // We assume that we do not know the target contract and thus, the consumption is infinite. @@ -142,8 +143,10 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _ gas = GasConsumption::infinite(); if (_item.instruction() == Instruction::CALL) gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists. - int valueSize = _item.instruction() == Instruction::DELEGATECALL ? 0 : 1; - if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize))) + int valueSize = 1; + if (_item.instruction() == Instruction::DELEGATECALL || _item.instruction() == Instruction::STATICCALL) + valueSize = 0; + else if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize))) gas += GasCosts::callValueTransferGas; gas += memoryGas(-2 - valueSize, -3 - valueSize); gas += memoryGas(-4 - valueSize, -5 - valueSize); diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index d58a47a0..8feb733a 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -159,6 +159,7 @@ const std::map<std::string, Instruction> dev::solidity::c_instructions = { "CREATE", Instruction::CREATE }, { "CALL", Instruction::CALL }, { "CALLCODE", Instruction::CALLCODE }, + { "STATICCALL", Instruction::STATICCALL }, { "RETURN", Instruction::RETURN }, { "DELEGATECALL", Instruction::DELEGATECALL }, { "CREATE2", Instruction::CREATE2 }, @@ -300,6 +301,7 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo = { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } }, { Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } }, { Instruction::DELEGATECALL, { "DELEGATECALL", 0, 6, 1, true, Tier::Special } }, + { Instruction::STATICCALL, { "STATICCALL", 0, 6, 1, true, Tier::Special } }, { Instruction::CREATE2, { "CREATE2", 0, 4, 1, true, Tier::Special } }, { Instruction::REVERT, { "REVERT", 0, 2, 0, true, Tier::Zero } }, { Instruction::INVALID, { "INVALID", 0, 0, 0, true, Tier::Zero } }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 37cdccdb..89a25fb7 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -77,8 +77,8 @@ enum class Instruction: uint8_t GASPRICE, ///< get price of gas in current environment EXTCODESIZE, ///< get external code size (from another contract) EXTCODECOPY, ///< copy external code (from another contract) - RETURNDATASIZE, ///< get size of the last return data - RETURNDATACOPY, ///< copy last return data to memory + RETURNDATASIZE = 0x3d, ///< get size of return data buffer + RETURNDATACOPY = 0x3e, ///< copy return data in current environment to memory BLOCKHASH = 0x40, ///< get hash of most recent complete block COINBASE, ///< get the block's coinbase address @@ -187,7 +187,8 @@ enum class Instruction: uint8_t CALLCODE, ///< message-call with another account's code only RETURN, ///< halt execution returning output data DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender - CREATE2 = 0xfb, ///< create new account with associated code + STATICCALL = 0xfa, ///< like CALL but disallow state modifications + CREATE2 = 0xfb, ///< create new account with associated code at address `sha3(sender + salt + sha3(init code)) % 2**160` REVERT = 0xfd, ///< halt execution, revert state and return output data INVALID = 0xfe, ///< invalid instruction for expressing runtime errors (e.g., division-by-zero) diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index db4ee867..f63f0c61 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -137,6 +137,7 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item) case Instruction::CALL: case Instruction::CALLCODE: case Instruction::DELEGATECALL: + case Instruction::STATICCALL: case Instruction::CREATE: case Instruction::CREATE2: case Instruction::GAS: @@ -165,6 +166,7 @@ bool SemanticInformation::invalidatesMemory(Instruction _instruction) case Instruction::CALL: case Instruction::CALLCODE: case Instruction::DELEGATECALL: + case Instruction::STATICCALL: return true; default: return false; |