Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 12 additions & 16 deletions src/compiler/evm_frontend/evm_imported.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,8 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
}

uint64_t CallGas = Gas;
bool HasEnoughBalance = true;

if (HasValueArgs) {
std::optional<bool> AccountState;
uint64_t GasCost = HasValue ? zen::evm::CALL_VALUE_COST : 0;
Expand All @@ -896,22 +898,16 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
Instance, zen::common::ErrorCode::GasLimitExceeded);
}

if (HasValueArgs) {
bool HasEnoughBalance = true;
if (HasValue) {
Instance->addGas(zen::evm::CALL_GAS_STIPEND);
CallGas += zen::evm::CALL_GAS_STIPEND;

const auto CallerBalance =
Module->Host->get_balance(CurrentMsg->recipient);
const intx::uint256 CallerValue =
intx::be::load<intx::uint256>(CallerBalance);
HasEnoughBalance = CallerValue >= intx::uint256(Value);

if (!HasEnoughBalance) {
Instance->setReturnData({});
return 0;
}
if (HasValueArgs && HasValue) {
CallGas += zen::evm::CALL_GAS_STIPEND;
Instance->addGas(zen::evm::CALL_GAS_STIPEND);
const auto CallerBalance = Module->Host->get_balance(CurrentMsg->recipient);
const intx::uint256 CallerValue =
intx::be::load<intx::uint256>(CallerBalance);
HasEnoughBalance = CallerValue >= intx::uint256(Value);
if (!HasEnoughBalance) {
Instance->setReturnData({});
return 0;
}
}

Expand Down
43 changes: 29 additions & 14 deletions src/tests/evm_precompiles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,33 @@ inline uint64_t adjustedExponentLength(uint64_t ExpLen,
inline boost::multiprecision::cpp_int
multComplexityEIP198(uint64_t MaxLen) noexcept {
using boost::multiprecision::cpp_int;
const cpp_int X(MaxLen);
using cpp_int_et_off = boost::multiprecision::number<
boost::multiprecision::cpp_int_backend<>, boost::multiprecision::et_off>;
const cpp_int_et_off X(MaxLen);
cpp_int_et_off Result = X * X;
if (MaxLen <= 64) {
return X * X;
return cpp_int(Result);
}
if (MaxLen <= 1024) {
return X * X / 4 + cpp_int(96) * MaxLen - 3072;
}
return X * X / 16 + cpp_int(480) * MaxLen - 199680;
Result /= 4;
Result += cpp_int_et_off(96) * MaxLen;
Result -= 3072;
return cpp_int(Result);
}
Result /= 16;
Result += cpp_int_et_off(480) * MaxLen;
Result -= 199680;
return cpp_int(Result);
}

inline boost::multiprecision::cpp_int
multComplexityEIP2565(uint64_t MaxLen) noexcept {
using boost::multiprecision::cpp_int;
using cpp_int_et_off = boost::multiprecision::number<
boost::multiprecision::cpp_int_backend<>, boost::multiprecision::et_off>;
const uint64_t Words = (MaxLen + 7) / 8;
const cpp_int W(Words);
return W * W;
const cpp_int_et_off W(Words);
return cpp_int(W * W);
}

inline bool toUint64(const boost::multiprecision::cpp_int &Value,
Expand Down Expand Up @@ -309,21 +320,25 @@ inline evmc::Result executeModExp(const evmc_message &Msg,
const uint64_t IterationCount = std::max<uint64_t>(AdjustedExpLen, 1);

using boost::multiprecision::cpp_int;
cpp_int GasCost = 0;
using cpp_int_et_off = boost::multiprecision::number<
boost::multiprecision::cpp_int_backend<>, boost::multiprecision::et_off>;
cpp_int_et_off GasCost = 0;
if (Revision >= EVMC_BERLIN) {
GasCost =
multComplexityEIP2565(MaxLen) * cpp_int(IterationCount) / cpp_int(3);
GasCost = cpp_int_et_off(multComplexityEIP2565(MaxLen));
GasCost *= cpp_int_et_off(IterationCount);
GasCost /= cpp_int_et_off(3);
if (GasCost < 200) {
GasCost = 200;
}
} else {
GasCost =
multComplexityEIP198(MaxLen) * cpp_int(IterationCount) / cpp_int(20);
GasCost += cpp_int(LegacyModExpBaseGas);
GasCost = cpp_int_et_off(multComplexityEIP198(MaxLen));
GasCost *= cpp_int_et_off(IterationCount);
GasCost /= cpp_int_et_off(20);
GasCost += cpp_int_et_off(LegacyModExpBaseGas);
}

uint64_t GasCost64 = 0;
if (!toUint64(GasCost, GasCost64)) {
if (!toUint64(cpp_int(GasCost), GasCost64)) {
return evmc::Result(EVMC_OUT_OF_GAS, 0, 0, nullptr, 0);
}

Expand Down
7 changes: 7 additions & 0 deletions src/tests/evm_test_host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class ZenMockedEVMHost : public evmc::MockedHost {
PrewarmStorageKeys;
std::unordered_set<evmc::address> CreatedInTx;
std::unordered_set<evmc::address> PendingSelfdestructs;
uint64_t CallStipendRefund = 0; // track CALL stipend refunds for prepaid fees
bool FeesPrepaidInTx = false;

public:
Expand Down Expand Up @@ -477,6 +478,12 @@ class ZenMockedEVMHost : public evmc::MockedHost {
ParentResult.gas_left == 0) {
ParentResult.gas_left = Msg.gas;
}
if (FeesPrepaidInTx && Msg.kind == EVMC_CALL &&
toUint256Bytes(Msg.value) != intx::uint256{0} &&
ParentResult.status_code == EVMC_SUCCESS &&
ParentResult.gas_left < Msg.gas) {
this->CallStipendRefund += CALL_GAS_STIPEND;
}
return ParentResult;
}

Expand Down
2 changes: 2 additions & 0 deletions src/tests/solidity_contract_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ GTEST_API_ int main(int argc, char **argv) {
uint64_t GasLimit = 0xFFFF'FFFF'FFFF;
LoggerLevel LogLevel = LoggerLevel::Info;
RuntimeConfig Config;
Config.Format = InputFormat::EVM;
Config.Mode = RunMode::InterpMode;

const std::unordered_map<std::string, InputFormat> FormatMap = {
{"wasm", InputFormat::WASM},
Expand Down
8 changes: 8 additions & 0 deletions tests/evm_asm/sar.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
status: success
error_code: 0
stack: []
memory: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
storage: {}
transient_storage: {}
return: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
events: []
8 changes: 8 additions & 0 deletions tests/evm_asm/sar_edge.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
status: success
error_code: 0
stack: []
memory: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
storage: {}
transient_storage: {}
return: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
events: []
8 changes: 8 additions & 0 deletions tests/evm_asm/shl.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
status: success
error_code: 0
stack: []
memory: 0000000000000000000000000000000000000000000000000000000000000008
storage: {}
transient_storage: {}
return: 0000000000000000000000000000000000000000000000000000000000000008
events: []
8 changes: 8 additions & 0 deletions tests/evm_asm/shl_edge.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
status: success
error_code: 0
stack: []
memory: 8000000000000000000000000000000000000000000000000000000000000000
storage: {}
transient_storage: {}
return: 8000000000000000000000000000000000000000000000000000000000000000
events: []
8 changes: 8 additions & 0 deletions tests/evm_asm/shl_truncate_overflow.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
status: success
error_code: 0
stack: []
memory: 0000000000000000000000000000000000000000000000000000000000000000
storage: {}
transient_storage: {}
return: 0000000000000000000000000000000000000000000000000000000000000000
events: []
8 changes: 8 additions & 0 deletions tests/evm_asm/shr.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
status: success
error_code: 0
stack: []
memory: 0000000000000000000000000000000000000000000000000000000000000002
storage: {}
transient_storage: {}
return: 0000000000000000000000000000000000000000000000000000000000000002
events: []
8 changes: 8 additions & 0 deletions tests/evm_asm/shr_edge.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
status: success
error_code: 0
stack: []
memory: 0000000000000000000000000000000000000000000000000000000000000001
storage: {}
transient_storage: {}
return: 0000000000000000000000000000000000000000000000000000000000000001
events: []