Vesting contract
To put what we've done so far to use we're going to build a simple 'vesting' contract. This contract will lock up some tokens owned by an owner for a beneficiary that can't be claimed until after a deadline. The owner can get their funds back if the deadline has not passed yet
Datum
The datum stores the PubKeyHash
of the beneficiary and creator's wallets and the vesting deadline is represented as a Time
.
struct Datum {
creator: PubKeyHash
beneficiary: PubKeyHash
deadline: Time
}
Note: The
Time
type represents a POSIX time and for more info Helios Builtins.
Redeemer
enum Redeemer {
Cancel
Claim
}
There are two cases when the validator should return true
:
-
Cancel
In this case, the 'owner' wishes to cancel the contract and get back their funds. For a 'Cancel' to succeed the following have to be checked
- The owner signed the transaction.
- The deadline hasn't passed.
-
Vesting Claim
A 'Claim' occurs when the 'beneficiary' wishes to claim the tokens vested for them. For it to be valid the following have to be checked:
- The beneficiary signed the transaction.
- The deadline has passed.
main
func main(datum: Datum, redeemer: Redeemer, context: ScriptContext) -> Bool {
tx: Tx = context.tx;
now: Time = tx.time_range.start;
redeemer.switch {
Cancel => {
// Check that deadline hasn't passed
now < datum.deadline &&
// Check that the owner signed the transaction
tx.is_signed_by(datum.creator)
},
Claim => {
// Check that deadline has passed.
now > datum.deadline &&
// Check that the beneficiary signed the transaction.
tx.is_signed_by(datum.beneficiary)
}
}
}
Complete code
spending vesting
struct Datum {
creator: PubKeyHash
beneficiary: PubKeyHash
deadline: Time
}
enum Redeemer {
Cancel
Claim
}
func main(datum: Datum, redeemer: Redeemer, context: ScriptContext) -> Bool {
tx: Tx = context.tx;
now: Time = tx.time_range.start;
redeemer.switch {
Cancel => {
now < datum.deadline &&
tx.is_signed_by(datum.creator)
},
Claim => {
now > datum.deadline &&
tx.is_signed_by(datum.beneficiary)
}
}
}