Skip to content

Commit 0e92b53

Browse files
authored
Merge pull request #14 from oralang/specs
update site
2 parents 9942370 + 6d765be commit 0e92b53

File tree

5 files changed

+530
-0
lines changed

5 files changed

+530
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
---
2+
slug: introducing-ora-type-system
3+
title: "Introducing Ora's Type System: Zig Meets Rust on the EVM"
4+
authors: [axe]
5+
tags: [type-system, design, compiler, safety]
6+
---
7+
8+
Smart contracts need a type system that's both safe and predictable. After years of working with Solidity's implicit behaviors and Rust's complex ownership rules, we asked: what if we took the best parts of both and built something specifically for the EVM?
9+
10+
That's how Ora's type system came to be. It's Zig-first in philosophy (explicit, no hidden control flow), Rust-influenced in safety (affine types for resources), and EVM-native in execution (every construct maps clearly to bytecode).
11+
12+
<!-- truncate -->
13+
14+
## The Philosophy: Explicit Over Implicit
15+
16+
Ora's type system has one core principle: **if it matters, make it explicit**.
17+
18+
In Solidity, you can accidentally create two mutable references to the same storage slot. The compiler won't stop you. Ora prevents this at compile time. Every variable declares its memory region: `storage`, `memory`, `calldata`, or `transient`. No guessing, no surprises.
19+
20+
```ora
21+
// Ora: explicit regions everywhere
22+
storage var u256 balance;
23+
memory var u256 temp;
24+
transient var u256 counter;
25+
26+
// Solidity: implicit and risky
27+
uint256 balance; // Is this storage? Memory? Who knows until runtime.
28+
```
29+
30+
This explicitness extends to everything. Want to know if a value can be copied or must be moved? Check the type. Want to know if a function can modify storage? Look at the signature. There's no hidden behavior.
31+
32+
## Memory Regions: Where Your Data Lives
33+
34+
On the EVM, where data lives matters. A lot. Ora makes this explicit with four memory regions:
35+
36+
- **`storage`** - Persistent contract state (SSTORE/SLOAD)
37+
- **`memory`** - Temporary, local (MSTORE/MLOAD)
38+
- **`calldata`** - Immutable caller input (read-only)
39+
- **`transient`** - Transaction-scoped scratch (EIP-1153)
40+
41+
Every variable declares its region. This prevents the classic Solidity bug where you accidentally modify storage when you meant to work with a local copy.
42+
43+
```ora
44+
contract Token {
45+
storage var u256 totalSupply;
46+
47+
pub fn mint(amount: u256) {
48+
// Explicit: this is a memory variable
49+
memory var u256 newSupply = totalSupply + amount;
50+
totalSupply = newSupply; // Explicit assignment back to storage
51+
}
52+
}
53+
```
54+
55+
The compiler enforces region rules. You can't accidentally create two mutable references to the same storage slot. You can't modify `calldata`. The type system prevents these bugs before they reach the blockchain.
56+
57+
## Affine Types: Move-Only Resources
58+
59+
Rust's ownership system is powerful but complex. Ora takes a simpler approach: affine types for resources that shouldn't be duplicated.
60+
61+
Think of permission tokens, session handles, or proof objects. These are things you want to move, not copy. Ora's affine system is much simpler than Rust's—no borrow checker, no lifetime annotations. Just: "this value moves, it doesn't copy."
62+
63+
```ora
64+
// Affine type: can't be duplicated
65+
affine struct PermissionToken {
66+
owner: address;
67+
expires: u256;
68+
}
69+
70+
fn transferPermission(token: PermissionToken) {
71+
// token is moved here, can't be used again
72+
// Prevents double-spending of permissions
73+
}
74+
```
75+
76+
For most values (integers, addresses, regular structs), copying is fine. Affine types are opt-in for resources that need move semantics. It's safety where it matters, simplicity everywhere else.
77+
78+
## Traits: Compile-Time Interfaces
79+
80+
Ora's traits are compile-time only. They're not runtime interfaces like Solidity, and they're not dynamic trait objects like Rust. They're Zig-style comptime polymorphism with Rust-like syntax.
81+
82+
```ora
83+
trait ERC20 {
84+
fn totalSupply() -> u256;
85+
fn balanceOf(owner: address) -> u256;
86+
fn transfer(to: address, amount: u256) -> bool;
87+
}
88+
89+
impl ERC20 for Token {
90+
fn balanceOf(owner: address) -> u256 {
91+
return self.balances[owner];
92+
}
93+
}
94+
```
95+
96+
Traits define behavior. Implementations bind behavior to storage. At runtime, traits don't exist—they're erased during compilation. This gives you abstraction without runtime cost.
97+
98+
For external contracts, Ora provides syntactic sugar:
99+
100+
```ora
101+
let token = external<ERC20>(contractAddress);
102+
token.transfer(alice, 100); // Compiler generates ABI stubs
103+
```
104+
105+
It looks like a trait object, but it's just ABI generation. No runtime conformance checks, no dynamic dispatch. Pure compile-time magic.
106+
107+
The trait system design was heavily influenced by working with [@philogy](https://twitter.com/philogy) and [@jtriley2p](https://twitter.com/jtriley2p). Their insights on compile-time interfaces and EVM-native abstractions shaped how Ora approaches traits.
108+
109+
## Refinement Types: Constraints in the Type
110+
111+
We've written about [refinement types](/blog/refinement-types-in-ora) before, but they're worth mentioning here. Ora's type system supports refinement predicates—constraints that are part of the type itself.
112+
113+
```ora
114+
amount: { x: u256 | x <= self.balance }
115+
```
116+
117+
These refinements are verified at compile time when possible, lowered to runtime guards when necessary. They're erased after verification, so there's no runtime overhead for proven constraints.
118+
119+
This is where Ora's type system gets really interesting: it's not just about preventing bugs, it's about proving correctness.
120+
121+
## No Inheritance, No Subtyping
122+
123+
Ora doesn't have inheritance. No multiple inheritance, no virtual functions, no diamond problems. The type system is flat and predictable.
124+
125+
This is intentional. Inheritance adds complexity and makes code harder to audit. Ora chooses composition over inheritance, traits over base classes. Every type stands on its own.
126+
127+
## How It Compares to Solidity
128+
129+
If you're coming from Solidity, here's what changes:
130+
131+
| What You're Used To | What Ora Does Instead |
132+
|---------------------|----------------------|
133+
| Implicit memory regions | Explicit `storage`/`memory`/`calldata` annotations |
134+
| Storage aliasing allowed | Compiler prevents dangerous aliasing |
135+
| `require()` everywhere | Refinement types + compile-time checks |
136+
| Interfaces at runtime | Traits at compile-time only |
137+
| No generics | Comptime generics (Zig-style) |
138+
| Inheritance | Composition + traits |
139+
140+
Ora is stricter, but that's the point. The compiler catches bugs that Solidity would let through. You write more explicit code, but you get safety guarantees in return.
141+
142+
## Why This Matters
143+
144+
Smart contracts handle real money. A type system that prevents bugs at compile time is worth the extra explicitness.
145+
146+
Ora's type system gives you:
147+
- **Predictability**: Every construct maps clearly to EVM behavior
148+
- **Safety**: Compile-time prevention of common bugs (aliasing, invalid regions)
149+
- **Auditability**: Explicit code is easier to review and verify
150+
- **Correctness**: Refinement types let you prove properties, not just hope they hold
151+
152+
It's not just about catching bugs—it's about building confidence. When the compiler proves something is safe, you don't need to worry about it.
153+
154+
## What's Next
155+
156+
The type system design is documented in our [design documents](/docs/design-documents/type-system-v0.1). It's a working design, evolving as we build the compiler.
157+
158+
We're actively implementing these features. Memory regions are working. Affine types are in progress. Traits are being designed. Refinement types are already functional.
159+
160+
The type system is one of Ora's core differentiators. It's what makes Ora contracts safer, more auditable, and more predictable than what's possible in Solidity today.
161+

website/docs/design-documents.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Design Documents
2+
3+
This section contains design documents, specifications, and architectural decisions for the Ora language and compiler.
4+
5+
## Overview
6+
7+
Design documents capture the rationale, trade-offs, and implementation details for major features and architectural decisions in the Ora project. These documents serve as:
8+
9+
- **Historical record**: Why decisions were made and what alternatives were considered
10+
- **Reference material**: Detailed technical specifications for implementation
11+
- **Collaboration tools**: Shared understanding for contributors and maintainers
12+
13+
## Document Categories
14+
15+
### Language Design
16+
Design decisions about the Ora language syntax, semantics, and features.
17+
18+
### Compiler Architecture
19+
Architectural decisions about the compiler pipeline, intermediate representations, and code generation.
20+
21+
### Formal Verification
22+
Design of the formal verification system, SMT solver integration, and verification condition generation.
23+
24+
### Standard Library
25+
Design of built-in functions, standard library modules, and language primitives.
26+
27+
## Contributing Design Documents
28+
29+
When creating a new design document:
30+
31+
1. **Use clear structure**: Include context, motivation, design decisions, and alternatives considered
32+
2. **Link to related docs**: Reference relevant specifications, examples, or implementation code
33+
3. **Keep it updated**: Update documents as designs evolve or are implemented
34+
4. **Include status**: Note whether the design is proposed, in progress, or completed
35+
36+
## Document Template
37+
38+
```markdown
39+
# [Feature/Component Name]
40+
41+
## Status
42+
[Proposed | In Progress | Completed | Deprecated]
43+
44+
## Overview
45+
Brief description of what this document covers.
46+
47+
## Motivation
48+
Why this feature/change is needed.
49+
50+
## Design Decisions
51+
Key decisions and rationale.
52+
53+
## Alternatives Considered
54+
Other approaches that were evaluated.
55+
56+
## Implementation Details
57+
Technical specifications and implementation notes.
58+
59+
## References
60+
Links to related documents, issues, or code.
61+
```
62+
63+
## Current Design Documents
64+
65+
### Language Design
66+
67+
- **[Type System (v0.1)](./type-system-v0.1)** - Working design document for Ora's type system, including memory regions, affine types, refinement predicates, traits, and comparison with Solidity.
68+
69+
### Coming Soon
70+
71+
- Compiler architecture decisions
72+
- Verification system design
73+
- Standard library specifications
74+
- Performance optimization strategies
75+
76+
---
77+
78+
**Note**: This section is actively being populated. If you're working on a design document, please add it here following the template above.
79+

0 commit comments

Comments
 (0)