Skip to content

Commit 1eb7356

Browse files
aa755jhunsaker
authored andcommitted
reserve balance checks now use the final state code hash
1 parent 8a0bd9e commit 1eb7356

File tree

3 files changed

+92
-11
lines changed

3 files changed

+92
-11
lines changed

category/execution/ethereum/test/test_monad_chain.cpp

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ TEST(MonadChain, can_sender_dip_into_reserve)
360360
.authorities = authorities,
361361
};
362362
EXPECT_FALSE(
363-
can_sender_dip_into_reserve(Address{1}, 1, NULL_HASH, context));
363+
can_sender_dip_into_reserve(Address{1}, 1, false, context));
364364
}
365365

366366
// False because of authority
@@ -378,7 +378,82 @@ TEST(MonadChain, can_sender_dip_into_reserve)
378378
.authorities = authorities,
379379
};
380380
EXPECT_FALSE(
381-
can_sender_dip_into_reserve(Address{1}, 1, NULL_HASH, context));
381+
can_sender_dip_into_reserve(Address{1}, 1, false, context));
382+
}
383+
}
384+
385+
TYPED_TEST(MonadTraitsTest, reserve_checks_code_hash)
386+
{
387+
using traits = typename TestFixture::Trait;
388+
constexpr Address SENDER{1};
389+
constexpr Address NEW_CONTRACT{2};
390+
constexpr uint64_t BASE_FEE_PER_GAS = 10;
391+
auto const to_wei = [](uint64_t mon) {
392+
return uint256_t{mon} * 1000000000000000000ULL;
393+
};
394+
395+
InMemoryMachine machine;
396+
mpt::Db db{machine};
397+
TrieDb tdb{db};
398+
vm::VM vm;
399+
BlockState bs{tdb, vm};
400+
401+
{
402+
State init_state{bs, Incarnation{0, 0}};
403+
init_state.add_to_balance(SENDER, to_wei(20));
404+
init_state.add_to_balance(NEW_CONTRACT, to_wei(3));
405+
MONAD_ASSERT(bs.can_merge(init_state));
406+
bs.merge(init_state);
407+
}
408+
409+
Transaction const tx{
410+
.max_fee_per_gas = BASE_FEE_PER_GAS,
411+
.gas_limit = 1,
412+
.type = TransactionType::legacy,
413+
.max_priority_fee_per_gas = 0,
414+
};
415+
uint256_t const gas_cost =
416+
uint256_t{BASE_FEE_PER_GAS} * uint256_t{tx.gas_limit};
417+
418+
std::vector<Address> const senders = {SENDER};
419+
std::vector<std::vector<std::optional<Address>>> const authorities = {{}};
420+
ankerl::unordered_dense::segmented_set<Address> senders_and_authorities;
421+
senders_and_authorities.insert(SENDER);
422+
MonadChainContext const context{
423+
.grandparent_senders_and_authorities = nullptr,
424+
.parent_senders_and_authorities = nullptr,
425+
.senders_and_authorities = senders_and_authorities,
426+
.senders = senders,
427+
.authorities = authorities};
428+
429+
auto const prepare_state = [&](State &state) {
430+
state.subtract_from_balance(SENDER, gas_cost);
431+
state.subtract_from_balance(NEW_CONTRACT, to_wei(3));
432+
byte_string const contract_code{0x60, 0x00};
433+
state.set_code(NEW_CONTRACT, contract_code);
434+
};
435+
436+
State state{bs, Incarnation{1, 1}};
437+
prepare_state(state);
438+
439+
bool const should_revert = revert_monad_transaction(
440+
traits::monad_rev(),
441+
traits::evm_rev(),
442+
SENDER,
443+
tx,
444+
BASE_FEE_PER_GAS,
445+
0,
446+
state,
447+
context);
448+
449+
if constexpr (traits::monad_rev() < MONAD_FOUR) {
450+
EXPECT_FALSE(should_revert);
451+
}
452+
else if constexpr (traits::monad_rev() >= MONAD_NEXT) {
453+
EXPECT_FALSE(should_revert);
454+
}
455+
else {
456+
EXPECT_TRUE(should_revert);
382457
}
383458
}
384459

category/execution/monad/reserve_balance.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <category/execution/monad/reserve_balance.h>
2323
#include <category/execution/monad/reserve_balance.hpp>
2424
#include <category/vm/evm/delegation.hpp>
25+
#include <category/vm/evm/monad/revision.h>
2526
#include <category/vm/interpreter/intercode.hpp>
2627

2728
#include <ankerl/unordered_dense.h>
@@ -51,16 +52,21 @@ bool dipped_into_reserve(
5152
uint256_t const gas_fees =
5253
uint256_t{tx.gas_limit} * gas_price(rev, tx, base_fee_per_gas);
5354
auto const &orig = state.original();
54-
for (auto const &[addr, _] : state.current()) {
55+
for (auto const &[addr, cur_account] : state.current()) {
5556
MONAD_ASSERT(orig.contains(addr));
5657
bytes32_t const orig_code_hash = orig.at(addr).get_code_hash();
58+
bytes32_t const effective_code_hash =
59+
(monad_rev >= MONAD_NEXT) ? cur_account.recent().get_code_hash()
60+
: orig_code_hash;
61+
bool effective_is_delegated = false;
5762

5863
// Skip if not EOA
59-
if (orig_code_hash != NULL_HASH) {
64+
if (effective_code_hash != NULL_HASH) {
6065
vm::SharedIntercode const intercode =
61-
state.read_code(orig_code_hash)->intercode();
62-
if (!monad::vm::evm::is_delegated(
63-
{intercode->code(), intercode->size()})) {
66+
state.read_code(effective_code_hash)->intercode();
67+
effective_is_delegated = monad::vm::evm::is_delegated(
68+
{intercode->code(), intercode->size()});
69+
if (!effective_is_delegated) {
6470
continue;
6571
}
6672
}
@@ -86,7 +92,7 @@ bool dipped_into_reserve(
8692
curr_balance < violation_threshold.value()) {
8793
if (addr == sender) {
8894
if (!can_sender_dip_into_reserve(
89-
sender, i, orig_code_hash, ctx)) {
95+
sender, i, effective_is_delegated, ctx)) {
9096
MONAD_ASSERT(
9197
violation_threshold.has_value(),
9298
"gas fee greater than reserve for non-dipping "
@@ -127,10 +133,10 @@ bool revert_monad_transaction(
127133
}
128134

129135
bool can_sender_dip_into_reserve(
130-
Address const &sender, uint64_t const i, bytes32_t const &orig_code_hash,
136+
Address const &sender, uint64_t const i, bool const sender_is_delegated,
131137
MonadChainContext const &ctx)
132138
{
133-
if (orig_code_hash != NULL_HASH) { // check delegated
139+
if (sender_is_delegated) { // delegated accounts cannot dip
134140
return false;
135141
}
136142

category/execution/monad/reserve_balance.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ bool revert_monad_transaction(
3737
MonadChainContext const &);
3838

3939
bool can_sender_dip_into_reserve(
40-
Address const &sender, uint64_t i, bytes32_t const &orig_code_hash,
40+
Address const &sender, uint64_t i, bool sender_is_delegated,
4141
MonadChainContext const &);
4242

4343
uint256_t get_max_reserve(monad_revision, Address const &);

0 commit comments

Comments
 (0)