EVM Preview Release 2
Pre-releaseThis continues the features from the EVM Preview Release 1.
New CLI EVM Commands
It adds new CLI EVM commands to fund and send a signed transaction.
You can fund an EOA account in the EVM by running the command:
flow evm fund {EVM address} {amount}
This will send the Flow amount to the EVM account using the signer as the funder. Default signer is the emulator but you can provide --signer
flag to specify different signer.
A command for sending signed transactions on the EVM was added:
flow evm send <signed rlp encoded transaction file>
The provided file must be a valid signed transaction that is RLP encoded.
New RPC Endpoints
This preview release adds subset of Ethereum RPC endpoints that can be used to interact with web3.js or other client libraries.
You can start the EVM RPC by running the following command:
flow evm rpc
This will start the HTTP server on the endpoint localhost:9000
which can then be configured in the web3.js like:
const { Web3 } = require('web3');
const web3 = new Web3("http://localhost:9000");
Please note that only a subset of the whole RPC API spec is implemented, the endpoints supported are:
- Send raw transaction
- Get transaction receipt
- Get transaction count
- Block number
- Get balance
- Estimate gas
- Gas price
- Call
Also note that in order to run the RPC command you must first run the emulator with EVM enabled:
flow emulator --evm-enabled
The RPC server if restarted, you must also restart the emulator, since in this demo version of the RPC server the nonce tracking is done in-memory and if restarted it will reset but the emulator will keep the state with nonces burned.
This release is not supposed to represent the production-ready code and it's sole purpose is to have as early access as possible. It's fragile and you should expect bugs.
Example of Web3.js
Here's an example of things you can do with the RPC endpoint:
const { Web3 } = require('web3');
const fs = require('fs');
const web3 = new Web3("http://localhost:9000");
const storageABI = require("./storageABI.json");
// this contract was deployed using the flow evm deploy command, the storage contract content and ABI you can find bellow
const storageAddress = "0x4859614cbe8bbe9ccad991cc69394343943cd52d";
let userAddress = "0xFACF71692421039876a5BB4F10EF7A439D8ef61E"
let userAccount = web3.eth.accounts.privateKeyToAccount("0xf6d5333177711e562cabf1f311916196ee6ffc2a07966d9d4628094073bd5442");
async function storageStore(value) {
let storage = new web3.eth.Contract(storageABI, storageAddress)
let data = storage.methods.store(value).encodeABI()
await userAccount.signTransaction({
from: userAccount.address,
to: storageAddress,
data: data,
value: '0',
gas: '100000',
gasPrice: '1',
// todo do we need to specify chain id
})
return web3.eth.sendSignedTransaction(signed.rawTransaction)
}
async function storageRetrieve() {
let storage = new web3.eth.Contract(storageABI, storageAddress)
let result = await storage.methods.retrieve().call()
console.log("result of the call is:", result)
}
Storage contract that is used in the above example contains the following code:
contract Storage {
event NewStore(uint256 value);
uint256 number;
constructor() payable {
number = 1337;
}
function store(uint256 num) public {
number = num;
emit NewStore(num);
}
function retrieve() public view returns (uint256){
return number;
}
}