Skip to content

Commit

Permalink
fix(EVM): Fix panics on insufficient balance in calls (#1108)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xVolosnikov committed Dec 2, 2024
1 parent 00e662c commit 2b6f698
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 36 deletions.
64 changes: 40 additions & 24 deletions system-contracts/contracts/EvmEmulator.yul
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,12 @@ object "EvmEmulator" {
}
}

function insufficientBalance(value) -> res {
if value {
res := gt(value, selfbalance())
}
}

// It is the responsibility of the caller to ensure that ip is correct
function readIP(ip, bytecodeEndOffset) -> opcode {
if lt(ip, bytecodeEndOffset) {
Expand Down Expand Up @@ -825,12 +831,19 @@ object "EvmEmulator" {
}
}
default {
pushEvmFrame(gasToPass, isStatic)
// pass all remaining native gas
success := call(gas(), addr, value, argsOffset, argsSize, 0, 0)
frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize)
if iszero(success) {
resetEvmFrame()
switch insufficientBalance(value)
case 0 {
pushEvmFrame(gasToPass, isStatic)
// pass all remaining native gas
success := call(gas(), addr, value, argsOffset, argsSize, 0, 0)
frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize)
if iszero(success) {
resetEvmFrame()
}
}
default {
frameGasLeft := gasToPass
_eraseReturndataPointer()
}
}
}
Expand Down Expand Up @@ -1042,12 +1055,7 @@ object "EvmEmulator" {

_eraseReturndataPointer()

let err := 0
if value {
if gt(value, selfbalance()) {
err := 1
}
}
let err := insufficientBalance(value)

if iszero(err) {
offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow
Expand Down Expand Up @@ -3345,6 +3353,12 @@ object "EvmEmulator" {
}
}

function insufficientBalance(value) -> res {
if value {
res := gt(value, selfbalance())
}
}

// It is the responsibility of the caller to ensure that ip is correct
function readIP(ip, bytecodeEndOffset) -> opcode {
if lt(ip, bytecodeEndOffset) {
Expand Down Expand Up @@ -3877,12 +3891,19 @@ object "EvmEmulator" {
}
}
default {
pushEvmFrame(gasToPass, isStatic)
// pass all remaining native gas
success := call(gas(), addr, value, argsOffset, argsSize, 0, 0)
frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize)
if iszero(success) {
resetEvmFrame()
switch insufficientBalance(value)
case 0 {
pushEvmFrame(gasToPass, isStatic)
// pass all remaining native gas
success := call(gas(), addr, value, argsOffset, argsSize, 0, 0)
frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize)
if iszero(success) {
resetEvmFrame()
}
}
default {
frameGasLeft := gasToPass
_eraseReturndataPointer()
}
}
}
Expand Down Expand Up @@ -4094,12 +4115,7 @@ object "EvmEmulator" {

_eraseReturndataPointer()

let err := 0
if value {
if gt(value, selfbalance()) {
err := 1
}
}
let err := insufficientBalance(value)

if iszero(err) {
offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow
Expand Down
32 changes: 20 additions & 12 deletions system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@ function checkOverflow(data1, data2) {
}
}

function insufficientBalance(value) -> res {
if value {
res := gt(value, selfbalance())
}
}

// It is the responsibility of the caller to ensure that ip is correct
function readIP(ip, bytecodeEndOffset) -> opcode {
if lt(ip, bytecodeEndOffset) {
Expand Down Expand Up @@ -763,12 +769,19 @@ function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r
}
}
default {
pushEvmFrame(gasToPass, isStatic)
// pass all remaining native gas
success := call(gas(), addr, value, argsOffset, argsSize, 0, 0)
frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize)
if iszero(success) {
resetEvmFrame()
switch insufficientBalance(value)
case 0 {
pushEvmFrame(gasToPass, isStatic)
// pass all remaining native gas
success := call(gas(), addr, value, argsOffset, argsSize, 0, 0)
frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize)
if iszero(success) {
resetEvmFrame()
}
}
default {
frameGasLeft := gasToPass
_eraseReturndataPointer()
}
}
}
Expand Down Expand Up @@ -980,12 +993,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld,

_eraseReturndataPointer()

let err := 0
if value {
if gt(value, selfbalance()) {
err := 1
}
}
let err := insufficientBalance(value)

if iszero(err) {
offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow
Expand Down

0 comments on commit 2b6f698

Please sign in to comment.