From a149a0ad8bf9af51baaa835ac72dd71024857580 Mon Sep 17 00:00:00 2001 From: Gregor G <75445744+sideninja@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:50:55 +0200 Subject: [PATCH] Update 20231116-evm-support.md --- protocol/20231116-evm-support.md | 35 ++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/protocol/20231116-evm-support.md b/protocol/20231116-evm-support.md index bcf39218..76c92b05 100644 --- a/protocol/20231116-evm-support.md +++ b/protocol/20231116-evm-support.md @@ -70,15 +70,13 @@ fun main(bytes: [UInt8; 20]) { } ``` -`run` is the next crucial function in this contract which runs RLP-encoded EVM transactions. If the interaction with “Flow EVM” is successful and it changes the state, a new Flow-EVM block is formed and its data is emitted as a Cadence event. Using `run` limits EVM block to a single EVM transaction, a future `batchRun` provides option for batching EVM transaction execution. +`run` is the next crucial function in this contract which runs RLP-encoded EVM transactions. If the interaction with “Flow EVM” is successful and it changes the state, a new Flow-EVM block is formed and its data is emitted as a Cadence event. Using `run` limits EVM block to a single EVM transaction, a `batchRun` provides option for batching EVM transaction execution in a single block. Using batch run you can provide an array of RLP-encoded EVM transactions as input and they will be all executed in a new block, the function will return an array of results `[EVM.Result]` which will be the same length as the array of input transactions and will match the order. ```cadence -// Example of tx wrapping import EVM from transaction(rlpEncodedTransaction: [UInt8], coinbaseBytes: [UInt8; 20]) { - - prepare(signer: AuthAccount) { + execute { let coinbase = EVM.EVMAddress(bytes: coinbaseBytes) let result = EVM.run(tx: rlpEncodedTransaction, coinbase: coinbase) assert( @@ -89,6 +87,24 @@ transaction(rlpEncodedTransaction: [UInt8], coinbaseBytes: [UInt8; 20]) { } ``` +Example of batch run: +``` +import EVM from + +transaction(rlpEncodedTransactions: [[UInt8]], coinbaseBytes: [UInt8; 20]) { + execute { + let coinbase = EVM.EVMAddress(bytes: coinbaseBytes) + let results = EVM.batchRun(txs: txs, coinbase: coinbase) + + assert(results.length == txs.length, message: "invalid result length") + for res in results { + assert(res.status == EVM.Status.successful, message: "unexpected status") + } + } +} + +``` + Note that calling EVM.run doesn't revert the outter flow transaction and it requires the developer to take proper action based on the result.Status. Execution of a rlp encoded transaction result in one of these cases: - `Status.invalid`: The execution of an evm transaction/call has failed at the validation step (e.g. nonce mismatch). An invalid transaction/call is rejected to be executed or be included in a block (no state change). - `Status.failed`: The execution of an evm transaction/call has been successful but the vm has reported an error as the outcome of execution (e.g. running out of gas). A failed tx/call is included in a block. @@ -541,6 +557,17 @@ contract EVM { return runResult } + /// Runs a batch of RLP-encoded EVM transactions, deducts the gas fees, + /// and deposits the gas fees into the provided coinbase address. + /// An invalid transaction is not executed and not included in the block. + access(all) + fun batchRun(txs: [[UInt8]], coinbase: EVMAddress): [Result] { + return InternalEVM.batchRun( + txs: txs, + coinbase: coinbase.bytes, + ) as! [Result] + } + access(all) fun encodeABI(_ values: [AnyStruct]): [UInt8] { return InternalEVM.encodeABI(values)