👨🔬 An extensible Python implementation of the Ethereum yellow paper from scratch.
To run the EVM from scratch:
Install Poetry
curl -sSL https://install.python-poetry.org | python3 -
Install Dependencies
poetry install
Run Tests
poetry run pytest -v
Run the
black
code formatter
poetry run black src
Write-up with examples:
Building an EVM from scratch [karmacoma.notion.so]
Takes the binary representation of a contract and generates the init code that will deploy that contract (Ti in Yellow Paper terminology).
For instance, let's say that you have some Yul code, that when compiled with solc
has the following binary representation: 602a60205260206020f3
.
> python raw_deployer.py 602a60205260206020f3
600a8061000d6000396000f3fe602a60205260206020f3
You can now deploy this code:
web3.eth.sendTransaction({
from: /* your address */,
/* no to address as we are creating a contract */
data: "600a8061000d6000396000f3fe602a60205260206020f3"
})
Wait for the transaction to be confirmed, and go look at the code of the contract that was deployed, it should match our compiled Yul code 602a60205260206020f3
🙌
Based on web3.py, this script can find addresses of contracts deployed by the CREATE2
opcode that satisfy a particular predicate.
Usage: python3 create2.py deployer_addr <salt | predicate> bytecode
When passing a salt value, this script prints the address of the newly deployed contract based on the deployer address and bytecode hash.
Example: python3 create2.py Bf6cE3350513EfDcC0d5bd5413F1dE53D0E4f9aE 42 602a60205260206020f3
When passing a predicate, this script will search for a salt value such that the new address satisfies the predicate.
Example: python3 create2.py Bf6cE3350513EfDcC0d5bd5413F1dE53D0E4f9aE 'lambda addr: "badc0de" in addr.lower()' 602a60205260206020f3
Another predicate that may be useful: 'lambda addr: addr.startswith("0" * 8)'
Use with a deployer contract like this:
contract Deployer {
function deploy(bytes memory code, uint256 salt) public returns(address) {
address addr;
assembly {
addr := create2(0, add(code, 0x20), mload(code), salt)
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
return addr;
}
}