aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libevmasm/GasMeter.cpp40
-rw-r--r--libevmasm/GasMeter.h3
2 files changed, 28 insertions, 15 deletions
diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp
index 51f3cf1d..da8b41e3 100644
--- a/libevmasm/GasMeter.cpp
+++ b/libevmasm/GasMeter.cpp
@@ -39,7 +39,7 @@ GasMeter::GasConsumption& GasMeter::GasConsumption::operator+=(GasConsumption co
return *this;
}
-GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item)
+GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _includeExternalCosts)
{
GasConsumption gas;
switch (_item.type())
@@ -128,23 +128,35 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item)
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
{
- gas = GasCosts::callGas;
- if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0)))
- gas += (*value);
- else
+ if (_includeExternalCosts)
+ // We assume that we do not know the target contract and thus, the consumption is infinite.
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)))
- gas += GasCosts::callValueTransferGas;
- gas += memoryGas(-2 - valueSize, -3 - valueSize);
- gas += memoryGas(-4 - valueSize, -5 - valueSize);
+ else
+ {
+ gas = GasCosts::callGas;
+ if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0)))
+ gas += (*value);
+ else
+ 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)))
+ gas += GasCosts::callValueTransferGas;
+ gas += memoryGas(-2 - valueSize, -3 - valueSize);
+ gas += memoryGas(-4 - valueSize, -5 - valueSize);
+ }
break;
}
case Instruction::CREATE:
- gas = GasCosts::createGas;
- gas += memoryGas(-1, -2);
+ if (_includeExternalCosts)
+ // We assume that we do not know the target contract and thus, the consumption is infinite.
+ gas = GasConsumption::infinite();
+ else
+ {
+ gas = GasCosts::createGas;
+ gas += memoryGas(-1, -2);
+ }
break;
case Instruction::EXP:
gas = GasCosts::expGas;
diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h
index 1a607a9f..ff127909 100644
--- a/libevmasm/GasMeter.h
+++ b/libevmasm/GasMeter.h
@@ -102,7 +102,8 @@ public:
/// @returns an upper bound on the gas consumed by the given instruction and updates
/// the state.
- GasConsumption estimateMax(AssemblyItem const& _item);
+ /// @param _inculdeExternalCosts if true, include costs caused by other contracts in calls.
+ GasConsumption estimateMax(AssemblyItem const& _item, bool _includeExternalCosts = true);
u256 const& largestMemoryAccess() const { return m_largestMemoryAccess; }