Skip to content

Commit 5f41787

Browse files
authored
Merge pull request #3 from formal-land/guillaume-claret@add-erc20-commands
Add more ERC-20 commands
2 parents 5dfe4ba + 4424a10 commit 5f41787

File tree

1 file changed

+103
-2
lines changed

1 file changed

+103
-2
lines changed

erc20.v

+103-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ Module Primitives.
3636
World ->
3737
TokenQuantity token_kind.
3838

39+
(** Get the number of token that a [spender] is allowed to spend from a [user] *)
40+
Parameter get_allowance :
41+
forall (token_kind : TokenKind),
42+
forall (user : User),
43+
forall (spender : User),
44+
World ->
45+
TokenQuantity token_kind.
46+
3947
(** Transfer a certain quantity of tokens from a user to another, and return the new state of the
4048
world where the quantity of tokens they both own has been updated. *)
4149
Parameter transfer :
@@ -45,6 +53,22 @@ Module Primitives.
4553
TokenQuantity token_kind ->
4654
World ->
4755
option World.
56+
57+
(** Set the allowance for a certain [spender] at a certain amount from the account of a [user] *)
58+
Parameter approve :
59+
forall (token_kind : TokenKind),
60+
forall (user : User),
61+
forall (spender : User),
62+
TokenQuantity token_kind ->
63+
World ->
64+
World.
65+
66+
Parameter mint :
67+
forall (token_kind : TokenKind),
68+
User ->
69+
TokenQuantity token_kind ->
70+
World ->
71+
option World.
4872
End Primitives.
4973

5074
(** Actions are the primitives that we can run in our DSL to interact with tokens, make transfers,
@@ -59,9 +83,17 @@ Module Action.
5983
| CreateTokenKind : t TokenKind
6084
(** Ask for the number of tokens owned by a user *)
6185
| GetBalance (token_kind : TokenKind) (user : User) : t (TokenQuantity token_kind)
86+
| GetAllowance (token_kind : TokenKind) (user spender : User) : t (TokenQuantity token_kind)
6287
(** Ask to transfer token from a user to another one. The result is a boolean stating if the
6388
transfer was successful, meaning if there were enough funds. *)
64-
| Transfer (token_kind : TokenKind) (from to : User) (value : TokenQuantity token_kind) : t bool.
89+
| Transfer (token_kind : TokenKind) (from to : User) (value : TokenQuantity token_kind) : t bool
90+
| Approve (token_kind : TokenKind) (user spender : User) (value : TokenQuantity token_kind) : t unit
91+
| Mint
92+
(token_kind : TokenKind)
93+
(account : User)
94+
(value : TokenQuantity token_kind) :
95+
t bool
96+
.
6597

6698
(** This function maps the actions we defined to the primitives acting on the world above *)
6799
Definition run (world : World) {A : Set} (action : t A) : A * World :=
@@ -70,11 +102,20 @@ Module Action.
70102
Primitives.create_token_kind world
71103
| GetBalance token_kind user =>
72104
(Primitives.get_balance token_kind user world, world)
105+
| GetAllowance token_kind user spender =>
106+
(Primitives.get_allowance token_kind user spender world, world)
73107
| Transfer token_kind from to value =>
74108
match Primitives.transfer token_kind from to value world with
75109
| Some world' => (true, world')
76110
| None => (false, world)
77111
end
112+
| Approve token_kind user spender value =>
113+
(tt, Primitives.approve token_kind user spender value world)
114+
| Mint token_kind account value =>
115+
match Primitives.mint token_kind account value world with
116+
| Some world' => (true, world')
117+
| None => (false, world)
118+
end
78119
end.
79120
End Action.
80121

@@ -205,7 +246,10 @@ Module Erc20.
205246
Module Command.
206247
Inductive t {token_kind : InitOutput} : Set -> Set :=
207248
| BalanceOf : User -> t (TokenQuantity token_kind)
208-
| Transfer : User -> TokenQuantity token_kind -> t unit.
249+
| GetAllowance : User -> User -> t (TokenQuantity token_kind)
250+
| Transfer : User -> TokenQuantity token_kind -> t unit
251+
| Approve (spender : User) (quantity : TokenQuantity token_kind) : t unit
252+
| Mint (account : User) (value : TokenQuantity token_kind) : t unit.
209253
Arguments t : clear implicits.
210254
End Command.
211255

@@ -232,6 +276,10 @@ Module Erc20.
232276
(* We run the action to get the balance *)
233277
let! balance := M.MakeAction (Action.GetBalance token_kind user) in
234278
M.Pure (Some (balance, state))
279+
(* The "allowance" entrypoint *)
280+
| Command.GetAllowance user spender =>
281+
let! allowance := M.MakeAction (Action.GetAllowance token_kind user spender) in
282+
M.Pure (Some (allowance, state))
235283
(* The "transfer" entrypoint *)
236284
| Command.Transfer to value =>
237285
(* We run the action to make the transfer and to know if it succeeded *)
@@ -240,6 +288,16 @@ Module Erc20.
240288
M.Pure (Some (tt, state))
241289
else
242290
M.Pure None
291+
(* The "approve" entrypoint *)
292+
| Command.Approve spender value =>
293+
let! _ := M.MakeAction (Action.Approve token_kind sender spender value) in
294+
M.Pure (Some (tt, state))
295+
| Command.Mint account value =>
296+
let! is_success := M.MakeAction (Action.Mint token_kind account value) in
297+
if is_success then
298+
M.Pure (Some (tt, state))
299+
else
300+
M.Pure None
243301
end;
244302
|}.
245303
End Erc20.
@@ -257,10 +315,14 @@ Module NoStealing.
257315
| Action.CreateTokenKind => True
258316
(** Asking for the balance of a user is safe (all data are public in a blockchain) *)
259317
| Action.GetBalance _ _ => True
318+
| Action.GetAllowance _ _ _ => True
260319
(** Transferring tokens is only safe is the account from which we take the money is the same
261320
as the user running the smart contract *)
262321
| Action.Transfer token_kind from to value =>
263322
from = sender
323+
| Action.Approve _ user _ _ =>
324+
user = sender
325+
| Action.Mint token_kind account value => True
264326
end.
265327
End InAction.
266328

@@ -331,6 +393,16 @@ Module Erc20IsSafe.
331393
}
332394
apply ActionTree.Forall.Pure.
333395
}
396+
{ (* GetAllowance *)
397+
cbn.
398+
unfold NoStealing.InActionTree.t.
399+
apply ActionTree.Forall.Let. {
400+
apply ActionTree.Forall.MakeAction.
401+
cbn.
402+
trivial.
403+
}
404+
apply ActionTree.Forall.Pure.
405+
}
334406
{ (* Transfer *)
335407
unfold NoStealing.InRun.t; cbn.
336408
(* We have two cases, depending on whether the transfer succeeded or not. In both cases we
@@ -353,6 +425,35 @@ Module Erc20IsSafe.
353425
apply ActionTree.Forall.Pure.
354426
}
355427
}
428+
{ (* Approve *)
429+
cbn.
430+
apply ActionTree.Forall.Let. {
431+
apply ActionTree.Forall.MakeAction.
432+
cbn.
433+
trivial.
434+
}
435+
apply ActionTree.Forall.Pure.
436+
}
437+
{ (* Mint *)
438+
unfold NoStealing.InRun.t; cbn.
439+
destruct Primitives.mint.
440+
{ cbn.
441+
apply ActionTree.Forall.Let. {
442+
apply ActionTree.Forall.MakeAction.
443+
cbn.
444+
trivial.
445+
}
446+
apply ActionTree.Forall.Pure.
447+
}
448+
{ cbn.
449+
apply ActionTree.Forall.Let. {
450+
apply ActionTree.Forall.MakeAction.
451+
cbn.
452+
trivial.
453+
}
454+
apply ActionTree.Forall.Pure.
455+
}
456+
}
356457
}
357458
Qed.
358459
End Erc20IsSafe.

0 commit comments

Comments
 (0)