From 2e65624a39d874bdf3f676ca07f0a9b67ea1df49 Mon Sep 17 00:00:00 2001 From: AdrienChampion Date: Mon, 4 Mar 2019 18:58:45 +0100 Subject: [PATCH] fix in user doc --- docs/user_doc/testing/time.html | 484 ++++++++++++++++++++++++++++++++ 1 file changed, 484 insertions(+) create mode 100644 docs/user_doc/testing/time.html diff --git a/docs/user_doc/testing/time.html b/docs/user_doc/testing/time.html new file mode 100644 index 0000000..60ad069 --- /dev/null +++ b/docs/user_doc/testing/time.html @@ -0,0 +1,484 @@ + + + + + + Timestamp Control - Techelson User Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + +
+
+

Timestamp Control

+

Some contracts need to reason about time, based on the timestamp of the block the computation takes +place in. By default, the timestamp of all blocks in Techelson is 1970-01-01T00:00:00Z. Testcases +can set this timestamp to anything, the only constraint is that the new timestamp is older than the +previous one. The relevant instruction is

+ + + +
instruction parameter stack
SET_TIMESTAMP none :: timestamp : 'S
-> 'S
+

As an example, consider the following contract Timestamp which takes (or unit (contract unit)): +it

+
    +
  • receives money once (Left Unit), and
  • +
  • unlocks it if one week has passed since it receives money.
  • +
+

To unlock the money, someone must call the contract and give it a unit contract to collect the +money (Right <contract>). Unlocking the money is only legal after one week (604800 seconds) has +passed since the money was received.

+

The code follows. Its storage is (option timestamp) which stores the last time it receives money. +The contract fails if asked to

+
    +
  • receive money but it's already storing money (its storage is not None),
  • +
  • unlock the money but it hasn't received anything (its storage is None), and
  • +
  • unlock the money but one week hasn't passed since it was received.
  • +
+
storage (option timestamp) ;
+parameter (or unit (contract unit)) ;
+code {
+    UNPAIR @storage @param ;
+    IF_LEFT {
+        DROP ;
+        IF_NONE {
+            NOW ;
+            SOME ;
+            NIL operation ;
+            PAIR
+        } {
+            PUSH string "cannot receive money twice" ;
+            FAILWITH
+        }
+    } {
+        SWAP ;
+        IF_NONE {
+            PUSH string "cannot send money, no money received" ;
+            FAILWITH
+        } {
+            NOW ;
+            SUB ;
+            PUSH int 604800 ; # One week in seconds.
+            IFCMPGT {
+                PUSH string "cannot send money, it has not been one week yet" ;
+                FAILWITH
+            } {
+                BALANCE ;
+                UNIT ;
+                TRANSFER_TOKENS ;
+                DIP {
+                    NONE timestamp ;
+                    NIL operation
+                } ;
+                CONS ;
+                PAIR
+            }
+        }
+    } ;
+} ;
+
+

Let's go through TestTimestamp, the testcase for Timestamp. The first step should be unsurprising +by now: deploy the contract and an account (so that we can unlock the money later).

+
{
+    { # Deploy contract.
+        NONE timestamp ;
+        PUSH mutez 0 ;
+        PUSH bool False ;
+        PUSH bool True ;
+        NONE key_hash ;
+        PUSH key "manager" ;
+        HASH_KEY ;
+        CREATE_CONTRACT @contract "Timestamp" ;
+        DIP NIL operation ;
+        CONS ;
+    } ;
+
+    { # Deploy account to retrieve the money later on.
+        PUSH mutez 0 ;
+        PUSH bool True ;
+        NONE key_hash ;
+        PUSH key "manager" ;
+        HASH_KEY ;
+        CREATE_ACCOUNT @account ;
+        DIP SWAP
+    } ;
+
+    CONS ;
+    APPLY_OPERATIONS ;
+    SWAP ;
+
+    { # Retrieve contract.
+        CONTRACT (or unit (contract unit)) ;
+        IF_NONE {
+            PUSH string "failed to retrieve contract" ;
+            FAILWITH
+        } {}
+    } ;
+
+    DIP { # Retrieve account.
+        CONTRACT unit ;
+        IF_NONE {
+            PUSH string "failed to retrieve account" ;
+            FAILWITH
+        } {}
+    } ;
+
+

Next, let's set the timestamp to January 1 2019, 11am, and send some money to the contract.

+
    { # Set timestamp.
+        PUSH timestamp "2019-01-01T11:00:00Z" ;
+        SET_TIMESTAMP
+    } ;
+
+    { # Send money to the account.
+        DUP ;
+        PUSH mutez 10 ;
+        UNIT ;
+        LEFT (contract unit) ;
+        TRANSFER_TOKENS ;
+        DIP NIL operation ;
+        CONS ;
+        APPLY_OPERATIONS
+    } ;
+
+

We now check the storage is what it should be:

+
    { # Check the storage is correct.
+        DUP ;
+        GET_STORAGE (option timestamp) ;
+        IF_NONE {
+            PUSH string "failed to retrieve storage" ;
+            FAILWITH
+        } {
+            IF_NONE {
+                PUSH string "storage should not be `None`" ;
+                FAILWITH
+            } {
+                PUSH timestamp "2019-01-01T11:00:00Z" ;
+                IFCMPNEQ {
+                    PUSH string "storage should be `2019-01-01T11:00:00Z`" ;
+                    FAILWITH
+                } {}
+            }
+        }
+    } ;
+
+

Let's make sure unlocking the money before one week has passed fails. First, the testcase sets the +timestamp to January 8 2019, 9am, which is not one week later than the date at which we sent +money to the contract. So this should fail.

+
    { # Set timestamp to almost one week later.
+        PUSH timestamp "2019-01-08T09:00:00Z" ;
+        SET_TIMESTAMP
+    } ;
+
+    { # Try to retrieve the money.
+        DUP ;
+        PUSH mutez 0 ;
+        DUUUUP ;
+        RIGHT unit ;
+        TRANSFER_TOKENS ;
+        PUSH (option string) (Some "cannot send money, it has not been one week yet") ;
+        MUST_FAIL string ;
+        DIP NIL operation ;
+        CONS ;
+        APPLY_OPERATIONS
+    } ;
+
+

Last, let's set the date to January 8 2019, 11am, at which point unlocking the money should work.

+
    { # Set timestamp to exactly one week later.
+        PUSH timestamp "2019-01-08T11:00:00Z" ;
+        SET_TIMESTAMP
+    } ;
+
+    { # Try to retrieve the money.
+        DUP ;
+        PUSH mutez 0 ;
+        DUUUUP ;
+        RIGHT unit ;
+        TRANSFER_TOKENS ;
+        DIP NIL operation ;
+        CONS ;
+        APPLY_OPERATIONS
+    } ;
+
+    { # Check the account received it.
+        DROP ;
+        GET_BALANCE ;
+        PUSH mutez 10 ;
+        IFCMPNEQ {
+            PUSH string "account's balance should be 10utz" ;
+            FAILWITH
+        } {}
+    }
+}
+
+

All set. Running techelson yields the following output. It is split in two parts here, first up +to the request to unlock the money on January 8 2019 at 9am, which should fail:

+
$ techelson --contract rsc/timestamp/contracts/timestamp.tz -- rsc/timestamp/okay/testTimestamp.techel
+Running test `TestTimestamp`
+
+running test script...
+   timestamp: 1970-01-01 00:00:00 +00:00
+
+applying operation CREATE[uid:1] (@address[2]@account, "b58check:manager", None, true, true, 0utz) 
+                       {
+                           storage unit ;
+                           parameter unit ;
+                           code ...;
+                       }
+   timestamp: 1970-01-01 00:00:00 +00:00
+   live contracts: none
+=> live contracts: <anonymous> (0utz) address[2]@account
+                   Timestamp (0utz) address[1]@contract
+
+running test script...
+   timestamp: 1970-01-01 00:00:00 +00:00
+
+applying operation TRANSFER[uid:2] address[0]@TestTimestamp -> address[1]@contract 10utz (Left Unit)
+   timestamp: 2019-01-01 11:00:00 +00:00
+   live contracts: <anonymous> (0utz) address[2]@account
+                   Timestamp (0utz) address[1]@contract
+
+running TRANSFER[uid:2] address[0]@TestTimestamp -> address[1]@contract 10utz (Left Unit)
+   timestamp: 2019-01-01 11:00:00 +00:00
+=> live contracts: <anonymous> (0utz) address[2]@account
+                   Timestamp (10utz) address[1]@contract
+
+running test script...
+   timestamp: 2019-01-01 11:00:00 +00:00
+
+applying operation MUST_FAIL[uid:4] "cannot send money, it has not been one week yet" : 
+string (TRANSFER[uid:3] address[0]@TestTimestamp -> address[1]@contract 0utz (Right address[2]@account))
+   timestamp: 2019-01-08 09:00:00 +00:00
+   live contracts: <anonymous> (0utz) address[2]@account
+                   Timestamp (10utz) address[1]@contract
+
+running TRANSFER[uid:3] address[0]@TestTimestamp -> address[1]@contract 0utz (Right address[2]@account)
+   timestamp: 2019-01-08 09:00:00 +00:00
+=> live contracts: <anonymous> (0utz) address[2]@account
+                   Timestamp (10utz) address[1]@contract
+failure confirmed on test operation
+  MUST_FAIL[uid:4] "cannot send money, it has not been one week yet" : 
+  string (TRANSFER[uid:3] address[0]@TestTimestamp -> address[1]@contract 0utz (Right address[2]@account))
+while running operation TRANSFER[uid:3] address[0]@TestTimestamp -> address[1]@contract 0utz (Right address[2]@account)
+failed with value "cannot send money, it has not been one week yet" : 
+string
+
+

So far so good. Finally, the rest of the output should go smoothly and succeed:

+
running test script...
+   timestamp: 2019-01-08 09:00:00 +00:00
+
+applying operation TRANSFER[uid:5] address[0]@TestTimestamp -> address[1]@contract 0utz (Right address[2]@account)
+   timestamp: 2019-01-08 11:00:00 +00:00
+   live contracts: <anonymous> (0utz) address[2]@account
+                   Timestamp (10utz) address[1]@contract
+
+running TRANSFER[uid:5] address[0]@TestTimestamp -> address[1]@contract 0utz (Right address[2]@account)
+   timestamp: 2019-01-08 11:00:00 +00:00
+=> live contracts: <anonymous> (0utz) address[2]@account
+                   Timestamp (10utz) address[1]@contract
+
+applying operation TRANSFER[uid:6] address[1]@contract -> address[2]@account 10utz Unit
+   timestamp: 2019-01-08 11:00:00 +00:00
+   live contracts: <anonymous> (0utz) address[2]@account
+                   Timestamp (10utz) address[1]@contract
+
+running TRANSFER[uid:6] address[1]@contract -> address[2]@account 10utz Unit
+   timestamp: 2019-01-08 11:00:00 +00:00
+=> live contracts: <anonymous> (10utz) address[2]@account
+                   Timestamp (0utz) address[1]@contract
+
+running test script...
+   timestamp: 2019-01-08 11:00:00 +00:00
+
+Done running test `TestTimestamp`
+
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + +