Skip to main content

Trigger Events

Smart contracts operate in a confined environment but need a mechanism to interact with users. A solution to this is triggering events, which is facilitated through smart contracts.

ISC Sandbox Interface

The ScFuncContext Call Context in ISC SandboxA controlled environment where programs can be tested safely. has an event() function to support event triggering. This function takes a text string parameter, requiring creators and users to maintain and understand the chosen format. However, this setup is prone to errors and inconsistency due to the arbitrary nature of the text strings used.

Structured Events with Schema Tool

To mitigate issues stemming from the rudimentary interface, use the Schema Tool to define structured events, making event creation and handling more consistent and less error-prone.

This tool allows you to establish structured events that are integrated into all Func function contexts. Note that events:

  • Can only be triggered within a Func
  • Become part of the smart contract's state
  • Are logged in the core blocklog contract
  • Cannot be triggered within a View

Event Structure

Define each event in the events section of the schema definition file. This setup ensures that events are encoded consistently, utilizing a function that automatically formats the event string with the event name, timestamp, and parameter fields, delimited by vertical bars. This structured approach facilitates streamlined, error-resistant event triggering.

Example

Here is the events section that can be found in the demo fairroulette smart contract:

events:
bet:
address: Address # address of better
amount: Uint64 # amount of tokens to bet
number: Uint16 # number to bet on
payout:
address: Address # address of winner
amount: Uint64 # amount of tokens won
round:
number: Uint32 # current betting round number
start:
stop:
winner:
number: Uint16 # the winning number

The Schema Tool will generate events.xx which contains the following code for the FairRouletteEvents struct:

package fairroulette

import "github.com/iotaledger/wasp/packages/wasmvm/wasmlib/go/wasmlib"
import "github.com/iotaledger/wasp/packages/wasmvm/wasmlib/go/wasmlib/wasmtypes"

type FairRouletteEvents struct {
}

func (e FairRouletteEvents) Bet(
// address of better
address wasmtypes.ScAddress,
// amount of tokens to bet
amount uint64,
// number to bet on
number uint16,
) {
evt := wasmlib.NewEventEncoder("fairroulette.bet")
evt.Encode(wasmtypes.AddressToString(address))
evt.Encode(wasmtypes.Uint64ToString(amount))
evt.Encode(wasmtypes.Uint16ToString(number))
evt.Emit()
}

func (e FairRouletteEvents) Payout(
// address of winner
address wasmtypes.ScAddress,
// amount of tokens won
amount uint64,
) {
evt := wasmlib.NewEventEncoder("fairroulette.payout")
evt.Encode(wasmtypes.AddressToString(address))
evt.Encode(wasmtypes.Uint64ToString(amount))
evt.Emit()
}

func (e FairRouletteEvents) Round(
// current betting round number
number uint32,
) {
evt := wasmlib.NewEventEncoder("fairroulette.round")
evt.Encode(wasmtypes.Uint32ToString(number))
evt.Emit()
}

func (e FairRouletteEvents) Start() {
evt := wasmlib.NewEventEncoder("fairroulette.start")
evt.Emit()
}

func (e FairRouletteEvents) Stop() {
evt := wasmlib.NewEventEncoder("fairroulette.stop")
evt.Emit()
}

func (e FairRouletteEvents) Winner(
// the winning number
number uint16,
) {
evt := wasmlib.NewEventEncoder("fairroulette.winner")
evt.Encode(wasmtypes.Uint16ToString(number))
evt.Emit()
}

Notice how the generated functions use the WasmLib EventEncoder to encode the parameters into a single string before emitting it. Here is the way in which fairroulette emits the bet event in its smart contract code:

    f.Events.Bet(bet.Better.Address(), bet.Amount, bet.Number)

The smart contract client code can define handler functions to listen in to the event stream and respond to any events it deems noteworthy. The Schema Tool will automatically generate the necessary client side code that properly listens for the events, parses the event strings into a type-safe structure, and passes this structure to the corresponding handler function.