--- id: first-contract title: First contract --- So far so good, we have learned enough of the LIGO language, we are confident enough to write out first smart contract. We will be implementing a counter contract. ## Dry-running a Contract Testing a contract can be quite easy if we utilize LIGO's built-in dry run feature. Dry-run works by simulating the access function execution, as if it were deployed on a real chain. You need to provide the following: - `file` - contract to run - `entrypoint` - name of the function to execute - `parameter` - parameter passed to the access function (in a theoretical invocation operation) - `storage` - a mock storage value, as if it were stored on a real chain Here is a full example: ``` ligo dry-run src/basic.ligo main Unit Unit // Outputs: // tuple[ list[] // Unit // ] ``` Output of the `dry-run` is the return value of our access function, we can see the operations emited - in our case an empty list, and the new storage value being returned - which in our case is still `Unit`. ## A Counter Contract Our counter contract will store a single `int` as it's storage, and will accept an `action` variant in order to re-route our single `main` access function to two entrypoints for `addition` and `subtraction`. ``` type action is Increment of int | Decrement of int function main (const p : action ; const s : int) : (list(operation) * int) is ((nil : list(operation)), (case p of | Increment (n) -> s + n | Decrement (n) -> s - n end)) ``` ```cameligo type action = | Increment of int | Decrement of int let main (p, s: action * int) : operation list * int = let result = match p with | Increment n -> s + n | Decrement n -> s - n in (([]: operation list), result) ``` ```reasonligo type action = | Increment(int) | Decrement(int); let main = (p_s: (action, int)) : (list(operation), int) => { let p, s = p_s; let result = switch (p) { | Increment(n) => s + n | Decrement(n) => s - n }; (([]: list(operation)), result); }; ``` To dry-run the counter contract, we will use the `main` entrypoint, provide a variant parameter of `Increment(5)` and an initial storage value of `5`. ``` ligo dry-run src/counter.ligo main "Increment(5)" 5 // tuple[ list[] // 10 // ] ``` Our contract's storage has been successfuly incremented to `10`. ## Deploying and interacting with a contract on a live-chain In order to deploy the counter contract to a real Tezos network, we'd have to compile it first, this can be done with the help of the `compile-contract` CLI command: ``` ligo compile-contract src/counter.ligo main ``` Command above will output the following Michelson code: ``` { parameter (or (int %decrement) (int %increment)) ; storage int ; code { DUP ; CAR ; DIP { DUP } ; SWAP ; CDR ; DIP { DUP } ; SWAP ; IF_LEFT { DUP ; DIP 2 { DUP } ; DIG 2 ; DIP { DUP } ; SUB ; SWAP ; DROP ; SWAP ; DROP } { DUP ; DIP 2 { DUP } ; DIG 2 ; DIP { DUP } ; ADD ; SWAP ; DROP ; SWAP ; DROP } ; NIL operation ; PAIR ; SWAP ; DROP ; SWAP ; DROP ; SWAP ; DROP } } ``` However in order to originate a Michelson contract on Tezos, we also need to provide the initial storage value, we can use `compile-storage` to compile the LIGO representation of the storage to Michelson. ``` ligo compile-storage src/counter.ligo main 5 // Outputs: 5 ``` In our case the LIGO storage value maps 1:1 to its Michelson representation, however this will not be the case once the parameter is of a more complex data type, like a record. ## Invoking a LIGO contract Same rules apply for parameters, as apply for translating LIGO storage values to Michelson. We will need to use `compile-parameter` to compile our `action` variant into Michelson, here's how: ``` ligo compile-parameter src/counter.ligo main 'Increment(5)' // Outputs: (Right 5) ``` Now we can use `(Right 5)` which is a Michelson value, to invoke our contract - e.g. via `tezos-client`