|
1 |
| -Require Import Coq.Lists.List. |
2 |
| -Require Import Coq.Strings.String. |
| 1 | +Require Export Coq.Lists.List. |
| 2 | +Require Export Coq.Strings.String. |
3 | 3 |
|
4 | 4 | Import ListNotations.
|
5 | 5 |
|
@@ -220,88 +220,6 @@ Module SmartContract.
|
220 | 220 | Arguments t : clear implicits.
|
221 | 221 | End SmartContract.
|
222 | 222 |
|
223 |
| -(** Here we give an application of our DSL above with a representation of a simplified version of |
224 |
| - an [ERC-20] smart contract. *) |
225 |
| -Module Erc20. |
226 |
| - (** The init parameters are a name and a symbol for the token we are creating. They do not play |
227 |
| - any role in the computations, but are there in the ERC-20 of OpenZeppelin that we study. *) |
228 |
| - Definition InitInput : Set := |
229 |
| - string * string. |
230 |
| - |
231 |
| - (** The init outputs a new token kind *) |
232 |
| - Definition InitOutput : Set := |
233 |
| - TokenKind. |
234 |
| - |
235 |
| - (** The state of the contract is just the name and the symbol of its token. The token balance for |
236 |
| - each user is stored in the global world and we do not have to handle it here. *) |
237 |
| - Module State. |
238 |
| - Record t : Set := { |
239 |
| - name : string; |
240 |
| - symbol : string; |
241 |
| - }. |
242 |
| - End State. |
243 |
| - |
244 |
| - (** The commands representing the entrypoints of our smart contract, with the type of their |
245 |
| - output. *) |
246 |
| - Module Command. |
247 |
| - Inductive t {token_kind : InitOutput} : Set -> Set := |
248 |
| - | BalanceOf : User -> t (TokenQuantity token_kind) |
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. |
253 |
| - Arguments t : clear implicits. |
254 |
| - End Command. |
255 |
| - |
256 |
| - (** The definition of our ERC-20 smart contract *) |
257 |
| - Definition smart_contract : |
258 |
| - SmartContract.t |
259 |
| - InitInput |
260 |
| - InitOutput |
261 |
| - Command.t |
262 |
| - State.t := |
263 |
| - {| |
264 |
| - (* The constructor function *) |
265 |
| - SmartContract.init _sender '(name, symbol) := |
266 |
| - let! token_kind := M.MakeAction Action.CreateTokenKind in |
267 |
| - let state := {| |
268 |
| - State.name := name; |
269 |
| - State.symbol := symbol; |
270 |
| - |} in |
271 |
| - M.Pure (Some (token_kind, state)); |
272 |
| - SmartContract.call A token_kind sender command state := |
273 |
| - match command in Command.t _ A return M.t (option (A * _)) with |
274 |
| - (* The "balanceOf" entrypoint *) |
275 |
| - | Command.BalanceOf user => |
276 |
| - (* We run the action to get the balance *) |
277 |
| - let! balance := M.MakeAction (Action.GetBalance token_kind user) in |
278 |
| - 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)) |
283 |
| - (* The "transfer" entrypoint *) |
284 |
| - | Command.Transfer to value => |
285 |
| - (* We run the action to make the transfer and to know if it succeeded *) |
286 |
| - let! is_success := M.MakeAction (Action.Transfer token_kind sender to value) in |
287 |
| - if is_success then |
288 |
| - M.Pure (Some (tt, state)) |
289 |
| - else |
290 |
| - 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 |
301 |
| - end; |
302 |
| - |}. |
303 |
| -End Erc20. |
304 |
| - |
305 | 223 | (** Here we will define what it means for a smart contract defined in our DSL to be safe, in the
|
306 | 224 | sense that no one can steal money from others. *)
|
307 | 225 | Module NoStealing.
|
@@ -353,107 +271,3 @@ Module NoStealing.
|
353 | 271 | }.
|
354 | 272 | End InSmartContract.
|
355 | 273 | End NoStealing.
|
356 |
| - |
357 |
| -(** Now we will verify that our ERC-20 smart contract is safe *) |
358 |
| -Module Erc20IsSafe. |
359 |
| - (** Here is the specification saying that our smart contract is safe. It applies the predicate |
360 |
| - saying that a smart contract is safe to our definition of ERC-20. *) |
361 |
| - Lemma is_safe : NoStealing.InSmartContract.t Erc20.smart_contract. |
362 |
| - (** Here is the proof that the specification is correct. It should be executed in an IDE to see |
363 |
| - the proof state as we progress line by line. |
364 |
| -
|
365 |
| - The general idea is to go over all the possible execution scenarios of the smart contract, |
366 |
| - with the init, the "balanceOf", and the "transfer" entrypoints, and to prove that they are all |
367 |
| - safe. |
368 |
| - *) |
369 |
| - Proof. |
370 |
| - constructor; intros; cbn. |
371 |
| - { (* init *) |
372 |
| - destruct init_input as [name symbol]. |
373 |
| - unfold NoStealing.InRun.t; cbn. |
374 |
| - destruct Primitives.create_token_kind. |
375 |
| - apply ActionTree.Forall.Let. { |
376 |
| - (* The init is safe because the action we make to create a new token kind is safe *) |
377 |
| - apply ActionTree.Forall.MakeAction. |
378 |
| - cbn. |
379 |
| - trivial. |
380 |
| - } |
381 |
| - apply ActionTree.Forall.Pure. |
382 |
| - } |
383 |
| - { (* call *) |
384 |
| - destruct command. |
385 |
| - { (* BalanceOf *) |
386 |
| - unfold NoStealing.InRun.t; cbn. |
387 |
| - apply ActionTree.Forall.Let. { |
388 |
| - (* The "balanceOf" entrypoint is safe because the action we make to get the balance of a |
389 |
| - user is safe *) |
390 |
| - apply ActionTree.Forall.MakeAction. |
391 |
| - cbn. |
392 |
| - trivial. |
393 |
| - } |
394 |
| - apply ActionTree.Forall.Pure. |
395 |
| - } |
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 |
| - } |
406 |
| - { (* Transfer *) |
407 |
| - unfold NoStealing.InRun.t; cbn. |
408 |
| - (* We have two cases, depending on whether the transfer succeeded or not. In both cases we |
409 |
| - make a single transfer (or transfer attempt) with the right user for the source account, |
410 |
| - so this is safe. |
411 |
| - *) |
412 |
| - destruct Primitives.transfer; cbn. |
413 |
| - { apply ActionTree.Forall.Let. { |
414 |
| - apply ActionTree.Forall.MakeAction. |
415 |
| - cbn. |
416 |
| - reflexivity. |
417 |
| - } |
418 |
| - apply ActionTree.Forall.Pure. |
419 |
| - } |
420 |
| - { apply ActionTree.Forall.Let. { |
421 |
| - apply ActionTree.Forall.MakeAction. |
422 |
| - cbn. |
423 |
| - reflexivity. |
424 |
| - } |
425 |
| - apply ActionTree.Forall.Pure. |
426 |
| - } |
427 |
| - } |
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 |
| - } |
457 |
| - } |
458 |
| - Qed. |
459 |
| -End Erc20IsSafe. |
0 commit comments