This document discusses smart contracts on the Near Protocol blockchain using Rust and WebAssembly (WASM). It covers:
- Using WASM and Rust to build smart contracts due to their advantages like existing tooling, memory safety, and zero-cost abstractions.
- Different approaches to building Rust APIs for smart contracts, including eDSL-based, non-invasive, and generating eDSL styles.
- Features like asynchronous cross-contract calls, unit/integration testing, and type safety that would be nice to have.
- The Near Protocol team of 14 people including experts from Google, Facebook, and TopCoder working to develop the platform.
2. Smart Contracts & AWS Lambda
• Event-driven — executes code
only when needed. Pay per
execution;
• Serverless — no need to provision
servers;
Request
Response
Regular server is active all time
Zzzzz..
Lambda is only active when called
3. Smart Contracts & AWS Lambda
• Event-driven — executes code
only when needed. Pay per
execution;
• Serverless — no need to provision
servers;
Regular server is active all time
Lambda is only active when called
Request
Response
Request
Response
4. A Smart Contract
• Event-driven — executes code only when needed. Pay per execution;
• Serverless — no need to provision servers;
• Decentralized — it is not run by a single entity.
5. Immutable History of Events
Users running nodes collectively build the blockchain
7. Inside a Node
Blockchain Layer
• P2P Network
• Consensus
• Blocks Storage
• RPC API
Runtime Layer
Virtual Machine
State Storage
Code
8. WASM
+ Rust/TypeScript
Pros:
• Existing tooling and community;
• General purpose & Turing complete;
Cons:
• Was not designed for the
blockchain;
• No formal verification.
Specialized
VM + Language
Pros:
• Designed for the blockchain;
• Allows formal verification (?)
Cons:
• Niche language;
• Not Turing complete (?)
9. Requirements for VM
• Platform-independent WASM ✓
• Determinism WASM ✓ w/o floats
• Sand-boxed execution/compilation WASM ✓ certain executors
• Small size of compiled code WASM ✓
• Close to machine code WASM ✓
11. Rust Zero-Cost Abstractions
Zero cost abstractions. What you don’t use, you don’t pay for.
And further: What you do use, you couldn’t hand code any better.
- Bjarne Stroustrup
12. Rust APIs
near_bindgen — Rust API for NEAR blockchain
smart_contract — Rust API for Wavelet blockchain by Perlin
EWASM — a subset of WASM for Ethereum-like blockchains
Ink! — Rust API for Substrate/Polkadot blockchain
Mantle — Rust API for Oasis blockchain
Deprecated:
PWASM + Fleetwood — Rust API for Parity's Kovan blockchain
13. Contract Interface and Blockchain Interface
Blockchain Layer
WASM Executor
Rust Contract
Contract Interface
Methods defined by the contract
that the blockchain can call
State Storage
Blockchain Interface
Methods defined by the blockchain
that the contract can call
18. #[derive(Default, Serialize, Deserialize)]
struct Incrementer {
value: u32,
}
#[near_bindgen]
impl Incrementer {
pub fn inc(&mut self, by: u32) {
self.value += by;
}
}
near_bindgen (non-invasive)
• Contract Interface:
• Derived from your code.
• Blockchain Interface:
• Interactions through Blockchain<>
• Blockchain Interface (State):
• Derived from your code.
So insignificant that we did not give it a name
21. How Does It Work
#[derive(Default, Serialize, Deserialize)]
struct Incrementer {
value: u32,
}
#[near_bindgen]
impl Incrementer {
pub fn inc(&mut self, by: u32) {
self.value += by;
}
}
Injected code uses Default to initialize new
contract.
&self and &mut self tell macro whether
the state needs to be saved.
Arguments and return values are injected with
JSON-serialization/deserialization allowing
cross-contract calls written in other languages,
like TypeScript.
Any Rust struct can be a contract with zero
modifications.
22. Expanded
#[derive(Default, Serialize, Deserialize)]
struct Incrementer {
value: u32,
}
impl Incrementer {
pub fn inc(&mut self, by: u32) {
self.value += by;
}
}
#[no_mangle]
pub extern "C" fn inc() {
let args: serde_json::Value = serde_json::from_slice(&input_read()).unwrap();
let by = serde_json::from_value(args["by"].clone()).unwrap();
let mut contract: Incrementer = read_state().unwrap_or_default();
let result = contract.inc(by);
write_state(&contract);
}
29. Unit Tests and Integration Tests
Contract A Contract B
Blockchain
30. Dependency Inversion and Dependency Injection
Impl Contract A Impl Contract B
Impl Blockchain
Trait Contract A Trait Contract B
Trait Blockchain
31. Unit Testing Contract A
Impl Contract A Impl Contract B
Impl Blockchain
Trait Contract A Trait Contract B
Trait Blockchain
Injected Mock
Injected Mock
32. Integration Testing Contracts A and B
Impl Contract A Impl Contract B
Impl Blockchain
Trait Contract A Trait Contract B
Trait Blockchain
Injected Mock