Skip to content

Commit

Permalink
fix(EVM): Gas optimizations (N-04) (#1171)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xVolosnikov authored Dec 30, 2024
1 parent ba441ac commit 2947cab
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 37 deletions.
44 changes: 20 additions & 24 deletions system-contracts/contracts/EvmEmulator.yul
Original file line number Diff line number Diff line change
Expand Up @@ -258,21 +258,21 @@ object "EvmEmulator" {
let oldSizeInWords := mload(MEM_LEN_OFFSET())

// div rounding up
let newSizeInWords := div(add(newMemsize, 31), 32)
let newSizeInWords := shr(5, add(newMemsize, 31))

// memory_size_word = (memory_byte_size + 31) / 32
// memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word)
// memory_expansion_cost = new_memory_cost - last_memory_cost
if gt(newSizeInWords, oldSizeInWords) {
let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords))
let quadraticPart := sub(
div(
shr(
9,
mul(newSizeInWords, newSizeInWords),
512
),
div(
shr(
9,
mul(oldSizeInWords, oldSizeInWords),
512
)
)

Expand Down Expand Up @@ -1105,7 +1105,7 @@ object "EvmEmulator" {
// minimum_word_size = (size + 31) / 32
// init_code_cost = 2 * minimum_word_size, EIP-3860
// code_deposit_cost = 200 * deployed_code_size, (charged inside call)
let minimum_word_size := div(add(size, 31), 32) // rounding up
let minimum_word_size := shr(5, add(size, 31)) // rounding up
let dynamicGas := add(
mul(2, minimum_word_size),
expandMemory(offset, size)
Expand Down Expand Up @@ -2224,7 +2224,7 @@ object "EvmEmulator" {

// dynamic_gas = 3 * words_copied + memory_expansion_cost
let dynamicGas := expandMemory2(offset, size, destOffset, size)
let wordsCopied := div(add(size, 31), 32) // div rounding up
let wordsCopied := shr(5, add(size, 31)) // div rounding up
dynamicGas := add(dynamicGas, mul(3, wordsCopied))

evmGasLeft := chargeGas(evmGasLeft, dynamicGas)
Expand Down Expand Up @@ -2731,8 +2731,7 @@ object "EvmEmulator" {
let offset, size

popStackCheck(sp, 2)
offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
offset, sp, size := popStackItemWithoutCheck(sp, stackHead)

if size {
evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size))
Expand Down Expand Up @@ -2764,11 +2763,10 @@ object "EvmEmulator" {
ip := add(ip, 1)
}
case 0xFD { // OP_REVERT
let offset,size
let offset, size

popStackCheck(sp, 2)
offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
offset, sp, size := popStackItemWithoutCheck(sp, stackHead)

switch iszero(size)
case 0 {
Expand Down Expand Up @@ -3386,21 +3384,21 @@ object "EvmEmulator" {
let oldSizeInWords := mload(MEM_LEN_OFFSET())

// div rounding up
let newSizeInWords := div(add(newMemsize, 31), 32)
let newSizeInWords := shr(5, add(newMemsize, 31))

// memory_size_word = (memory_byte_size + 31) / 32
// memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word)
// memory_expansion_cost = new_memory_cost - last_memory_cost
if gt(newSizeInWords, oldSizeInWords) {
let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords))
let quadraticPart := sub(
div(
shr(
9,
mul(newSizeInWords, newSizeInWords),
512
),
div(
shr(
9,
mul(oldSizeInWords, oldSizeInWords),
512
)
)

Expand Down Expand Up @@ -4233,7 +4231,7 @@ object "EvmEmulator" {
// minimum_word_size = (size + 31) / 32
// init_code_cost = 2 * minimum_word_size, EIP-3860
// code_deposit_cost = 200 * deployed_code_size, (charged inside call)
let minimum_word_size := div(add(size, 31), 32) // rounding up
let minimum_word_size := shr(5, add(size, 31)) // rounding up
let dynamicGas := add(
mul(2, minimum_word_size),
expandMemory(offset, size)
Expand Down Expand Up @@ -5340,7 +5338,7 @@ object "EvmEmulator" {

// dynamic_gas = 3 * words_copied + memory_expansion_cost
let dynamicGas := expandMemory2(offset, size, destOffset, size)
let wordsCopied := div(add(size, 31), 32) // div rounding up
let wordsCopied := shr(5, add(size, 31)) // div rounding up
dynamicGas := add(dynamicGas, mul(3, wordsCopied))

evmGasLeft := chargeGas(evmGasLeft, dynamicGas)
Expand Down Expand Up @@ -5847,8 +5845,7 @@ object "EvmEmulator" {
let offset, size

popStackCheck(sp, 2)
offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
offset, sp, size := popStackItemWithoutCheck(sp, stackHead)

if size {
evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size))
Expand Down Expand Up @@ -5880,11 +5877,10 @@ object "EvmEmulator" {
ip := add(ip, 1)
}
case 0xFD { // OP_REVERT
let offset,size
let offset, size

popStackCheck(sp, 2)
offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
offset, sp, size := popStackItemWithoutCheck(sp, stackHead)

switch iszero(size)
case 0 {
Expand Down
2 changes: 1 addition & 1 deletion system-contracts/contracts/precompiles/CodeOracle.yul
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ object "CodeOracle" {
let lengthInBytes := and(shr(224, versionedCodeHash), 0xffff)
let paddedLengthInBytes := paddedBytecodeLen(lengthInBytes)

decommit(versionedCodeHash, div(paddedLengthInBytes, 32))
decommit(versionedCodeHash, shr(5, paddedLengthInBytes))
}
default {
// Unsupported
Expand Down
12 changes: 6 additions & 6 deletions system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul
Original file line number Diff line number Diff line change
Expand Up @@ -198,21 +198,21 @@ function _expandMemoryInternal(newMemsize) -> gasCost {
let oldSizeInWords := mload(MEM_LEN_OFFSET())

// div rounding up
let newSizeInWords := div(add(newMemsize, 31), 32)
let newSizeInWords := shr(5, add(newMemsize, 31))

// memory_size_word = (memory_byte_size + 31) / 32
// memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word)
// memory_expansion_cost = new_memory_cost - last_memory_cost
if gt(newSizeInWords, oldSizeInWords) {
let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords))
let quadraticPart := sub(
div(
shr(
9,
mul(newSizeInWords, newSizeInWords),
512
),
div(
shr(
9,
mul(oldSizeInWords, oldSizeInWords),
512
)
)

Expand Down Expand Up @@ -1045,7 +1045,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld,
// minimum_word_size = (size + 31) / 32
// init_code_cost = 2 * minimum_word_size, EIP-3860
// code_deposit_cost = 200 * deployed_code_size, (charged inside call)
let minimum_word_size := div(add(size, 31), 32) // rounding up
let minimum_word_size := shr(5, add(size, 31)) // rounding up
let dynamicGas := add(
mul(2, minimum_word_size),
expandMemory(offset, size)
Expand Down
10 changes: 4 additions & 6 deletions system-contracts/evm-emulator/EvmEmulatorLoop.template.yul
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@ for { } true { } {

// dynamic_gas = 3 * words_copied + memory_expansion_cost
let dynamicGas := expandMemory2(offset, size, destOffset, size)
let wordsCopied := div(add(size, 31), 32) // div rounding up
let wordsCopied := shr(5, add(size, 31)) // div rounding up
dynamicGas := add(dynamicGas, mul(3, wordsCopied))

evmGasLeft := chargeGas(evmGasLeft, dynamicGas)
Expand Down Expand Up @@ -1394,8 +1394,7 @@ for { } true { } {
let offset, size

popStackCheck(sp, 2)
offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
offset, sp, size := popStackItemWithoutCheck(sp, stackHead)

if size {
evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size))
Expand Down Expand Up @@ -1427,11 +1426,10 @@ for { } true { } {
ip := add(ip, 1)
}
case 0xFD { // OP_REVERT
let offset,size
let offset, size

popStackCheck(sp, 2)
offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
offset, sp, size := popStackItemWithoutCheck(sp, stackHead)

switch iszero(size)
case 0 {
Expand Down

0 comments on commit 2947cab

Please sign in to comment.