# 
        Vesting Example
    
        # 
        Homework
    
Lecture 3, Part 7
        # 
        Homework 1
    
Homework 1 is to implement an on-chain validator that allows a wallet to lock ADA in a contract. The contract has beneficiary addresses and a deadline. Before the deadline, only beneficiary 1 should be able to grab the ADA. But after the deadline, only beneficiary 2 should be able to grab the ADA.
My solution uses guards to match 2 cases:
- Where beneficiary 1 signed and the deadline not reached
 - Where beneficiary 2 signed and deadline reached
 
Otherwise, false.
I use where to define some helper expressions. signedByBeneficiary1 and 2
are modeled after signedByBeneficiary in Vesting.hs. The other expressions
are taken right out of Vesting.hs with no changes necessary.
I use deadlineReached with the not function to reverse it when I want to
check if the deadline has not been reached.
Here's the fixed validator:
mkValidator :: VestingDatum -> () -> ScriptContext -> Bool
mkValidator dat () ctx
  | signedByBeneficiary1 && not deadlineReached = True
  | signedByBeneficiary2 &&     deadlineReached = True
  | otherwise                                   = False
    where
      info :: TxInfo
      info = scriptContextTxInfo ctx
      signedByBeneficiary1 :: Bool
      signedByBeneficiary1 = txSignedBy info $ unPaymentPubKeyHash $ beneficiary1 dat
      signedByBeneficiary2 :: Bool
      signedByBeneficiary2 = txSignedBy info $ unPaymentPubKeyHash $ beneficiary2 dat
      deadlineReached :: Bool
      deadlineReached = contains (from $ deadline dat) $ txInfoValidRange info
        # 
        Homework 2
    
Homework 2 is to write a validator that parameterizes the Vesting.hs. This
time the beneficiary and the datum are split into two separate parameters
instead of a single data type.
The type signature looks like this:
mkValidator :: PaymentPubKeyHash -> POSIXTime -> () -> ScriptContext -> Bool
I wrote the validator by copying from Vesting.hs and replacing dat (which
was the custom data type containing both parameters) with two separate
parameters beneficiary deadline.
mkValidator beneficiary deadline () ctx =
The body of the validator is the same as Vesting.hs, but with the parameters
referenced directly instead of through dat.
mkValidator beneficiary deadline () ctx =
  traceIfFalse "beneficiary's signature missing" signedByBeneficiary &&
  traceIfFalse "deadline not reached" deadlineReached
    where
        info :: TxInfo
        info = scriptContextTxInfo ctx
        signedByBeneficiary :: Bool
        signedByBeneficiary = txSignedBy info $ unPaymentPubKeyHash $ beneficiary
        deadlineReached :: Bool
        deadlineReached = contains (from $ deadline) $ txInfoValidRange info
The typedValidator is copied almost exactly from Parameterized.hs. The only
change is the parameters passed to Scripts.wrapValidator take into account the
deadline POSIXTime parameter.
typedValidator :: PaymentPubKeyHash -> Scripts.TypedValidator Vesting
typedValidator p = Scripts.mkTypedValidator @Vesting
    ($$(PlutusTx.compile [|| mkValidator ||]) `PlutusTx.applyCode` PlutusTx.liftCode p)
    $$(PlutusTx.compile [|| wrap ||])
  where
    wrap = Scripts.wrapValidator @POSIXTime @()
The validator and scrAddress are copied straight from Parameterized.hs.