In third weeks plutus pioneer lecture lars said that Vesting period shouldn't be longer than 36 hours. He argued that this is because time is calculated in slots on-chain and that this parameter might change in the future:

There is one slight complication that Ouroboros, the consensus protocol powering Cardano, does not use POSIX time; it uses slots. Plutus uses real time, so we need to be able to convert back and forth between real time and slots. Right now, the slot length is one second. Knowing that, it is easy to go back and forth between real time and slot numbers. However, this could change in future through a parameter change via a hard fork. And, of course, we can't know that in advance.

We do not know right now what the slot length will be in 10 years, for example. This means that we must not have a definite upper bound. We know what the slot length will be in the next 36 hours because if there's a change in protocol parameters, then we know that at least 36 hours in advance.You can not specify arbitrary time ranges in the transaction interval. It must only be at most 36 hours in the future, or it can be indefinite.

I would like to implement vesting smartcontract but for much longer time periods, for example 9 months.


Right now I see two ways to implement restriction by time:

  1. Use txInfoValidRange by specifying transaction valid range. However I see a huge problem here or maybe I just dont' understand tx valid range correctly. Lets say that validator is of alwayssucceeds type but with added tx valid range check. I don't get it how to guarantee that funds are to be locked until specified SLOT, since in this case anyone can build transaction with w/e --invalid-before SLOT parameter they want.
data VestingDatum = VestingDatum
   { deadline    :: POSIXTime
   } deriving Show

{-# INLINABLE mkValidator #-}
mkValidator :: VestingDatum -> () -> ScriptContext -> Bool
mkValidator dat () ctx = traceIfFalse "deadline not reached" deadlineReached
   info :: TxInfo
   info = scriptContextTxInfo ctx

   deadlineReached :: Bool
   deadlineReached = contains (from $ deadline dat) $ txInfoValidRange info
  1. Provide some kind of time NFT from oracle.


  1. What is currently the best way to implement Vesting with longer than 36 hours time periods?
  2. How likely is 1 SLOT == 1 Second parameter to change in the future, when and by how much?
  3. Does universal time NFT oracle exist in Cardano ecosystem?
  4. Is there a way to provide restriction that for funds to be unlocked from the smartcontract transaction must have specific --invalid-before SLOT parameter?

1 Answer 1


Lars is right. There is no guarantee that 1 slot remains equal to 1 second because a parameter update could happen at any time and be applied for future epochs. There are currently no plans to change this and I don't know why it would be changed from 1 second. I also don't know of any specific time oracles, but you're right in thinking this is a viable option.

"anyone can build transaction with w/e --invalid-before SLOT parameter they want.".

This is not true. In your example, deadlineReached will return true provided the transaction's --invalid-before SLOT is equal to or greater than deadline (once converted) regardless of the transaction's upper bound. You cannot submit a transaction with a higher --invalid-before SLOT than the current slot because ledger's phase-1 validation, which is performed for free before any plutus validator script is run, would reject it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.