mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add new gas price for deployed bytecode (EIP2028)
This commit is contained in:
parent
21312f52f2
commit
840aba8929
@ -96,7 +96,7 @@ bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items)
|
|||||||
bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const
|
bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const
|
||||||
{
|
{
|
||||||
assertThrow(_data.size() > 0, OptimizerException, "Empty bytecode generated.");
|
assertThrow(_data.size() > 0, OptimizerException, "Empty bytecode generated.");
|
||||||
return bigint(GasMeter::dataGas(_data, m_params.isCreation));
|
return bigint(GasMeter::dataGas(_data, m_params.isCreation, m_params.evmVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items)
|
size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items)
|
||||||
@ -131,7 +131,7 @@ bigint LiteralMethod::gasNeeded() const
|
|||||||
return combineGas(
|
return combineGas(
|
||||||
simpleRunGas({Instruction::PUSH1}),
|
simpleRunGas({Instruction::PUSH1}),
|
||||||
// PUSHX plus data
|
// PUSHX plus data
|
||||||
(m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas) + dataGas(toCompactBigEndian(m_value, 1)),
|
(m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas) + dataGas(toCompactBigEndian(m_value, 1)),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@ bigint CodeCopyMethod::gasNeeded() const
|
|||||||
// Run gas: we ignore memory increase costs
|
// Run gas: we ignore memory increase costs
|
||||||
simpleRunGas(copyRoutine()) + GasCosts::copyGas,
|
simpleRunGas(copyRoutine()) + GasCosts::copyGas,
|
||||||
// Data gas for copy routines: Some bytes are zero, but we ignore them.
|
// Data gas for copy routines: Some bytes are zero, but we ignore them.
|
||||||
bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas),
|
bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas),
|
||||||
// Data gas for data itself
|
// Data gas for data itself
|
||||||
dataGas(toBigEndian(m_value))
|
dataGas(toBigEndian(m_value))
|
||||||
);
|
);
|
||||||
@ -322,7 +322,7 @@ bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine) const
|
|||||||
return combineGas(
|
return combineGas(
|
||||||
simpleRunGas(_routine) + numExps * (GasCosts::expGas + GasCosts::expByteGas(m_params.evmVersion)),
|
simpleRunGas(_routine) + numExps * (GasCosts::expGas + GasCosts::expByteGas(m_params.evmVersion)),
|
||||||
// Data gas for routine: Some bytes are zero, but we ignore them.
|
// Data gas for routine: Some bytes are zero, but we ignore them.
|
||||||
bytesRequired(_routine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas),
|
bytesRequired(_routine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -266,13 +266,13 @@ unsigned GasMeter::runGas(Instruction _instruction)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u256 GasMeter::dataGas(bytes const& _data, bool _inCreation)
|
u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersion _evmVersion)
|
||||||
{
|
{
|
||||||
bigint gas = 0;
|
bigint gas = 0;
|
||||||
if (_inCreation)
|
if (_inCreation)
|
||||||
{
|
{
|
||||||
for (auto b: _data)
|
for (auto b: _data)
|
||||||
gas += (b != 0) ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas;
|
gas += (b != 0) ? GasCosts::txDataNonZeroGas(_evmVersion) : GasCosts::txDataZeroGas;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gas = bigint(GasCosts::createDataGas) * _data.size();
|
gas = bigint(GasCosts::createDataGas) * _data.size();
|
||||||
|
@ -102,7 +102,10 @@ namespace GasCosts
|
|||||||
static unsigned const txGas = 21000;
|
static unsigned const txGas = 21000;
|
||||||
static unsigned const txCreateGas = 53000;
|
static unsigned const txCreateGas = 53000;
|
||||||
static unsigned const txDataZeroGas = 4;
|
static unsigned const txDataZeroGas = 4;
|
||||||
static unsigned const txDataNonZeroGas = 68;
|
inline unsigned txDataNonZeroGas(langutil::EVMVersion _evmVersion)
|
||||||
|
{
|
||||||
|
return _evmVersion >= langutil::EVMVersion::istanbul() ? 16 : 68;
|
||||||
|
}
|
||||||
static unsigned const copyGas = 3;
|
static unsigned const copyGas = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +152,7 @@ public:
|
|||||||
/// @returns the gas cost of the supplied data, depending whether it is in creation code, or not.
|
/// @returns the gas cost of the supplied data, depending whether it is in creation code, or not.
|
||||||
/// In case of @a _inCreation, the data is only sent as a transaction and is not stored, whereas
|
/// In case of @a _inCreation, the data is only sent as a transaction and is not stored, whereas
|
||||||
/// otherwise code will be stored and have to pay "createDataGas" cost.
|
/// otherwise code will be stored and have to pay "createDataGas" cost.
|
||||||
static u256 dataGas(bytes const& _data, bool _inCreation);
|
static u256 dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersion _evmVersion);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @returns _multiplier * (_value + 31) / 32, if _value is a known constant and infinite otherwise.
|
/// @returns _multiplier * (_value + 31) / 32, if _value is a known constant and infinite otherwise.
|
||||||
|
@ -1410,7 +1410,7 @@ Json::Value CompilerStack::gasEstimates(string const& _contractName) const
|
|||||||
if (eth::AssemblyItems const* items = assemblyItems(_contractName))
|
if (eth::AssemblyItems const* items = assemblyItems(_contractName))
|
||||||
{
|
{
|
||||||
Gas executionGas = gasEstimator.functionalEstimation(*items);
|
Gas executionGas = gasEstimator.functionalEstimation(*items);
|
||||||
Gas codeDepositGas{eth::GasMeter::dataGas(runtimeObject(_contractName).bytecode, false)};
|
Gas codeDepositGas{eth::GasMeter::dataGas(runtimeObject(_contractName).bytecode, false, m_evmVersion)};
|
||||||
|
|
||||||
Json::Value creation(Json::objectValue);
|
Json::Value creation(Json::objectValue);
|
||||||
creation["codeDepositCost"] = gasToJson(codeDepositGas);
|
creation["codeDepositCost"] = gasToJson(codeDepositGas);
|
||||||
|
@ -96,7 +96,7 @@ void GasMeterVisitor::operator()(Literal const& _lit)
|
|||||||
m_runGas += dev::eth::GasMeter::runGas(dev::eth::Instruction::PUSH1);
|
m_runGas += dev::eth::GasMeter::runGas(dev::eth::Instruction::PUSH1);
|
||||||
m_dataGas +=
|
m_dataGas +=
|
||||||
singleByteDataGas() +
|
singleByteDataGas() +
|
||||||
size_t(dev::eth::GasMeter::dataGas(dev::toCompactBigEndian(valueOfLiteral(_lit), 1), m_isCreation));
|
size_t(dev::eth::GasMeter::dataGas(dev::toCompactBigEndian(valueOfLiteral(_lit), 1), m_isCreation, m_dialect.evmVersion()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GasMeterVisitor::operator()(Identifier const&)
|
void GasMeterVisitor::operator()(Identifier const&)
|
||||||
@ -108,7 +108,7 @@ void GasMeterVisitor::operator()(Identifier const&)
|
|||||||
size_t GasMeterVisitor::singleByteDataGas() const
|
size_t GasMeterVisitor::singleByteDataGas() const
|
||||||
{
|
{
|
||||||
if (m_isCreation)
|
if (m_isCreation)
|
||||||
return dev::eth::GasCosts::txDataNonZeroGas;
|
return dev::eth::GasCosts::txDataNonZeroGas(m_dialect.evmVersion());
|
||||||
else
|
else
|
||||||
return dev::eth::GasCosts::createDataGas;
|
return dev::eth::GasCosts::createDataGas;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,8 @@ evmc::VM* EVMHost::getVM(string const& _path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM* _vm):
|
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM* _vm):
|
||||||
m_vm(_vm)
|
m_vm(_vm),
|
||||||
|
m_evmVersion(_evmVersion)
|
||||||
{
|
{
|
||||||
if (!m_vm)
|
if (!m_vm)
|
||||||
{
|
{
|
||||||
@ -73,21 +74,21 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM* _vm):
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_evmVersion == langutil::EVMVersion::homestead())
|
if (_evmVersion == langutil::EVMVersion::homestead())
|
||||||
m_evmVersion = EVMC_HOMESTEAD;
|
m_evmRevision = EVMC_HOMESTEAD;
|
||||||
else if (_evmVersion == langutil::EVMVersion::tangerineWhistle())
|
else if (_evmVersion == langutil::EVMVersion::tangerineWhistle())
|
||||||
m_evmVersion = EVMC_TANGERINE_WHISTLE;
|
m_evmRevision = EVMC_TANGERINE_WHISTLE;
|
||||||
else if (_evmVersion == langutil::EVMVersion::spuriousDragon())
|
else if (_evmVersion == langutil::EVMVersion::spuriousDragon())
|
||||||
m_evmVersion = EVMC_SPURIOUS_DRAGON;
|
m_evmRevision = EVMC_SPURIOUS_DRAGON;
|
||||||
else if (_evmVersion == langutil::EVMVersion::byzantium())
|
else if (_evmVersion == langutil::EVMVersion::byzantium())
|
||||||
m_evmVersion = EVMC_BYZANTIUM;
|
m_evmRevision = EVMC_BYZANTIUM;
|
||||||
else if (_evmVersion == langutil::EVMVersion::constantinople())
|
else if (_evmVersion == langutil::EVMVersion::constantinople())
|
||||||
m_evmVersion = EVMC_CONSTANTINOPLE;
|
m_evmRevision = EVMC_CONSTANTINOPLE;
|
||||||
else if (_evmVersion == langutil::EVMVersion::istanbul())
|
else if (_evmVersion == langutil::EVMVersion::istanbul())
|
||||||
m_evmVersion = EVMC_ISTANBUL;
|
m_evmRevision = EVMC_ISTANBUL;
|
||||||
else if (_evmVersion == langutil::EVMVersion::berlin())
|
else if (_evmVersion == langutil::EVMVersion::berlin())
|
||||||
assertThrow(false, Exception, "Berlin is not supported yet.");
|
assertThrow(false, Exception, "Berlin is not supported yet.");
|
||||||
else //if (_evmVersion == langutil::EVMVersion::petersburg())
|
else //if (_evmVersion == langutil::EVMVersion::petersburg())
|
||||||
m_evmVersion = EVMC_PETERSBURG;
|
m_evmRevision = EVMC_PETERSBURG;
|
||||||
}
|
}
|
||||||
|
|
||||||
evmc_storage_status EVMHost::set_storage(const evmc::address& _addr, const evmc::bytes32& _key, const evmc::bytes32& _value) noexcept
|
evmc_storage_status EVMHost::set_storage(const evmc::address& _addr, const evmc::bytes32& _key, const evmc::bytes32& _value) noexcept
|
||||||
@ -146,7 +147,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
|
|||||||
{
|
{
|
||||||
message.gas -= message.kind == EVMC_CREATE ? eth::GasCosts::txCreateGas : eth::GasCosts::txGas;
|
message.gas -= message.kind == EVMC_CREATE ? eth::GasCosts::txCreateGas : eth::GasCosts::txGas;
|
||||||
for (size_t i = 0; i < message.input_size; ++i)
|
for (size_t i = 0; i < message.input_size; ++i)
|
||||||
message.gas -= message.input_data[i] == 0 ? eth::GasCosts::txDataZeroGas : eth::GasCosts::txDataNonZeroGas;
|
message.gas -= message.input_data[i] == 0 ? eth::GasCosts::txDataZeroGas : eth::GasCosts::txDataNonZeroGas(m_evmVersion);
|
||||||
if (message.gas < 0)
|
if (message.gas < 0)
|
||||||
{
|
{
|
||||||
evmc::result result({});
|
evmc::result result({});
|
||||||
@ -191,7 +192,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
|
|||||||
|
|
||||||
evmc::address currentAddress = m_currentAddress;
|
evmc::address currentAddress = m_currentAddress;
|
||||||
m_currentAddress = message.destination;
|
m_currentAddress = message.destination;
|
||||||
evmc::result result = m_vm->execute(*this, m_evmVersion, message, code.data(), code.size());
|
evmc::result result = m_vm->execute(*this, m_evmRevision, message, code.data(), code.size());
|
||||||
m_currentAddress = currentAddress;
|
m_currentAddress = currentAddress;
|
||||||
|
|
||||||
if (message.kind == EVMC_CREATE)
|
if (message.kind == EVMC_CREATE)
|
||||||
|
@ -180,7 +180,10 @@ private:
|
|||||||
static evmc::result resultWithGas(evmc_message const& _message, bytes const& _data) noexcept;
|
static evmc::result resultWithGas(evmc_message const& _message, bytes const& _data) noexcept;
|
||||||
|
|
||||||
evmc::VM* m_vm = nullptr;
|
evmc::VM* m_vm = nullptr;
|
||||||
evmc_revision m_evmVersion;
|
// EVM version requested by the testing tool
|
||||||
|
langutil::EVMVersion m_evmVersion;
|
||||||
|
// EVM version requested from EVMC (matches the above)
|
||||||
|
evmc_revision m_evmRevision;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <test/libsolidity/SolidityExecutionFramework.h>
|
#include <test/libsolidity/SolidityExecutionFramework.h>
|
||||||
|
#include <liblangutil/EVMVersion.h>
|
||||||
#include <libdevcore/SwarmHash.h>
|
#include <libdevcore/SwarmHash.h>
|
||||||
#include <libevmasm/GasMeter.h>
|
#include <libevmasm/GasMeter.h>
|
||||||
|
|
||||||
@ -37,10 +38,10 @@ namespace solidity
|
|||||||
namespace test
|
namespace test
|
||||||
{
|
{
|
||||||
|
|
||||||
#define CHECK_DEPLOY_GAS(_gasNoOpt, _gasOpt) \
|
#define CHECK_DEPLOY_GAS(_gasNoOpt, _gasOpt, _evmVersion) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
u256 bzzr1Cost = GasMeter::dataGas(dev::bzzr1Hash(m_compiler.metadata(m_compiler.lastContractName())).asBytes(), true); \
|
u256 bzzr1Cost = GasMeter::dataGas(dev::bzzr1Hash(m_compiler.metadata(m_compiler.lastContractName())).asBytes(), true, _evmVersion); \
|
||||||
u256 gasOpt{_gasOpt}; \
|
u256 gasOpt{_gasOpt}; \
|
||||||
u256 gasNoOpt{_gasNoOpt}; \
|
u256 gasNoOpt{_gasNoOpt}; \
|
||||||
u256 gas = m_optimiserSettings == OptimiserSettings::minimal() ? gasNoOpt : gasOpt; \
|
u256 gas = m_optimiserSettings == OptimiserSettings::minimal() ? gasNoOpt : gasOpt; \
|
||||||
@ -95,22 +96,25 @@ BOOST_AUTO_TEST_CASE(string_storage)
|
|||||||
m_compiler.overwriteReleaseFlag(true);
|
m_compiler.overwriteReleaseFlag(true);
|
||||||
compileAndRun(sourceCode);
|
compileAndRun(sourceCode);
|
||||||
|
|
||||||
if (Options::get().evmVersion() <= EVMVersion::byzantium())
|
auto evmVersion = dev::test::Options::get().evmVersion();
|
||||||
CHECK_DEPLOY_GAS(134071, 130763);
|
|
||||||
|
if (evmVersion <= EVMVersion::byzantium())
|
||||||
|
CHECK_DEPLOY_GAS(134071, 130763, evmVersion);
|
||||||
// This is only correct on >=Constantinople.
|
// This is only correct on >=Constantinople.
|
||||||
else if (Options::get().useABIEncoderV2)
|
else if (Options::get().useABIEncoderV2)
|
||||||
{
|
{
|
||||||
if (Options::get().optimizeYul)
|
if (Options::get().optimizeYul)
|
||||||
CHECK_DEPLOY_GAS(151455, 127653);
|
CHECK_DEPLOY_GAS(151455, 127653, evmVersion);
|
||||||
else
|
else
|
||||||
CHECK_DEPLOY_GAS(151455, 135371);
|
CHECK_DEPLOY_GAS(151455, 135371, evmVersion);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CHECK_DEPLOY_GAS(126861, 119591);
|
CHECK_DEPLOY_GAS(126861, 119591, evmVersion);
|
||||||
if (Options::get().evmVersion() >= EVMVersion::byzantium())
|
|
||||||
|
if (evmVersion >= EVMVersion::byzantium())
|
||||||
{
|
{
|
||||||
callContractFunction("f()");
|
callContractFunction("f()");
|
||||||
if (Options::get().evmVersion() == EVMVersion::byzantium())
|
if (evmVersion == EVMVersion::byzantium())
|
||||||
CHECK_GAS(21551, 21526, 20);
|
CHECK_GAS(21551, 21526, 20);
|
||||||
// This is only correct on >=Constantinople.
|
// This is only correct on >=Constantinople.
|
||||||
else if (Options::get().useABIEncoderV2)
|
else if (Options::get().useABIEncoderV2)
|
||||||
|
@ -114,9 +114,10 @@ public:
|
|||||||
|
|
||||||
static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation)
|
static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation)
|
||||||
{
|
{
|
||||||
|
auto evmVersion = dev::test::Options::get().evmVersion();
|
||||||
GasMeter::GasConsumption gas = _isCreation ? GasCosts::txCreateGas : GasCosts::txGas;
|
GasMeter::GasConsumption gas = _isCreation ? GasCosts::txCreateGas : GasCosts::txGas;
|
||||||
for (auto i: _data)
|
for (auto i: _data)
|
||||||
gas += i != 0 ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas;
|
gas += i != 0 ? GasCosts::txDataNonZeroGas(evmVersion) : GasCosts::txDataZeroGas;
|
||||||
return gas;
|
return gas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user