Public functions
Public functions are callable from the outside by both standard principals and contract principals. Contracts that feature any interactivity will need at least one public function. The fact of them being callable does not imply that the underlying functionality is public. The developer can include assertions to make sure that only specific contract callers or inputs are valid.
Public functions must return a
response type value. If the function
returns an ok
type, then the function call is considered valid, and any
changes made to the blockchain state will materialise. It means that state
changes such as updating variables or transferring tokens will only be
committed to the chain if the contract call that triggered these changes returns
an ok
.
The effects of returning an ok
or an err
are illustrated by the example
below. It is a basic function that takes an unsigned integer as an input and
will return an ok
if it is even or an err
if it is uneven. It will also
increment a variable called even-values
at the start of the function. To check
if the number is even, we calculate the remainder of a division by two and check
that it is equal to zero using the is-eq
function (n mod 2 should equal 0).
(define-data-var even-values uint u0)
(define-public (count-even (number uint))
(begin
;; increment the "event-values" variable by one.
(var-set even-values (+ (var-get even-values) u1))
;; check if the input number is even (number mod 2 equals 0).
(if (is-eq (mod number u2) u0)
(ok "the number is even")
(err "the number is uneven")
)
)
)
;; Call count-even two times.
(print (count-even u4))
(print (count-even u7))
;; Will this return u1 or u2?
(print (var-get even-values))
Did you notice how the final print expression returned u1
and not u2
, even
though the count-even
function is called twice? If you are used to programming
in a different language, for example JavaScript, then it might strike you as
odd: the even-values
variable is updated at the start of the function so it
seems intuitive that the number should increment on every function call.
Edit the example above and try going through the following iterations:
- Replace the uneven number
u7
with an even number likeu8
. Does the printout ofeven-values
containu1
oru2
? - Change the
err
type in theif
expression to anok
. What is the value ofeven-values
then?
What happens is that the entire public function call is rolled back or
reverted as soon as it returns an err
value. It is as if the function call
never happened! It therefore does not matter if you update the variable at the
start or end of the function.
Understanding responses and how they can affect the chain state is key to being a successful smart contract developer. The chapter on error handling will go in greater detail on how to guard your functions and the exact control flow.
(define-public (sum-three)
)
(print (sum-three u3 u5 u9))