Skip to content
Open
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
2 changes: 2 additions & 0 deletions category/vm/evm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ target_sources(monad-vm-evm PRIVATE
"delegation.cpp"
"delegation.hpp"
"explicit_traits.hpp"
"message.cpp"
"message.hpp"
"opcodes.hpp"
"opcodes_xmacro.hpp"
"revision.cpp"
Expand Down
86 changes: 86 additions & 0 deletions category/vm/evm/message.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (C) 2025-26 Category Labs, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include <category/vm/evm/message.hpp>

#include <evmc/evmc.h>

#include <cstddef>
#include <type_traits>
#include <utility>

// Value equality with evmc_call_kind / evmc_flags.
static_assert(sizeof(monad_call_kind) == sizeof(evmc_call_kind));

#define MONAD_ASSERT_ENUM_EQ(name) \
static_assert( \
std::to_underlying(MONAD_##name) == std::to_underlying(EVMC_##name))

MONAD_ASSERT_ENUM_EQ(CALL);
MONAD_ASSERT_ENUM_EQ(DELEGATECALL);
MONAD_ASSERT_ENUM_EQ(CALLCODE);
MONAD_ASSERT_ENUM_EQ(CREATE);
MONAD_ASSERT_ENUM_EQ(CREATE2);
MONAD_ASSERT_ENUM_EQ(EOFCREATE);
MONAD_ASSERT_ENUM_EQ(STATIC);
MONAD_ASSERT_ENUM_EQ(DELEGATED);

#undef MONAD_ASSERT_ENUM_EQ

// Layout equality with evmc_message.
static_assert(std::is_standard_layout_v<monad_message>);
static_assert(std::is_trivially_copyable_v<monad_message>);
static_assert(sizeof(monad_message) == 192);
static_assert(sizeof(monad_message) == sizeof(evmc_message));
static_assert(alignof(monad_message) == alignof(evmc_message));

#define MONAD_ASSERT_MESSAGE_FIELD_EQ(field) \

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offsets only: sizeof on the pointer members trips bugprone-sizeof-expression. The type asserts below cover the narrowed-field case that offsets alone would miss.

static_assert( \
offsetof(monad_message, field) == offsetof(evmc_message, field))

MONAD_ASSERT_MESSAGE_FIELD_EQ(kind);
MONAD_ASSERT_MESSAGE_FIELD_EQ(flags);
MONAD_ASSERT_MESSAGE_FIELD_EQ(depth);
MONAD_ASSERT_MESSAGE_FIELD_EQ(gas);
MONAD_ASSERT_MESSAGE_FIELD_EQ(recipient);
MONAD_ASSERT_MESSAGE_FIELD_EQ(sender);
MONAD_ASSERT_MESSAGE_FIELD_EQ(input_data);
MONAD_ASSERT_MESSAGE_FIELD_EQ(input_size);
MONAD_ASSERT_MESSAGE_FIELD_EQ(value);
MONAD_ASSERT_MESSAGE_FIELD_EQ(create2_salt);
MONAD_ASSERT_MESSAGE_FIELD_EQ(code_address);
MONAD_ASSERT_MESSAGE_FIELD_EQ(memory_handle);
MONAD_ASSERT_MESSAGE_FIELD_EQ(memory);
MONAD_ASSERT_MESSAGE_FIELD_EQ(memory_capacity);

#undef MONAD_ASSERT_MESSAGE_FIELD_EQ

// Same offset does not rule out a narrowed field padded back to the next one;
// the enum is pinned above, Address/bytes32_t in their own headers.
#define MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(field) \
static_assert(std::is_same_v< \
decltype(monad_message::field), \
decltype(evmc_message::field)>)

MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(flags);
MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(depth);
MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(gas);
MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(input_data);
MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(input_size);
MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(memory_handle);
MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(memory);
MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ(memory_capacity);

#undef MONAD_ASSERT_MESSAGE_FIELD_TYPE_EQ
60 changes: 60 additions & 0 deletions category/vm/evm/message.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (C) 2025-26 Category Labs, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#pragma once

#include <category/core/address.hpp>
#include <category/core/bytes.hpp>

#include <cstddef>
#include <cstdint>

// Mirrors evmc_call_kind 1:1; values asserted equal in message.cpp.
enum monad_call_kind
{
MONAD_CALL = 0,
MONAD_DELEGATECALL = 1,
MONAD_CALLCODE = 2,
MONAD_CREATE = 3,
MONAD_CREATE2 = 4,
MONAD_EOFCREATE = 5
};

// Mirrors evmc_flags 1:1; values asserted equal in message.cpp.
enum monad_call_flags

@khordadi khordadi Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in the issue title, but without it every reader of flags still needs evmc.h.

{
MONAD_STATIC = 1,
MONAD_DELEGATED = 2
};

// Mirrors the category-labs fork's evmc_message field-for-field (no
// code/code_size, memory-pool fields present); layout asserted in message.cpp.
struct monad_message
{
monad_call_kind kind;
uint32_t flags;
int32_t depth;
int64_t gas;
monad::Address recipient;
monad::Address sender;
uint8_t const *input_data;
size_t input_size;
monad::bytes32_t value;
monad::bytes32_t create2_salt;
monad::Address code_address;
uint8_t *memory_handle;
uint8_t *memory;
uint32_t memory_capacity;

@khordadi khordadi Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fork layout: evmc 663a1c2 dropped code/code_size, 8533622 added the memory-pool fields. A mirror of upstream evmc_message fails the asserts in message.cpp.

};
Loading