|
| 1 | +--- |
| 2 | +eip: 2003 |
| 3 | +title: EVMC modules for implementations of precompiled contracts |
| 4 | +author: Paweł Bylica (@chfast), Alex Beregszaszi (@axic) |
| 5 | +discussions-to: https://github.com/ethereum/evmc/issues/259 |
| 6 | +status: Draft |
| 7 | +type: Informational |
| 8 | +created: 2019-05-09 |
| 9 | +requires: 1352 |
| 10 | +--- |
| 11 | + |
| 12 | +## Abstract |
| 13 | + |
| 14 | +[EVMC] specifies a generic API for Ethereum execution engines. |
| 15 | +This EIP specifies a way of providing implementations of Ethereum precompiled contracts |
| 16 | +using the [EVMC VM API]. |
| 17 | + |
| 18 | + |
| 19 | +## Specification |
| 20 | + |
| 21 | +For the complete [EVMC] specification visit the [EVMC documentation] first. |
| 22 | +This EIP is based on and is compatible with EVMC ABI version 6. |
| 23 | + |
| 24 | +The EVMC module with implementations of precompiled contracts SHOULD: |
| 25 | + |
| 26 | +1. Advertise the [`EVMC_CAPABILITY_PRECOMPILES`] capability |
| 27 | + in the [`get_capabilities()`] method. |
| 28 | + |
| 29 | +2. Implement the [`execute()`] method in the following way: |
| 30 | + |
| 31 | + 1. Validate the incoming execution request requirements: |
| 32 | + |
| 33 | + 1. The message kind ([`evmc_message::kind`]) is a call ([`EVMC_CALL`]). |
| 34 | + |
| 35 | + 2. The call destination address ([`evmc_message::destination`]) |
| 36 | + is within the range of precompiled contracts defined by [EIP-1352]. |
| 37 | + |
| 38 | + 3. There is no code provided (the `code` argument is `NULL` and `code_size` argument is `0`). |
| 39 | + |
| 40 | + If the requirements are not fulfilled, abort execution with the [`EVMC_REJECTED`] status code. |
| 41 | + |
| 42 | + 2. Check if the call destination address ([`evmc_message::destination`]) |
| 43 | + targets existing precompiled contract. |
| 44 | + Consider the EVM revision ([`evmc_revision`]) requested by |
| 45 | + the `rev` parameter of [`execute()`]. |
| 46 | + |
| 47 | + If yes, execute as follows: |
| 48 | + |
| 49 | + 1. Inspect the input data ([`evmc_message::input_data`], [`evmc_message::input_size`]) |
| 50 | + and calculate the _gas cost_ of the execution. |
| 51 | + |
| 52 | + 2. Compute the amount of _gas left_ after execution by |
| 53 | + subtracting the _gas cost_ from the call gas limit ([`evmc_message::gas`]). |
| 54 | + |
| 55 | + 3. If _gas left_ is negative, |
| 56 | + abort execution with the [`EVMC_OUT_OF_GAS`] status code. |
| 57 | + |
| 58 | + 4. Otherwise, |
| 59 | + execute the code of the precompiled contract, |
| 60 | + return the [`EVMC_SUCCESS`] status code, the output and _gas left_ |
| 61 | + ([`evmc_result::output_data`], [`evmc_result::output_size`], [`evmc_result::gas_left`]). |
| 62 | + |
| 63 | + 3. Otherwise, emulate execution of empty code by returning |
| 64 | + the [`EVMC_SUCCESS`] status code |
| 65 | + and _gas left_ equal the call gas limit ([`evmc_message::gas`]). |
| 66 | + |
| 67 | +Precompiled contract implementations are allowed to return two more EVMC error codes: |
| 68 | +- [`EVMC_FAILURE`] if the failure was caused due to something other than out of gas (e.g. input validation error) |
| 69 | +- [`EVMC_REVERT`] if the precompile doesn't want to forfeit all supplied gas (as of May 2019 no such precompile exists) |
| 70 | + |
| 71 | +The Client is not required to provide the Host interface ([`evmc_context`] argument of [`execute()`] is set to NULL). |
| 72 | +Therefore, the precompiled contracts implementation MUST NOT access the `evmc_context`. |
| 73 | + |
| 74 | + |
| 75 | +## Rationale |
| 76 | + |
| 77 | +It is very unlikely that any precompile will need to access or modify a contract state. |
| 78 | +Not requiring the Client to implement the EVMC Host interface removes the big portion of work |
| 79 | +needed for full EVMC integration. |
| 80 | + |
| 81 | + |
| 82 | +## Test Cases |
| 83 | + |
| 84 | +EVMC provides the [evmc-vmtester] tool for checking compatibility with the EVMC specification. |
| 85 | + |
| 86 | + |
| 87 | +## Implementations |
| 88 | + |
| 89 | +- [Example of Precompiles VM implementation][example_precompiles_vm.cpp] |
| 90 | +- [ewasm precompiles] |
| 91 | +- Aleth code for precompiles |
| 92 | +- Parity code for precompiles |
| 93 | +- [EIP-1962 implemented as an EVMC precompile module](https://github.com/axic/eip1962-evmc) |
| 94 | + |
| 95 | + |
| 96 | +## References |
| 97 | + |
| 98 | +- [EVMC – Ethereum Client-VM Connector API][EVMC] |
| 99 | +- [EVMC documentation] |
| 100 | +- [EVMC VM Implementation Guide][EVMC VM API] |
| 101 | +- [EIP 1352: Specify restricted address range for precompiles/system contracts][EIP-1352] |
| 102 | + |
| 103 | + |
| 104 | +## Copyright |
| 105 | + |
| 106 | +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
| 107 | + |
| 108 | + |
| 109 | +[EIP-1352]: https://eips.ethereum.org/EIPS/eip-1352 |
| 110 | +[EVMC]: https://github.com/ethereum/evmc |
| 111 | +[EVMC documentation]: https://ethereum.github.io/evmc/ |
| 112 | +[EVMC VM API]: https://ethereum.github.io/evmc/vmguide.html |
| 113 | +[evmc-vmtester]: https://ethereum.github.io/evmc/vmtester.html |
| 114 | +[example_precompiles_vm.cpp]: https://github.com/ethereum/evmc/blob/master/examples/example_precompiles_vm/example_precompiles_vm.cpp |
| 115 | +[ewasm precompiles]: https://github.com/ewasm/ewasm-precompiles |
| 116 | + |
| 117 | +[`EVMC_CALL`]: https://ethereum.github.io/evmc/group__EVMC.html#ggab2fa68a92a6828064a61e46060abc634abcf3ae29d9a88ff70b98374fc665694a |
| 118 | +[`EVMC_CAPABILITY_PRECOMPILES`]: https://ethereum.github.io/evmc/group__EVMC.html#gga44f9ecb88cf6422a0072936494fd6ac7a43ea2aa7b099a2d67bc53c118ff3683d |
| 119 | +[`EVMC_FAILURE`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920aed5b2a4afa5a47af732569445920a4a9 |
| 120 | +[`EVMC_OUT_OF_GAS`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920abfc47f75656c996c0b29c0553c00fc18 |
| 121 | +[`EVMC_REJECTED`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920a2f3e0d8777f8d974ead27ae2a6eb2005 |
| 122 | +[`EVMC_REVERT`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920aed708e84d49cc1270e54ec20b0ca0a05 |
| 123 | +[`EVMC_SUCCESS`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920a4bc3069fec2bab2a55355a72b7db68b7 |
| 124 | +[`execute()`]: https://ethereum.github.io/evmc/structevmc__instance.html#a0823ebff21f9b0395b157e8c6b14a207 |
| 125 | +[`get_capabilities()`]: https://ethereum.github.io/evmc/structevmc__instance.html#ae63b9ca898aa41cbd1e2fe86ca8f4e1c |
| 126 | +[`evmc_message::destination`]: https://ethereum.github.io/evmc/structevmc__message.html#a88ecfaa03a85a31c6da36fa043b98cea |
| 127 | +[`evmc_message::input_data`]: https://ethereum.github.io/evmc/structevmc__message.html#a1adee3454b105eb29cd659ee0cf65c77 |
| 128 | +[`evmc_message::input_size`]: https://ethereum.github.io/evmc/structevmc__message.html#a2cf1deebd0dbbb20f25ecdfa299f4b5d |
| 129 | +[`evmc_message::gas`]: https://ethereum.github.io/evmc/structevmc__message.html#ae8deff46588584fa27890e74c82db5e7 |
| 130 | +[`evmc_message::kind`]: https://ethereum.github.io/evmc/structevmc__message.html#a691cb93e81d6dfd4fd7e2fa3d06a6bfa |
| 131 | +[`evmc_result::gas_left`]: https://ethereum.github.io/evmc/structevmc__result.html#af8478c93dbcc3cb2876037c5a5afd4c0 |
| 132 | +[`evmc_result::output_data`]: https://ethereum.github.io/evmc/structevmc__result.html#a61978e85f9d795a7b9695b9cbf1748d6 |
| 133 | +[`evmc_result::output_size`]: https://ethereum.github.io/evmc/structevmc__result.html#a93bb7419aff492cdef754421c6d74e26 |
| 134 | +[`evmc_revision`]: https://ethereum.github.io/evmc/group__EVMC.html#gae5759b1590071966ccf6a505b52a0ef7 |
0 commit comments