Code

For the sake of brevity, we skip the app_id key in lock_state, which enables the lock state to provide the exclusivity option to the lock consuming dApps. We will add this detail later.

Lock State: (uint64 lock_balance, uint64 end_time)

Lock() function

  1. subtracts lock_amount from balance and adds it to lock_balance.

  2. leaves the end_time the same or increases it to msg_endTime it if msg_endTime is greater.

The following set of rules prevent double spending and allow us to have a simple, secure and low cost implementation.

The jetton-wallet contract

  1. can not undo a locking operation.

  2. can unlock the full lock_balance ONLY after end_time.

  3. can add more locks to the lock state provided that end_time can stay the same or increase.

Lock Code in Alice's DAOL jetton-wallet contract:

// Replace // with ;; for commenting lines in Func code editor.
```func
() lock_tokens (slice in_msg_body, slice sender_address, int msg_value, int fwd_fee) impure {
  //;; NOTE we can not allow fails in action phase since in that case there will be
  //;; no bounce. Thus check and throw in computation phase.
  (int balance, int lock_balance, int endtime, slice owner_address, slice jetton_master_address, cell jetton_wallet_code) = load_data();
  int query_id = in_msg_body~load_uint(64);
  int lock_amount = in_msg_body~load_coins();
  int msg_endtime = in_msg_body~load_uint(64);
  slice response_address = in_msg_body~load_msg_addr();
  //;; ignore custom payload
  //;; slice custom_payload = in_msg_body~load_dict();
  
  //;; instead of using custom_payload we preferred to introduce lock_balance and endtime
  //;; state variables explicitly to describe behaviour easily.
  //;; in the TEP proposal version the lock state includes app_id for exclusivity option.
  //;; The locking consumer dapps that demand exclusivity will check app_id 

  int newBalance = balance - lock_amount;
  //;; locking cannot exceed balance
  //;; if user tries to lock more than balance 
  //;; we do not reject but cap the lock at balance
  if (newBalance < 0){ 
    lock_amount = balance;
    balance = 0;
  } else {
    balance = newBalance;
    lock_balance += lock_amount;
  }
  //;; user can only increase endtime (prevention against double spend)
  if (msg_endtime > endtime) {endtime = msg_endtime;}
  
  throw_unless(705, equal_slices(owner_address, sender_address));
  //;; throw_unless(706, balance >= 0);
  throw_unless(707, msg_value > fwd_fee + 2 * gas_consumption);
  
  var msg_body = begin_cell()
      .store_uint(op::lock_notification(), 32)
      .store_uint(query_id, 64)
      .store_coins(lock_amount)
      .store_uint(endtime, 64)
      .store_slice(owner_address)
      .store_slice(response_address)
      .end_cell();

  var msg = begin_cell()
    .store_uint(0x18, 6)
    .store_slice(jetton_master_address)
    .store_coins(0)
    .store_uint(1, 1 + 4 + 4 + 64 + 32 + 1 + 1)
    .store_ref(msg_body);

  send_raw_message(msg.end_cell(), 64);

  save_data(balance, lock_balance, endtime, owner_address, jetton_master_address, jetton_wallet_code);
}
```

Last updated