Sergey Melnychuk · RustMeet 2026 · Kraków
It's about Rust — async, WebAssembly, and implementing a complex spec from scratch.
No crypto wallet required 🦀
| Project | Goal | Result |
|---|---|---|
| Beerus | StarkNet light client, ready for integration with wallets | Done. Used in ETH-STRK bridge. Now closed. |
| Solenoid | Observable async-first wasm-ready EVM from scratch | Done. Works too slow. Now archived. |
| YEVM | Observable and fast async + wasm EVM, learn from Solenoid | Done. It works. |
YEVM
Naming things is hard.
Why build a new one in 2026?
wasm32-unknown-unknown: no OS, no stdlibSSTORE, CALL, warm/cold accessasync trait methodswasm32-unknown-unknown
// simplified
async fn execute(&mut self, opcode: u8) -> Result<()> {
match opcode {
SLOAD => {
let key = self.stack.pop()?;
let val = self.storage.load(key).await?; // async fetch
self.stack.push(val)
}
// ...
}
}
.await is a yield point — overhead adds upBut for browser use cases — latency hides the cost:
📊 QuoterV2 Results:
💰 Amount Out: 1 WETH for 3943.532812 USDC
📊 Price After (WETH/USDC): 3955.222269012662
🎯 Initialized Ticks Crossed: 1
⛽ Gas Estimate: 84919
✅ Transaction executed successfully!
🔄 Reverted: false
⛽ Gas used: 123290
SSTORE).await — what if it didn't?Designing and evolving such complex thing as EVM is hard
.awaits)async (handles fetches)
pub struct Call {...} // from, to, gas, data, value
pub enum HaltReason {...} // out-of-gas, out-of-memory, ...
pub enum CallMode {...} // call, static, delegate, callcode, create, create2
pub enum Fetch {...} // code, nonce, balance, account, block, state
pub enum EvmYield {
Return(Vec<u8>),
Revert(Vec<u8>),
Halt(HaltReason),
Call(Call, CallMode),
Fetch(Fetch),
}
pub type EvmResult<T> = std::result::Result<T, EvmYield>
pub fn dispatch<S: State>(
op: u8,
evm: &mut Evm,
ctx: &Context,
call: &Call,
state: &mut S) -> EvmResult<()> {
match op {
0x00 => basic::stop(evm),
// ...
0x31 => chain::balance(evm, ctx, call, state),
// ...
0xFF => calls::selfdestruct(evm, ctx, call, state),
_ => invalid(evm, ctx, call, state),
}
}
pub fn balance<S: State>(evm: &mut Evm, state: &mut S) -> EvmResult<()> {
evm.gas_charge(100)?;
let [acc] = evm.peek()?;
let acc: Acc = acc.to();
let Some(balance) = state.balance(&acc) else {
return Err(EvmYield::Fetch(Fetch::Balance(acc)));
};
if state.warm_acc(&acc) {
evm.gas_charge(2_500)?;
}
evm.push(balance)?;
Ok(())
}
Opcode handler:
futures::channel::mpsc
wasm32-unknown-unknown target3 random blocks from mainnet
AVG time (ms) to execute full block:
| Host | B1 | B2 | B3 |
|---|---|---|---|
| MacBook Pro M1 | 77 | 45 | 43 |
| Intel NUC i7-1260P | 81 | 51 | 50 |
| Cloud VM (AMD EPYC) | 130 | 81 | 80 |
Live demo: check vitalik.eth USDT balance
ByBit hack: Impl Swap TX (21895238:116)
ByBit hack: Drain ETH TX (21895251:35)
Learn more
Thank you!