Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions playground/src/examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,44 @@ function second<a, b>(pair: Pair<a, b>) returns (b) {
function main() returns (word) {
return second(Pair(true, 42));
}
`,
},
],
},
{
id: "option",
name: "Option",
description: "A generic optional value: checked division returns an Option instead of reverting.",
entry: "main.sol",
files: [
{
path: "main.sol",
content: `import * from std;

enum Option<a> {
None,
Some(a)
}

// Division by zero yields Option.None instead of reverting.
function checkedDiv(a: word, b: word) returns (Option<word>) {
if (b == 0) {
return Option.None;
}
return Option.Some(a / b);
}

function unwrapOr(option: Option<word>, orElse: word) returns (word) {
match (option) {
case Option.Some(value) { return value; }
default { return orElse; }
}
}

function main() returns (word) {
// 84 / 2 succeeds with Some(42); 84 / 0 would fall back to 0.
return unwrapOr(checkedDiv(84, 2), 0);
}
`,
},
],
Expand Down Expand Up @@ -182,6 +220,96 @@ contract Escrow {
}
}
}
`,
},
],
},
{
id: "mini-nft",
name: "Mini NFT",
description: "An NFT with typed ownership: tokens either have an owner or do not exist, with no zero-address sentinels.",
entry: "main.sol",
files: [
{
path: "main.sol",
content: `import * from std;
import * from std.dispatch;
import * from std.Generic;
import * from std.StorageGeneric;
import {caller} from std.opcodes;

// A token either has an owner or does not exist: unset mapping entries
// read back as Option.None.
enum Option<a> {
None,
Some(a)
}

function contains<a>(option: Option<a>, value: a) returns (bool) where a: Eq {
match (option) {
case Option.Some(inner) { return inner == value; }
default { return false; }
}
}

// msg.sender: the CALLER opcode lifted from word into address.
function sender() returns (address) {
return address(caller());
}

contract MiniNFT {
nextId : uint256;
owners : mapping(uint256 => Option<address>);
approvals : mapping(uint256 => Option<address>);
balances : mapping(address => uint256);

constructor() {}

function mint() public returns (uint256) {
let id = nextId;
nextId = nextId + uint256(1);
let to = sender();
owners[id] = Option.Some(to);
balances[to] = balances[to] + uint256(1);
return id;
}

function ownerOf(id: uint256) public returns (address) {
match (owners[id]) {
case Option.Some(owner) { return owner; }
default {
require(false, "no such token");
return address(0);
}
}
}

function approve(to: address, id: uint256) public {
require(sender() == ownerOf(id), "not the owner");
approvals[id] = Option.Some(to);
}

function transfer(to: address, id: uint256) public {
let owner = ownerOf(id);
let from = sender();
require(from == owner || contains(approvals[id], from), "not authorized");
approvals[id] = Option.None;
owners[id] = Option.Some(to);
balances[owner] = balances[owner] - uint256(1);
balances[to] = balances[to] + uint256(1);
}

function balanceOf(who: address) public returns (uint256) {
return balances[who];
}

function exists(id: uint256) public returns (bool) {
match (owners[id]) {
case Option.Some(_) { return true; }
default { return false; }
}
}
}
`,
},
],
Expand Down