From 1afca3ebd346ffb4dc854cd2df404d23825b500d Mon Sep 17 00:00:00 2001 From: Andrei Maiboroda Date: Thu, 19 Sep 2024 17:25:06 +0200 Subject: [PATCH 1/3] Add EVMC_DELEGATED flag --- include/evmc/evmc.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index 35e3c0db5..4fc513f7a 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -86,7 +86,8 @@ enum evmc_call_kind /** The flags for ::evmc_message. */ enum evmc_flags { - EVMC_STATIC = 1 /**< Static call mode. */ + EVMC_STATIC = 1, /**< Static call mode. */ + EVMC_DELEGATED = 2 /**< Delegated call mode (EIP-7702). Valid since Prague. */ }; /** @@ -101,7 +102,7 @@ struct evmc_message /** * Additional flags modifying the call execution behavior. - * In the current version the only valid values are ::EVMC_STATIC or 0. + * */ uint32_t flags; From 37b008414c260e941a784306991ac03e4b67a7de Mon Sep 17 00:00:00 2001 From: Andrei Maiboroda Date: Thu, 19 Sep 2024 15:11:55 +0200 Subject: [PATCH 2/3] Support EVMC_DELEGATED in go bindings --- bindings/go/evmc/evmc.go | 5 ++++- bindings/go/evmc/evmc_test.go | 2 +- bindings/go/evmc/host_test.go | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bindings/go/evmc/evmc.go b/bindings/go/evmc/evmc.go index bf6ac8912..c0817e129 100644 --- a/bindings/go/evmc/evmc.go +++ b/bindings/go/evmc/evmc.go @@ -205,7 +205,7 @@ type Result struct { } func (vm *VM) Execute(ctx HostContext, rev Revision, - kind CallKind, static bool, depth int, gas int64, + kind CallKind, static bool, delegated bool, depth int, gas int64, recipient Address, sender Address, input []byte, value Hash, code []byte) (res Result, err error) { @@ -213,6 +213,9 @@ func (vm *VM) Execute(ctx HostContext, rev Revision, if static { flags |= C.EVMC_STATIC } + if delegated { + flags |= C.EVMC_DELEGATED + } ctxId := addHostContext(ctx) // FIXME: Clarify passing by pointer vs passing by value. diff --git a/bindings/go/evmc/evmc_test.go b/bindings/go/evmc/evmc_test.go index fd6da980a..0c00772a4 100644 --- a/bindings/go/evmc/evmc_test.go +++ b/bindings/go/evmc/evmc_test.go @@ -47,7 +47,7 @@ func TestExecuteEmptyCode(t *testing.T) { addr := Address{} h := Hash{} - result, err := vm.Execute(nil, Byzantium, Call, false, 1, 999, addr, addr, nil, h, nil) + result, err := vm.Execute(nil, Byzantium, Call, false, false, 1, 999, addr, addr, nil, h, nil) if !bytes.Equal(result.Output, []byte("")) { t.Errorf("execution unexpected output: %x", result.Output) diff --git a/bindings/go/evmc/host_test.go b/bindings/go/evmc/host_test.go index 11eebf3fe..7c092f854 100644 --- a/bindings/go/evmc/host_test.go +++ b/bindings/go/evmc/host_test.go @@ -90,7 +90,7 @@ func TestGetBlockNumberFromTxContext(t *testing.T) { host := &testHostContext{} addr := Address{} h := Hash{} - result, err := vm.Execute(host, Byzantium, Call, false, 1, 100, addr, addr, nil, h, code) + result, err := vm.Execute(host, Byzantium, Call, false, false, 1, 100, addr, addr, nil, h, code) output := result.Output gasLeft := result.GasLeft @@ -121,7 +121,7 @@ func TestCall(t *testing.T) { host := &testHostContext{} addr := Address{} h := Hash{} - result, err := vm.Execute(host, Byzantium, Call, false, 1, 100, addr, addr, nil, h, code) + result, err := vm.Execute(host, Byzantium, Call, false, false, 1, 100, addr, addr, nil, h, code) output := result.Output gasLeft := result.GasLeft From 384507093822118e3a60756a56b7b6eb2e99cbda Mon Sep 17 00:00:00 2001 From: Andrei Maiboroda Date: Thu, 21 Nov 2024 17:31:53 +0100 Subject: [PATCH 3/3] Add get_delegate_address() host function --- examples/example_host.cpp | 2 ++ include/evmc/evmc.h | 20 ++++++++++++++++++++ include/evmc/evmc.hpp | 14 ++++++++++++++ include/evmc/mocked_host.hpp | 7 +++++++ test/unittests/cpp_test.cpp | 5 +++++ 5 files changed, 48 insertions(+) diff --git a/examples/example_host.cpp b/examples/example_host.cpp index 6e9e583bf..40969c66d 100644 --- a/examples/example_host.cpp +++ b/examples/example_host.cpp @@ -196,6 +196,8 @@ class ExampleHost : public evmc::Host { accounts[addr].transient_storage[key] = value; } + + evmc::address get_delegate_address(const evmc::address&) const noexcept override { return {}; } }; diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index 4fc513f7a..5849a5b28 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -834,6 +834,23 @@ typedef enum evmc_access_status (*evmc_access_storage_fn)(struct evmc_host_conte typedef struct evmc_result (*evmc_call_fn)(struct evmc_host_context* context, const struct evmc_message* msg); +/** + * Get delegate address function. + * + * This callback function is used by a VM to get target address of EIP-7702 delegation designation, + * in case it is set for given account. + * If account's code does not contain delegation designation, this function returns address + * 0x0000000000000000000000000000000000000000. + * + * @param context The pointer to the Host execution context. + * @param address The address of the account. + * @return The address of delegation designation target account + * or 0 if delegation is not set. + */ +typedef evmc_address (*evmc_get_delegate_address_fn)(struct evmc_host_context* context, + const evmc_address* address); + + /** * The Host interface. * @@ -891,6 +908,9 @@ struct evmc_host_interface /** Set transient storage callback function. */ evmc_set_transient_storage_fn set_transient_storage; + + /** Get delegate address function. */ + evmc_get_delegate_address_fn get_delegate_address; }; diff --git a/include/evmc/evmc.hpp b/include/evmc/evmc.hpp index 2dfabf826..2104d80ad 100644 --- a/include/evmc/evmc.hpp +++ b/include/evmc/evmc.hpp @@ -499,6 +499,9 @@ class HostInterface virtual void set_transient_storage(const address& addr, const bytes32& key, const bytes32& value) noexcept = 0; + + /// @copydoc evmc_host_interface::get_delegate_address + virtual address get_delegate_address(const address& addr) const noexcept = 0; }; @@ -609,6 +612,11 @@ class HostContext : public HostInterface { host->set_transient_storage(context, &address, &key, &value); } + + address get_delegate_address(const address& address) const noexcept final + { + return host->get_delegate_address(context, &address); + } }; @@ -877,6 +885,11 @@ inline void set_transient_storage(evmc_host_context* h, { Host::from_context(h)->set_transient_storage(*addr, *key, *value); } + +inline evmc_address get_delegate_address(evmc_host_context* h, const evmc_address* addr) noexcept +{ + return Host::from_context(h)->get_delegate_address(*addr); +} } // namespace internal inline const evmc_host_interface& Host::get_interface() noexcept @@ -898,6 +911,7 @@ inline const evmc_host_interface& Host::get_interface() noexcept ::evmc::internal::access_storage, ::evmc::internal::get_transient_storage, ::evmc::internal::set_transient_storage, + ::evmc::internal::get_delegate_address, }; return interface; } diff --git a/include/evmc/mocked_host.hpp b/include/evmc/mocked_host.hpp index 8aad17c46..7147b2377 100644 --- a/include/evmc/mocked_host.hpp +++ b/include/evmc/mocked_host.hpp @@ -507,5 +507,12 @@ class MockedHost : public Host record_account_access(addr); accounts[addr].transient_storage[key] = value; } + + /// Get account's delegate address. + address get_delegate_address(const address& addr) const noexcept override + { + record_account_access(addr); + return {}; + } }; } // namespace evmc diff --git a/test/unittests/cpp_test.cpp b/test/unittests/cpp_test.cpp index b0ca20e72..74dc80a9e 100644 --- a/test/unittests/cpp_test.cpp +++ b/test/unittests/cpp_test.cpp @@ -92,6 +92,11 @@ class NullHost : public evmc::Host const evmc::bytes32& /*key*/, const evmc::bytes32& /*value*/) noexcept override {} + + evmc::address get_delegate_address(const evmc::address& addr) const noexcept override + { + return {}; + } }; TEST(cpp, address)