@@ -263,12 +263,11 @@ GasMeter::GasConsumption GasMeter::memoryGas(int _stackPosOffset, int _stackPosS
263263 }));
264264}
265265
266- unsigned GasMeter::runGas (Instruction _instruction, langutil::EVMVersion _evmVersion)
266+ namespace
267267{
268- if (_instruction == Instruction::JUMPDEST)
269- return 1 ;
270-
271- switch (instructionInfo (_instruction, _evmVersion).gasPriceTier )
268+ std::optional<unsigned > gasCostForTier (Tier _tier)
269+ {
270+ switch (_tier)
272271 {
273272 case Tier::Zero: return GasCosts::tier0Gas;
274273 case Tier::Base: return GasCosts::tier1Gas;
@@ -286,10 +285,21 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer
286285
287286 case Tier::Special:
288287 case Tier::Invalid:
289- assertThrow ( false , OptimizerException, " Invalid gas tier for instruction " + instructionInfo (_instruction, _evmVersion). name ) ;
288+ return std:: nullopt ;
290289 }
291290 util::unreachable ();
292291}
292+ }
293+
294+ unsigned GasMeter::runGas (Instruction _instruction, langutil::EVMVersion _evmVersion)
295+ {
296+ if (_instruction == Instruction::JUMPDEST)
297+ return 1 ;
298+
299+ if (auto gasCost = gasCostForTier (instructionInfo (_instruction, _evmVersion).gasPriceTier ))
300+ return *gasCost;
301+ assertThrow (false , OptimizerException, " Invalid gas tier for instruction " + instructionInfo (_instruction, _evmVersion).name );
302+ }
293303
294304unsigned GasMeter::pushGas (u256 _value, langutil::EVMVersion _evmVersion)
295305{
@@ -299,14 +309,22 @@ unsigned GasMeter::pushGas(u256 _value, langutil::EVMVersion _evmVersion)
299309 );
300310}
301311
302- unsigned GasMeter::swapGas (size_t )
312+ unsigned GasMeter::swapGas (size_t _depth, langutil::EVMVersion _evmVersion )
303313{
304- return 3 ;
314+ if (_depth <= 16 )
315+ return runGas (evmasm::swapInstruction (static_cast <unsigned >(_depth)), _evmVersion);
316+ auto gasCost = gasCostForTier (instructionInfo (evmasm::Instruction::SWAPN, _evmVersion).gasPriceTier );
317+ assertThrow (gasCost.has_value (), OptimizerException, " Expected gas cost for SWAPN to be defined." );
318+ return *gasCost;
305319}
306320
307- unsigned GasMeter::dupGas (size_t )
321+ unsigned GasMeter::dupGas (size_t _depth, langutil::EVMVersion _evmVersion )
308322{
309- return 3 ;
323+ if (_depth <= 16 )
324+ return runGas (evmasm::swapInstruction (static_cast <unsigned >(_depth)), _evmVersion);
325+ auto gasCost = gasCostForTier (instructionInfo (evmasm::Instruction::DUPN, _evmVersion).gasPriceTier );
326+ assertThrow (gasCost.has_value (), OptimizerException, " Expected gas cost for DUPN to be defined." );
327+ return *gasCost;
310328}
311329
312330u256 GasMeter::dataGas (bytes const & _data, bool _inCreation, langutil::EVMVersion _evmVersion)
0 commit comments