Minting Token With Time Base

I manage to mint a token in testnet with single issuing minting.
Now I plan to make another token, but in time base minting.
For example, Today I mint 1000coin, and next year I mint another 100coin and so on each year mint 100coin until reach 2000 coin. Any guide how to do this?
Thanks

This may be similar to

If I understand correctly, this can only be done with distinct policies, which makes the tokens from the various batches non-fungible or with a Plutus script (when it becomes available). The pioneer program has not yet touched on it. There is this ScriptPurpose …

Yes, exactly. So, if right now we launch our token with single mint policy, can we alter to multiple mint policy in the future?

If you mint a simple script based token now, it will likely not be fungible with a later plutus script token - at least that is my current understanding.

Yes, tokens minted now with a simple script are forever associated with the monetary policy under which they are minted, and that determines the Policy ID and hence the Asset ID. A future Plutus script couldn’t mint or burn those. However, you could create a Plutus script that would migrate the old tokens to new ones in the same transaction that the old simple script burns the old tokens, provided that the old tokens are allowed to be burned. (If old tokens cannot be burned, then the Plutus script could hold onto the old ones forever and issue the new ones, but the min-ADA requirement might be an issue.)

Regarding the use case in the original post, without Plutus there is no way for the script to enforce a limit on how many are minted, though scripts currently can limit when they can be minted. So, if you wanted, you could create a simple script (and hence one Policy ID) that would allow minting (and burning) only on one particular day each year for (say) the next ten years. That would fix the supply, except for those single days, and the different vintages of tokens would be fungible among themselves.

1 Like

Yes, how to do this? I mean what the script will be if I want to make this simple script. For example, what I’m going to do is mint 1000coin today and exactly next year, 30 April 2022 I will mint another 100coin, 30 April 2023, another 100coin. And after that no more coin can be mint.

The documentation on time locking discusses how to create time constraints on minting and shows how to use “any” and “all” logic to organize multiple conditions. Using a single script with three time windows will give the tokens that same Policy ID, so if they have the same Asset Names, then they will be fungible among the different vintages. We want all minting transactions to be signed by a specified key, plus we want the current slot number to fall in one of three time windows. I’ve annotated the JSON below with comments:

{
  "type" : "all", # The script must be signed and the current slot must fall in one of the time windows.
  "scripts" : [
     {
       "type" : "sig", # Required signature.
       "keyHash" : "f4fa4f219060508b9902bd16de3548ae686e5e69852f93428f453417"
     },
     {
       "type" : "any", # The current slot must be in one of the three windows.
       "scripts" : [
         {
           "type" : "all", # First time window.
           "scripts" : [
             {
               "type" : "after",
               "slot" : 28174507 # 30 April 2021 00:00:00 UTC
             },
             {
               "type" : "before",
               "slot" : 28260907 # 1 May 2021 00:00:00 UTC
             }
           ]
         },
         {
           "type" : "all", # Second time window.
           "scripts" : [
             {
               "type" : "after",
               "slot" : 59710507 # 30 April 2022 00:00:00 UTC
             },
             {
               "type" : "before",
               "slot" : 59796907 # 1 May 2021 00:00:00 UTC
             }
           ]
         },
         {
           "type" : "all", # Third time window.
           "scripts" : [
             {
               "type" : "after",
               "slot" : 91246507 # 30 April 2023 00:00:00 UTC
             },
             {
               "type" : "before",
               "slot" : 91332907 # 1 May 2023 00:00:00 UTC
             }
           ]
         }
       ]
     }
  ]
}

Here is how to compute the future slot numbers: You can run the following command to find, at the same moment, the number of seconds since 1970-01-01 UTC (the first line in the output below) and the tip of mainnet (the “slotNo”) entry.

$ date +%s ; cardano-cli query tip --mainnet
1619790514
{
    "blockNo": 5657639,
    "headerHash": "def691f4900935f9839d8290e51c046f86d3a41764c4f3c115cf49a6e79c75cf",
    "slotNo": 28224221

}

The difference between these is 1591566293. Now we can compute the slot numbers at future dates:

$ date -d '2021-04-30T00:00:00+00:00 - 1591566293 seconds' +%s
28174507

$ date -d '2021-05-01T00:00:00+00:00 - 1591566293 seconds' +%s
28260907

$ date -d '2022-04-30T00:00:00+00:00 - 1591566293 seconds' +%s
59710507

$ date -d '2022-05-01T00:00:00+00:00 - 1591566293 seconds' +%s
59796907

$ date -d '2023-04-30T00:00:00+00:00 - 1591566293 seconds' +%s
91246507

$ date -d '2023-05-01T00:00:00+00:00 - 1591566293 seconds' +%s
91332907

Here are a few important caveats:

  1. One should definitely try this out on testnet before putting it on mainnet. (For example, one can create a script with three time windows over the next week and try to mint inside and outside of the time windows to check that it works correctly.)
  2. When one submits the transactions, use the --invalid-before and --invalid-hereafter flags in cardano-cli transaction build-raw.
  3. One should be careful about time zones, daylight savings time, and leap years. Using the date command handles these.
  4. The slot calculations are probably not accurate to more than a couple of seconds. In particular, UTC can have leap seconds and I also don’t know if the mainnet clock drifts over the years with respect to UTC. I wouldn’t try this with very small time windows like minutes.
  5. I don’t know if it is guaranteed that in the future slots will always last for one second.
  6. One needs to use the exact same script to mint or burn within these time windows, so it is very important to store a permanent copy that can be retrieved years from now.

This is amazing. Thanks… But, let me make this straight.
This will be the policy.script right? and to execute this script

cardano-cli transaction policyid --script-file policy.script

And after that we minting the coin

cardano-cli transaction build-raw
–mary-era
–fee 0
–tx-in b1ddb0347fed2aecc7f00caabaaf2634f8e2d17541f6237bbed78e2092e1c414#0
–tx-out addr_test1vqvlku0ytscqg32rpv660uu4sgxlje25s5xrpz7zjqsva3c8pfckz+1000000000+“1000000000 328a60495759e0d8e244eca5b85b2467d142c8a755d6cd0592dff47b.melcoin”
–mint=“1000000000 328a60495759e0d8e244eca5b85b2467d142c8a755d6cd0592dff47b.melcoin”
–out-file matx.raw

Will be done manually, BUT, must be execute during the time frame that the script allow that to be done.
Right?

Yes, this is the policy script. It can be used for all of the mintings.

In your cardano-cli transaction build-raw example, you’ll need to add --invalid-before 28174507 --invalid-hereafter 28260907 when you submit during the first window; otherwise, you’ll get a validation error when you submit the transaction. And yes, it has to be submitted in this time window. Similarly for future time windows.

Also note that slot numbers are different on testnet, so all of those need to be recomputed from scratch for using a script like this there.

1 Like

Thanks a lot this is really helping me. One more thing, can we limit the amount of coin that we can mint at the specific time frame? For example in second period I only can mint 100coin.

Unfortunately, we have to wait for smart contracts to limit the number minted. A simple Marlowe contract will be able to handle this.

1 Like

Thank you so much dude. I understand now… Really appreciate it.

1 Like

You’re very welcome. Explaining this helped me figure out the most efficient way to convert from calendar dates to slot numbers. It also is prompting me to research how synchronized mainnet slot numbers will be with UTC over the years.

BTW, you can use the Marlowe playground to experiment with a simple contract that limits the number of tokens minted, constrainting minting to time windows, etc. If the Alonzo testnet is available soon, then you can test everything out there.

I think Alonzo testnet already here right now. Not so sure. Anyway, if right now I mint with a single time minting policy, can I change the script later?

Changing the script will change the Policy ID. Any tokens minted by the changed script won’t be fungible with those minted by the original script. Even if you use the same Asset Name, the Asset ID will be different for tokens minted by the two scripts because of the different Policy ID, so they won’t be interchangeable.

Also, I now doubt that Marlowe will support this use case–a Plutus contract might be needed.

1 Like

Hi Bwbush,
I need to confirm one thing. I read the script several time and compare the guide about time locking.
So, if we run this policy is that mean that we only can’t mint and burn the token or we cannot do anything with the token during the locking period?
Because I read this note

Note that this is not really time locking in the normal sense, and indeed this is a very dangerous script to use because any funds left in a script address using this script after time slot 3000 will be locked there permanently!

from here Scripts — cardano-node Documentation 1.0.0 documentation

That’s a very good question, and the documentation could be clearer. There is a difference between using a script to mint a token versus sending funds to a script address:

  1. When you use a script to mint a token, the script (and hence any time locking) only is run to validate transactions that mint or burn the token–it has no effect on other transactions. Thus, you can transfer tokens in non-burning transactions, use them in smart contracts, etc. without any restriction. You can look at pool.pm/tokens and cardanoscan.io etc. to see that time-locked tokens have been transferred between addresses well after they have been locked against further minting or any burning. (Note that a time-locked script for a token does lock in a min-ada value associated with the token, but that is a small amount of ADA.)
  2. A different use case (the one that the quote from the documentation warns against) is using a script as an address for receiving ADA transactions (which may or may not also include tokens). Using a script as an address has nothing to do with using it for minting or burning tokens. In this situation, when one attempts to withdraw funds from the script’s address, the script must validate the transaction. A time-locked script won’t validate a transaction after its time has passed, so any ADA or tokens held by the script are stuck there forever. BTW, script addresses can be useful when several people want to hold ADA in common at the same address (a script address) and only spend them when they all agree; there are many other interesting scenarios for script addresses.

The same scripting language is used for both of these use cases and the mechanics of a script witnessing (i.e., validating) a transaction are the same for both, but a minting script only affects minting/burning whereas a script address affects spending out of that address.

P.S. You can experiment on testnet without concern for accidentally losing tADA (test ADA) in locked scripts or unburnable tokens.

1 Like

Thank you for your prompt reply.
So now I understand what’s the different between only the script and script address.
I try to write the policy.script.
Can I write like this?

{
“type”: “any”
“scripts”:
[
{
“type”: “before”
“slot” : 1000
“keyHash”: “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”,
}
]
}
My question is can I combine type and slot and keyhash one time or must use type and keyhash, then slot and keyhash. So there will be 2 policy.skey
Please correct me if I’m wrong.

You cannot combine slot and keyHash under a single type (as in your example), and (very important) you need to use all instead of any. Here is what the simplest form of time-locked script looks like.

Regarding signing keys, you only need one .skey per unique keyHash. For a simple time-locked script, you’d need one .skey for the script in addition to whatever .skeys you need so sign the inputs for the transaction.

1 Like

Thanks,
So the structure will be

{
  "scripts": [
    {
      "slot": 28860486,
      "type": "before"
    },
    {
      "keyHash": "d4b9b71fffec086c6a75893735183f28b000894f1f717293a7554a65",
      "type": "sig"
    }
  ],
  "type": "all"
}

Slot comes first then the keyhash come with the “sig” right? Any why I need to use all instead of any? Because I only have one sig.