A simple in-memory EVM JS emulator.
Install
npm i evm-js-emulator
Usage
import { newSession, parseBuffer, toUint, MAX_UINT, isSuccess } from 'evm-js-emulator';
const session = newSession({
rpcUrl: 'https://polygon-rpc.com',
cacheDir: '.evm-cache',
});
const executor = await session.prepareCall({
contract: toUint('0x ... write contract address here ...'),
origin: toUint('0x ... write sender address here ...'),
calldata: parseBuffer('0x ... write calldata here ...'),
callvalue: U256(0),
static: false,
timestamp: Date.now() / 1000,
gasLimit: MAX_UINT,
gasPrice: U256(0xffff),
retdatasize: 0,
});
const result = await executor.execute();
if (isSuccess(result)) {
}
Debugging
- Once you get an executor, before calling
.execute()
, you can log every EVM execution instruction using the helper:
import { watchInstructions } from 'evm-js-emulator/tests/test-utils';
watchInstructions(executor, 3);
-
You can name contracts or add ABIs to have nicer logs using the contractsNames
properties of newSession({ contractsNames: ...})
(see types).
-
Add breakpoints in codegen js files that you will find in you cache directory (subdirectory "contracts")... those are the contracts you are running, compiled to JS.
Disclaimer
This is a best-effort reproduction of the EVM.
It has been tested on many contracts, but:
- Gas is almost not implemented (contributions welcome)
- Some opcodes might not be implemented (contributions welcome)
- Behaviours might differ
TODO
- Implement missing opcodes
- Implement sourcemaps to be able to step in .sol files