Skip to content

Commit fea599a

Browse files
committed
Update readme
1 parent f6d7447 commit fea599a

File tree

3 files changed

+285
-8
lines changed

3 files changed

+285
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "scilla-parser"
3-
version = "0.5.0"
3+
version = "0.6.0"
44
edition = "2021"
55
description = "Scilla smart contract parser written in Rust"
66
license = "MIT"

README.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ This repository contains a Rust parser for the Scilla smart contract language. [
55
Add the following to your Cargo.toml:
66
```toml
77
[dependencies]
8-
scilla_parser = "0.4.0"
8+
scilla_parser = "0.6.0"
99
```
10+
1011
Alternatively, You can run this command:
1112
```shell
1213
cargo add scilla_parser
@@ -16,20 +17,30 @@ This will add the scilla_parser dependency to Cargo.toml as specified in the ins
1617
# Usage
1718
To parse a Scilla file:
1819
```rust
19-
use scilla_parser::{parse, Contract, Field, FieldList, Transition};
20+
use std::{error::Error, path::PathBuf};
21+
use scilla_parser::{Contract, Field, FieldList, Transition, TransitionList, Type};
2022

2123
let contract_path = PathBuf::from("tests/contracts/chainid.scilla");
22-
let contract = parse(&contract_path).unwrap();
24+
let contract = Contract::from_path(&contract_path).unwrap();
2325

2426
assert_eq!(
2527
contract,
2628
Contract {
2729
name: "ChainId".to_string(),
28-
path: contract_path.canonicalize().unwrap(),
29-
fields: FieldList(vec![]),
30-
constructor_params: FieldList(vec![]),
31-
transitions: vec![Transition::new("EventChainID", FieldList::default())]
30+
fields: FieldList::default(),
31+
init_params: FieldList::default(),
32+
transitions: TransitionList(vec![Transition::new(
33+
"EventChainID",
34+
FieldList::default()
35+
)])
3236
}
3337
);
3438
```
39+
40+
To parse a string containing a scilla contract:
41+
```rust
42+
let scilla_code: &str = "scilla contract";
43+
let contract: Contract = scilla_code.parse().unwrap();
44+
```
45+
3546
For more example take a look at the [tests](./tests/test_parser.rs).

tests/contracts/ZRC2Interop.scilla

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
scilla_version 0
2+
3+
(***************************************************)
4+
(* Associated library *)
5+
(***************************************************)
6+
import IntUtils
7+
library ZRC2Interop
8+
9+
let one_msg =
10+
fun (msg : Message) =>
11+
let nil_msg = Nil {Message} in
12+
Cons {Message} msg nil_msg
13+
14+
let two_msgs =
15+
fun (msg1 : Message) =>
16+
fun (msg2 : Message) =>
17+
let msgs_tmp = one_msg msg2 in
18+
Cons {Message} msg1 msgs_tmp
19+
20+
(* Error events *)
21+
type Error =
22+
| CodeIsSender
23+
| CodeInsufficientFunds
24+
| CodeInsufficientAllowance
25+
| CodeNotOwner
26+
27+
let make_error =
28+
fun (result : Error) =>
29+
let result_code =
30+
match result with
31+
| CodeIsSender => Int32 -1
32+
| CodeInsufficientFunds => Int32 -2
33+
| CodeInsufficientAllowance => Int32 -3
34+
| CodeNotOwner => Int32 -4
35+
end
36+
in
37+
{ _exception : "Error"; code : result_code }
38+
39+
let zero = Uint128 0
40+
41+
(* Dummy user-defined ADT *)
42+
type Unit =
43+
| Unit
44+
45+
let get_val =
46+
fun (some_val: Option Uint128) =>
47+
match some_val with
48+
| Some val => val
49+
| None => zero
50+
end
51+
52+
(***************************************************)
53+
(* The contract definition *)
54+
(***************************************************)
55+
56+
contract ZRC2Interop
57+
(
58+
contract_owner: ByStr20,
59+
name : String,
60+
symbol: String,
61+
decimals: Uint32,
62+
init_supply : Uint128
63+
)
64+
65+
(* Mutable fields *)
66+
67+
field total_supply : Uint128 = init_supply
68+
69+
field balances: Map ByStr20 Uint128
70+
= let emp_map = Emp ByStr20 Uint128 in
71+
builtin put emp_map contract_owner init_supply
72+
73+
field allowances: Map ByStr20 (Map ByStr20 Uint128)
74+
= Emp ByStr20 (Map ByStr20 Uint128)
75+
76+
(**************************************)
77+
(* Procedures *)
78+
(**************************************)
79+
80+
procedure ThrowError(err : Error)
81+
e = make_error err;
82+
throw e
83+
end
84+
85+
procedure IsOwner(address: ByStr20)
86+
is_owner = builtin eq contract_owner address;
87+
match is_owner with
88+
| True =>
89+
| False =>
90+
err = CodeNotOwner;
91+
ThrowError err
92+
end
93+
end
94+
95+
procedure IsNotSender(address: ByStr20)
96+
is_sender = builtin eq _origin address;
97+
match is_sender with
98+
| True =>
99+
err = CodeIsSender;
100+
ThrowError err
101+
| False =>
102+
end
103+
end
104+
105+
procedure AuthorizedMint(recipient: ByStr20, amount: Uint128)
106+
o_recipient_bal <- balances[recipient];
107+
bal = get_val o_recipient_bal;
108+
new_balance = builtin add amount bal;
109+
balances[recipient] := new_balance;
110+
current_total_supply <- total_supply;
111+
new_total_supply = builtin add current_total_supply amount;
112+
total_supply := new_total_supply;
113+
e = {_eventname: "Minted"; minter: _origin; recipient: recipient; amount: amount};
114+
event e
115+
end
116+
117+
procedure AuthorizedBurnIfSufficientBalance(from: ByStr20, amount: Uint128)
118+
o_get_bal <- balances[from];
119+
bal = get_val o_get_bal;
120+
can_burn = uint128_le amount bal;
121+
match can_burn with
122+
| True =>
123+
(* Subtract amount from from *)
124+
new_balance = builtin sub bal amount;
125+
balances[from] := new_balance;
126+
current_total_supply <- total_supply;
127+
new_total_supply = builtin sub current_total_supply amount;
128+
total_supply := new_total_supply;
129+
e = {_eventname: "Burnt"; burner: _origin; burn_account: from; amount: amount};
130+
event e
131+
| False =>
132+
err = CodeInsufficientFunds;
133+
ThrowError err
134+
end
135+
end
136+
137+
procedure AuthorizedMoveIfSufficientBalance(from: ByStr20, to: ByStr20, amount: Uint128)
138+
o_from_bal <- balances[from];
139+
bal = get_val o_from_bal;
140+
can_do = uint128_le amount bal;
141+
match can_do with
142+
| True =>
143+
(* Subtract amount from from and add it to to address *)
144+
new_from_bal = builtin sub bal amount;
145+
balances[from] := new_from_bal;
146+
(* Adds amount to to address *)
147+
get_to_bal <- balances[to];
148+
new_to_bal = match get_to_bal with
149+
| Some bal => builtin add bal amount
150+
| None => amount
151+
end;
152+
balances[to] := new_to_bal
153+
| False =>
154+
(* Balance not sufficient *)
155+
err = CodeInsufficientFunds;
156+
ThrowError err
157+
end
158+
end
159+
160+
(***************************************)
161+
(* Transitions *)
162+
(***************************************)
163+
164+
(* @dev: Mint new tokens. Only contract_owner can mint. *)
165+
(* @param recipient: Address of the recipient whose balance is to increase. *)
166+
(* @param amount: Number of tokens to be minted. *)
167+
transition Mint(recipient: ByStr20, amount: Uint128)
168+
IsOwner _origin;
169+
AuthorizedMint recipient amount;
170+
(* Prevent sending to a contract address that does not support transfers of token *)
171+
msg_to_recipient = {_tag : "RecipientAcceptMint"; _recipient : recipient; _amount : zero;
172+
minter : _origin; recipient : recipient; amount : amount};
173+
msg_to_sender = {_tag : "MintSuccessCallBack"; _recipient : _origin; _amount : zero;
174+
minter : _origin; recipient : recipient; amount : amount};
175+
msgs = two_msgs msg_to_recipient msg_to_sender;
176+
send msgs
177+
end
178+
179+
(* @dev: Burn existing tokens. Only contract_owner can burn. *)
180+
(* @param burn_account: Address of the token_owner whose balance is to decrease. *)
181+
(* @param amount: Number of tokens to be burned. *)
182+
transition Burn(burn_account: ByStr20, amount: Uint128)
183+
IsOwner _origin;
184+
AuthorizedBurnIfSufficientBalance burn_account amount;
185+
msg_to_sender = {_tag : "BurnSuccessCallBack"; _recipient : _origin; _amount : zero;
186+
burner : _origin; burn_account : burn_account; amount : amount};
187+
msgs = one_msg msg_to_sender;
188+
send msgs
189+
end
190+
191+
(* @dev: Increase the allowance of an approved_spender over the caller tokens. Only token_owner allowed to invoke. *)
192+
(* param spender: Address of the designated approved_spender. *)
193+
(* param amount: Number of tokens to be increased as allowance for the approved_spender. *)
194+
transition IncreaseAllowance(spender: ByStr20, amount: Uint128)
195+
IsNotSender spender;
196+
some_current_allowance <- allowances[_origin][spender];
197+
current_allowance = get_val some_current_allowance;
198+
new_allowance = builtin add current_allowance amount;
199+
allowances[_origin][spender] := new_allowance;
200+
e = {_eventname : "IncreasedAllowance"; token_owner : _origin; spender: spender; new_allowance : new_allowance};
201+
event e
202+
end
203+
204+
(* @dev: Decrease the allowance of an approved_spender over the caller tokens. Only token_owner allowed to invoke. *)
205+
(* param spender: Address of the designated approved_spender. *)
206+
(* param amount: Number of tokens to be decreased as allowance for the approved_spender. *)
207+
transition DecreaseAllowance(spender: ByStr20, amount: Uint128)
208+
IsNotSender spender;
209+
some_current_allowance <- allowances[_origin][spender];
210+
current_allowance = get_val some_current_allowance;
211+
new_allowance =
212+
let amount_le_allowance = uint128_le amount current_allowance in
213+
match amount_le_allowance with
214+
| True => builtin sub current_allowance amount
215+
| False => zero
216+
end;
217+
allowances[_origin][spender] := new_allowance;
218+
e = {_eventname : "DecreasedAllowance"; token_owner : _origin; spender: spender; new_allowance : new_allowance};
219+
event e
220+
end
221+
222+
(* @dev: Moves an amount tokens from _origin to the recipient. Used by token_owner. *)
223+
(* @dev: Balance of recipient will increase. Balance of _origin will decrease. *)
224+
(* @param to: Address of the recipient whose balance is increased. *)
225+
(* @param amount: Amount of tokens to be sent. *)
226+
transition Transfer(to: ByStr20, amount: Uint128)
227+
AuthorizedMoveIfSufficientBalance _origin to amount;
228+
e = {_eventname : "TransferSuccess"; sender : _origin; recipient : to; amount : amount};
229+
event e;
230+
(* Prevent sending to a contract address that does not support transfers of token *)
231+
msg_to_recipient = {_tag : "RecipientAcceptTransfer"; _recipient : to; _amount : zero;
232+
sender : _origin; recipient : to; amount : amount};
233+
msg_to_sender = {_tag : "TransferSuccessCallBack"; _recipient : _origin; _amount : zero;
234+
sender : _origin; recipient : to; amount : amount};
235+
msgs = two_msgs msg_to_recipient msg_to_sender;
236+
send msgs
237+
end
238+
239+
(* @dev: Move a given amount of tokens from one address to another using the allowance mechanism. The caller must be an approved_spender. *)
240+
(* @dev: Balance of recipient will increase. Balance of token_owner will decrease. *)
241+
(* @param from: Address of the token_owner whose balance is decreased. *)
242+
(* @param to: Address of the recipient whose balance is increased. *)
243+
(* @param amount: Amount of tokens to be transferred. *)
244+
transition TransferFrom(from: ByStr20, to: ByStr20, amount: Uint128)
245+
o_spender_allowed <- allowances[from][_origin];
246+
allowed = get_val o_spender_allowed;
247+
can_do = uint128_le amount allowed;
248+
match can_do with
249+
| True =>
250+
AuthorizedMoveIfSufficientBalance from to amount;
251+
e = {_eventname : "TransferFromSuccess"; initiator : _origin; sender : from; recipient : to; amount : amount};
252+
event e;
253+
new_allowed = builtin sub allowed amount;
254+
allowances[from][_origin] := new_allowed;
255+
(* Prevent sending to a contract address that does not support transfers of token *)
256+
msg_to_recipient = {_tag: "RecipientAcceptTransferFrom"; _recipient : to; _amount: zero;
257+
initiator: _origin; sender : from; recipient: to; amount: amount};
258+
msg_to_sender = {_tag: "TransferFromSuccessCallBack"; _recipient: _origin; _amount: zero;
259+
initiator: _origin; sender: from; recipient: to; amount: amount};
260+
msgs = two_msgs msg_to_recipient msg_to_sender;
261+
send msgs
262+
| False =>
263+
err = CodeInsufficientAllowance;
264+
ThrowError err
265+
end
266+
end

0 commit comments

Comments
 (0)