Writing Your First Plutus Smart Contract

img

8) Writing Your First RedeemerScript

If you recall, a RedeemerScript is a piece of data that is sent along with a collectFromScript call. It ends up being used in the ValidatorScript as the first input. We will be writing our own in this section.

Similar to the DataScript, creating a RedeemerScript is nearly identical. Let’s look at our current withdraw function.

1
2
withdrawADA :: MockWallet ()
withdrawADA = collectFromScript myFirstValidator unitRedeemer

First, let’s add the ability to input a PIN number when calling withdrawADA via the Plutus Playground.

1
2
withdrawADA :: Int -> MockWallet ()
withdrawADA pin = collectFromScript myFirstValidator unitRedeemer

Now we’ll build the RedeemerScript using the submitted PIN number and the RedeemerScript constructor.

1
2
withdrawADA :: Int -> MockWallet ()
withdrawADA pin = collectFromScript myFirstValidator (RedeemerScript (lifted pin) )

The whole process is pretty much the same as building our DataScript in the previous section.

Continuing, we will also add the submitted PIN number as input to our ValidatorScript.

1
2
3
myFirstValidator :: ValidatorScript
myFirstValidator = ValidatorScript (fromCompiledCode $$(PlutusTx.compile
    [|| \(submittedPIN :: Int) (myPIN :: Int) (c :: ()) -> ()  ||]))

And that concludes implementing our RedeemerScript.

But we are not done yet. To end this section off, we will also specify the final input to our smart contract. However, we must add one more import before we get there.

1
import Ledger.Validation

Now we can specify the input.

1
2
3
myFirstValidator :: ValidatorScript
myFirstValidator = ValidatorScript (fromCompiledCode $$(PlutusTx.compile
    [|| \(submittedPIN :: Int) (myPIN :: Int) (p :: PendingTx') -> ()  ||]))

As you can see, the final input is of the type PendingTx'. This is the pending transaction tied to the running of the smart contract. It contains various pieces of data including block height, transaction fee, inputs, outputs, etc. In this current lesson we won’t be using any of it, however it is good to know that it is available for you to use and play around with in the future.

Here is the compilation of what we’ve done so far.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module MyFirstPlutusSmartContract where

import qualified Language.PlutusTx            as PlutusTx
import           Ledger
import           Wallet
import           Ledger.Validation
import           Playground.Contract


myFirstValidator :: ValidatorScript
myFirstValidator = ValidatorScript (fromCompiledCode $$(PlutusTx.compile
    [|| \(submittedPIN :: Int) (myPIN :: Int) (p :: PendingTx') -> ()  ||]))
   
smartContractAddress :: Address'
smartContractAddress = scriptAddress myFirstValidator

watchSmartContract :: MockWallet ()
watchSmartContract = startWatching smartContractAddress

depositADA :: Int -> Value -> MockWallet ()
depositADA pin val = payToScript_ smartContractAddress val (DataScript (lifted pin))

withdrawADA :: Int -> MockWallet ()
withdrawADA pin = collectFromScript myFirstValidator (RedeemerScript (lifted pin))

$(mkFunction 'watchSmartContract)
$(mkFunction 'depositADA)
$(mkFunction 'withdrawADA)

Test it out for yourself, make sure it compiles, and try using the new withdrawADA UI. In the next section, we will finally be writing our smart contract logic and locking deposited ada with a PIN number.