| 117 | |
| 118 | template <Traits traits> |
| 119 | void extcodecopy( |
| 120 | Context *ctx, uint256_t const *address_ptr, |
| 121 | uint256_t const *dest_offset_ptr, uint256_t const *offset_ptr, |
| 122 | uint256_t const *size_ptr) |
| 123 | { |
| 124 | auto const size = ctx->get_memory_offset(*size_ptr); |
| 125 | Memory::Offset dest_offset; |
| 126 | |
| 127 | if (*size > 0) { |
| 128 | dest_offset = ctx->get_memory_offset(*dest_offset_ptr); |
| 129 | |
| 130 | ctx->expand_memory<traits>(dest_offset + size); |
| 131 | |
| 132 | auto const size_in_words = shr_ceil<5>(size); |
| 133 | ctx->deduct_gas(size_in_words * bin<3>); |
| 134 | } |
| 135 | |
| 136 | auto address = address_from_uint256(*address_ptr); |
| 137 | |
| 138 | if constexpr (traits::eip_2929_active()) { |
| 139 | auto const access_status = |
| 140 | ctx->host->access_account(ctx->context, &address); |
| 141 | if (access_status == EVMC_ACCESS_COLD) { |
| 142 | ctx->deduct_gas(traits::cold_account_cost()); |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | if (*size > 0) { |
| 147 | auto const offset = clamp_cast<uint32_t>(*offset_ptr); |
| 148 | |
| 149 | auto *dest_ptr = ctx->memory.data + *dest_offset; |
| 150 | auto const n = ctx->host->copy_code( |
| 151 | ctx->context, &address, offset, dest_ptr, *size); |
| 152 | |
| 153 | auto *begin = dest_ptr + static_cast<uint32_t>(n); |
| 154 | auto *end = dest_ptr + *size; |
| 155 | |
| 156 | std::fill(begin, end, 0); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | EXPLICIT_TRAITS(extcodecopy); |
| 161 |
nothing calls this directly
no test coverage detected