Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Solidity for NEAR

Arto Bendiken
September 13, 2022

Solidity for NEAR

We present a prototype of a toolchain for compiling Ethereum Virtual Machine (EVM) smart contracts into WebAssembly bytecode for NEAR, and discuss future directions to incorporate this functionality directly into Aurora Engine.

Arto Bendiken

September 13, 2022
Tweet

More Decks by Arto Bendiken

Other Decks in Programming

Transcript

  1. 1. Overview 2. History 3. EVM to WebAssembly? 4. Solidity

    for NEAR 5. Future Directions Agenda
  2. Aurora Engine, an L2 for NEAR Protocol Aurora Engine (EVM)

    NEAR Runtime (WebAssembly) NEAR Protocol
  3. NEAR Runtime (WebAssembly bytecode runtime) Wasmer (WebAssembly→x86-64 JIT) SputnikVM (EVM

    bytecode interpreter) EVM Interpretation Tower x86-64 CPU (Intel/AMD μcode JIT)
  4. EVM Optimizations in 2021-2022 Changes to NEAR Protocol • secp256k1

    ecrecover host function • ripemd host function • alt_bn128 host function • Decrease in cost per Wasm op code • Decrease in state access cost (caching trie nodes) • Increase the per-transaction gas limit Changes to Aurora • Cache state access • Optimize for performance instead of code size Changes to SputnikVM • Implement SIGNEXTEND, MLOAD, and MSTORE more eiciently • Specialize the PUSH1 and PUSH2 implementations (from generic PUSHN) • Structure the interpreter loop more eiciently
  5. Kudos! Contributors from Aurora • Michael Birch (@birchmd) • Joshua

    Bouw (@joshuajbouw) • Evgeny Ukhanov (@mrLSD) Contributors from NEAR • Aleksey Kladov (@matklad) • Nikolay Igoi (@olonho) • Aleksandr Logunov (@longarithm)
  6. // SPDX-License-Identifier: Unlicense pragma solidity ^0.8.16; contract Counter { int

    private count = 0; function increment() public { count += 1; } function decrement() public { count -= 1; } function get() public view returns (int) { return count; } } increment: JUMPDEST POP PUSH1 0x01 PUSH1 0x00 SLOAD ADD DUP1 PUSH1 0x00 SSTORE PUSH1 0x00 MSTORE PUSH1 0x20 PUSH1 0x00 RETURN STOP EVM to WebAssembly (counter.sol ⇒ counter.sol.asm)
  7. increment: JUMPDEST POP PUSH1 0x01 PUSH1 0x00 SLOAD ADD DUP1

    PUSH1 0x00 SSTORE PUSH1 0x00 MSTORE PUSH1 0x20 PUSH1 0x00 RETURN STOP pub fn increment() { evm.push1(0x01); evm.push1(0x00); evm.sload(); evm.add(); evm.dup1(); evm.push1(0x00); evm.sstore(); evm.push1(0x00); evm.mstore(); evm.push1(0x20); evm.push1(0x00); evm.r#return() } EVM to WebAssembly (counter.sol.asm ⇒ counter.rs)
  8. (func $increment i32.const 1 call $evm/push1 i32.const 0 call $evm/push1

    call $evm/sload call $evm/add call $evm/dup1 i32.const 0 call $evm/push1 call $evm/sstore i32.const 0 call $evm/push1 increment: JUMPDEST POP PUSH1 0x01 PUSH1 0x00 SLOAD ADD DUP1 PUSH1 0x00 SSTORE PUSH1 0x00 MSTORE PUSH1 0x20 PUSH1 0x00 RETURN STOP EVM to WebAssembly (counter.sol.asm ⇒ counter.wat) call $evm/mstore i32.const 32 call $evm i32.const 0 call $evm call $evm/return )
  9. // SPDX-License-Identifier: Unlicense pragma solidity ^0.8.16; contract Calc { function

    multiply(int a, int b) public pure returns (int) { return a * b; } }
  10. % evm2near test/calc.sol -o test.wasm % near dev-deploy test.wasm %

    near view dev-1662780277695-66709124501364 \ multiply '{"a":6, "b":7}'
  11. We are hiring Junior and Senior Compiler Engineers to join

    this deep-tech R&D team! Apply at auroralabs.dev under “Work at Aurora”
  12. Expensive instructions • CODECOPY Requires embedding a copy of the

    original EVM bytecode into the output (bloat) • PC Requires either instrumenting generated code for precise program-counter accounting (slowdown), or embedding a large lookup table into the output (bloat) • GAS Requires instrumenting generated code to support precise gas accounting (slowdown) Unimplemented instructions (7) • CREATE • CALL • CALLCODE • DELEGATECALL • CREATE2 • STATICCALL • SELFDESTRUCT EVM to WebAssembly: Some challenges
  13. Immediately past the MVP release • Make EVM gas metering

    optional for a nice speedup when it isn’t required for full EVM compatibility • Implement a test suite based on popular real-world deployed contracts and associated transactions, sanity checking that for the same inputs we get the same known-good outputs (including EVM gas metering) Future R&D directions past MVP • Inlining EVM opcode calls for certain instructions where that would benefit • Applying other standard compiler optimizations from the literature for leaner and meaner bytecode • Adding NEAR host functions to beer support 256-bit machine words without the need for expensive bigint arithmetic • Adding NEAR host functions to speed up other aspects of execution, based on extensive and convincing profiling results EVM to WebAssembly: Compiler
  14. Dynamically loaded WebAssembly embedded inside the Aurora Engine (“JIT”) •

    Just-in-time compiled WebAssembly bytecode automatically deployed to, stored in, and maintained by the Aurora Engine for “hot” contracts • Trusted-yet-sandboxed bytecode deployed reproducibly by trusted parties • Zero EVM compatibility issues, just a significant speedup • Requires a NEP process, nearcore implementation, and protocol upgrade for dynamic bytecode support (6 months minimum) Standalone static NEAR contract deployment (“AOT”) • Ahead-of-time compiled WebAssembly bytecode manually deployed on-chain on NEAR, and authenticated with the Aurora Engine registry by the deployer • Untrusted, arbitrary bytecode deployed directly by third parties • Some challenges and trade-os for interacting with other EVM contracts (cross-shard calls) • Doesn’t require anything in particular from NEAR and nearcore EVM to WebAssembly: Execution models