@@ -74,24 +74,38 @@ uint256be Host::get_balance(const address& addr) const noexcept
74
74
return (acc != nullptr ) ? intx::be::store<uint256be>(acc->balance ) : uint256be{};
75
75
}
76
76
77
+ namespace
78
+ {
79
+ // For EXTCODE* instructions if the target is an EOF account, then only return EF00.
80
+ // While we only do this if the caller is legacy, it is not a problem doing this
81
+ // unconditionally, because EOF contracts dot no have EXTCODE* instructions.
82
+ bytes_view extcode (bytes_view code) noexcept
83
+ {
84
+ if (code.size () >= 2 && code[0 ] == 0xEF && code[1 ] == 0x00 )
85
+ return code.substr (2 );
86
+
87
+ return code;
88
+ }
89
+ } // namespace
90
+
77
91
size_t Host::get_code_size (const address& addr) const noexcept
78
92
{
79
93
const auto * const acc = m_state.find (addr);
80
- return (acc != nullptr ) ? acc->code .size () : 0 ;
94
+ return (acc != nullptr ) ? extcode ( acc->code ) .size () : 0 ;
81
95
}
82
96
83
97
bytes32 Host::get_code_hash (const address& addr) const noexcept
84
98
{
85
99
// TODO: Cache code hash. It will be needed also to compute the MPT hash.
86
100
const auto * const acc = m_state.find (addr);
87
- return (acc != nullptr && !acc->is_empty ()) ? keccak256 (acc->code ) : bytes32{};
101
+ return (acc != nullptr && !acc->is_empty ()) ? keccak256 (extcode ( acc->code ) ) : bytes32{};
88
102
}
89
103
90
104
size_t Host::copy_code (const address& addr, size_t code_offset, uint8_t * buffer_data,
91
105
size_t buffer_size) const noexcept
92
106
{
93
107
const auto * const acc = m_state.find (addr);
94
- const auto code = (acc != nullptr ) ? bytes_view{ acc->code } : bytes_view{};
108
+ const auto code = (acc != nullptr ) ? extcode ( acc->code ) : bytes_view{};
95
109
const auto code_slice = code.substr (std::min (code_offset, code.size ()));
96
110
const auto num_bytes = std::min (buffer_size, code_slice.size ());
97
111
std::copy_n (code_slice.begin (), num_bytes, buffer_data);
0 commit comments