Smart Contracts

A smart contract is a piece of bytecode that can be deployed to a blockchain via a transaction.

It can be called in the same way that an API may be called to perform computation and store and retrieve data from a database.

A smart contract consists of two parts:

Application Binary Interface (ABI)

The ABI is a structure which defines the endpoints that a contract exposes for calls. That is to say that functions defined in the ABI are considered to be external and thus a contract cannot call its own functions.

The following example demonstrates an interface for a wallet which is able to receive and send funds.

The structure begins by using the keyword abi followed by the name of the contract.

Inside the declaration are function signatures, annotations denoting the interaction with storage and documentation comments outlining the functionality.

library;

abi Wallet {
    /// When the BASE_ASSET is sent to this function the internal contract balance is incremented
    #[storage(read, write)]
    fn receive_funds();

    /// Sends `amount_to_send` of the BASE_ASSET to `recipient`
    ///
    /// # Arguments
    ///
    /// - `amount_to_send`: amount of BASE_ASSET to send
    /// - `recipient`: user to send the BASE_ASSET to
    ///
    /// # Reverts
    ///
    /// * When the caller is not the owner of the wallet
    /// * When the amount being sent is greater than the amount in the contract
    #[storage(read, write)]
    fn send_funds(amount_to_send: u64, recipient: Identity);
}

Implementation the ABI

Similar to traits in Rust implementing the ABI is done with the syntax impl <name-of-abi> for Contract.

All functions defined in the ABI must be declared in the implementation.

Since the interface is defined outside of the contract we must import it using the use syntax before we can use it.

contract;

use interface::Wallet;

impl Wallet for Contract {
    #[storage(read, write)]
    fn receive_funds() {
        // function implementation
    }

    #[storage(read, write)]
    fn send_funds(amount_to_send: u64, recipient: Identity) {
        // function implementation
    }
}