Writing Your First Plutus Smart Contract

img

6) Withdrawing Funds From The Smart Contract

Withdrawing funds from a smart contract is quite similar to depositing funds. In this case however we are going to be using the function collectFromScript. In regards to inputs, it takes:

  1. A ValidatorScript.
  2. A RedeemerScript.

You may have noticed that this takes less inputs than payToScript_, and this is because it attempts to collect all ada from the smart contract. The first input is the ValidatorScript itself (not the address like in the last section) and a RedeemerScript. A RedeemerScript is very much so like a DataScript where it is any kind of data which is relevant to the smart contract at hand. Of course the type of data will have to be specified at some point, but it enables an infinite number of possibilities of types of input.

Now let’s write out the type signature of our withdrawal function.

1
withdrawADA :: MockWallet ()

Simple enough, right? This isn’t anything we haven’t seen before. withdrawADA is simply a function that causes some sort of Wallet action. Now for the definition.

1
withdrawADA = collectFromScript myFirstValidator unitRedeemer

As you can see the RedeemerScript is provided to our collectFromScript call as unitRedeemer. Just like unitData is the default empty DataScript, unitRedeemer is the default empty RedeemerScript. With this function our wallet will send the RedeemerScript to the smart contract and if it validates/doesn’t run into any errors, then our wallet will collect all of the ada from the smart contract. Since we have an empty ValidatorScript there is no logic that will be processed on the collectFromScript call, and thus all withdrawals will be allowed (for the time being).

Finally we need to make the Plutus Playground aware once more of our new function.

1
$(mkFunction 'withdrawADA)

And we have now completed adding the ability to withdraw ada from the smart contract.

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
module MyFirstPlutusSmartContract where

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


myFirstValidator :: ValidatorScript
myFirstValidator = ValidatorScript (fromCompiledCode $$(PlutusTx.compile
    [|| \(a :: ()) (b :: ()) (c :: ()) -> ()  ||]))
   
smartContractAddress :: Address'
smartContractAddress = scriptAddress myFirstValidator

watchSmartContract :: MockWallet ()
watchSmartContract = startWatching smartContractAddress

depositADA :: Value -> MockWallet ()
depositADA val = payToScript_ smartContractAddress val unitData

withdrawADA :: MockWallet ()
withdrawADA = collectFromScript myFirstValidator unitRedeemer

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

Compile this code yourself in the Plutus Playground and try testing depositing and withdrawing ada. Remember, you need to call watchSmartContract first in the Action Sequence for each wallet you wish to keep track of the state of the smart contract.

In our next section, we will cover how to create our very first DataScript.