Transfers, contract calls

Transfer

The transfer instruction is used to transfer Tezis to an account.

effect {
transfer 1tez to coder;
}

where coder is a role variable.

Calling a contract

It is possible to call a smart contract with the transfer instruction. Say for example you want to call the set_value entry point of the following contract:

archetype contract_called
variable v : nat = 0
entry set_value(x : nat) { v := x }

The contract may then be called with the transfer ... to ... call ... instruction:

effect {
var c = @KT1RNB9PXsnp7KMkiMrWNMRzPjuefSWojBAm;
transfer 0tez to c call add_value<nat>(3);
}

Note that it fails if the contract at address c does not provide an entry point annotated %add_value

Self

It is possible to call the current contract itself. Say the current contract has the my_add_value entry point; it is possible to call it from another entry point with the following instruction:

entry my_add_value(int a, int b) {
sum := a + b;
}
entry add_1_3 () {
transfer 0tez to entry self.my_add_value(1,3)
}

Getter & entrysig

A common pattern for contracts to exchange values is to call an entry point with a callback.

This pattern is presented in the two-way-inter-contract invocation article below:

The archetype version of the sender contract (see article above):

archetype sender
variable bar : int = 0
getter getBar () { return bar }
entry setBar (b : int) { bar := b }

It uses the getter keyword used to declare an entry point to the contract called "getBar"; the Michelson version of this entry actually takes a callback function (a setter) used to set/use the bar value in another contract. It is syntactic sugar equivalent to the following entry declaration:

entry getBar (cb : entrysig<int>) { transfer 0tz to entry cb(bar) }

The entrysig type is used to declare the callback type; it is parametrized by the signature of the callback, represented as the tuple of argument types.

The difference between the getter and entry versions of the getBar entry above is that the callback argument is anonymous in the getter version.

The archetype version of the inspector contract (see article above):

archetype inspector
variable foo : int = 0
entry setFoo(v : int) { foo := v }
entry getFoo(asender : address) {
transfer 0tez to asender call getBar<entrysig<int>>(self.setFoo)
}

Entrypoint

The entrypoint function may be used to build an entrysig value from the name and the address. It returns an option value of entrysig type, so that it is possible to handle the case when the entry point does not exist.

The above inspector contract may be rewritten as:

archetype inspector
variable foo : int = 0
entry setFoo(v : int) { foo := v }
entry getFoo(asender : address) {
var entryopt = entrypoint<entrysig<int>>("%getBar", asender);
if issome(entryopt) then (
var e = opt_get(entryopt);
transfer 0tez to entry e(self.setFoo))
else fail("could not find getBar entry or invalid address")
}