Skip to content

Smart Contract Examples

Blockmatic Contract List provides a ton of example links to various smart contracts that are available.

However, you might be just looking for a quick way to perform basic functionality inside of your smart contract.

Require Authorization Action

Requires permission from the name passed from the client to transact.

Code
cpp
ACTION hi(name user) {
    require_auth(user);
}

Actions with More Parameters

When you need to add more parameters to your action.

Code
cpp
ACTION hi(name user, string message) {
    print("Hello, your message was: ", message);
}

CRUD Operations

When you want to create a data entry, store it, update it, and delete that entry from a table.

The code below is a simple 'set your status' contract.

Code
cpp
#include <eosio/eosio.hpp>
#include <eosio/print.hpp>

using namespace std;
using namespace eosio;

CONTRACT status : public eosio::contract {
    using eosio::contract::contract;
    
    public:
        ACTION setstatus(name& user, string& status) {
            require_auth(user);
            
            auto info_itr = info.find(user.value);
            if (info_itr == info.end()) {
                // This creates an entry in the table for the user
                info.emplace(user, [&](status_struct &_info) {
                    _info.user = user.value;
                    _info.status = status;
                });
            } else {
                // This modifies an existing entry, and sets existing data.
                info.modify(info_itr, same_payer, [&](status_struct &_info) {
                    _info.status = status;
                });
            }

            print(user.to_string(), " has set their status to: ", status);
        }

        ACTION rmvstatus(name& user) {
            require_auth(user);

            // This requires an entry to exist; before proceeding any further
            auto info_itr = info.require_find(user.value, "user does not have any entries");

            // This empties the table entry for the specified user
            info.erase(info_itr);

            print(user.to_string(), " removed table entry");
        }

    private:
        TABLE status_struct {
            uint64_t user;
            string status;
        
            uint64_t primary_key() const {
                return user;
            }
        };

        typedef multi_index<name("status"), status_struct> status_t;
        status_t info = status_t(get_self(), get_self().value);
};

// Trevor Wessel - 2023

Scoped CRUD Operations

When you want to create a data entry, store it, update it, and delete that entry from a table owned by a user.

This means that table entries are owned by the user for their specific table. Only they can modify their entries.

The code below is the equivalent of a Twitter clone.

Code
cpp
#include <eosio/eosio.hpp>
#include <eosio/print.hpp>
#include <eosio/system.hpp>

using namespace std;
using namespace eosio;

CONTRACT journal : public eosio::contract {
    using eosio::contract::contract;
    
    public:
        ACTION add(name& user, string& message) {
            require_auth(user);

            check(message.size() <= 256, "Message cannot exceed 256 bytes");

            auto current_time = get_current_time();

            // This makes it so that multiple users can have a 'journal'
            // They have their own tables which are scoped to their name
            // They can only add entries to the table which they own
            journal_t scoped_journal = journal_t(get_self(), user.value);
            auto journal_itr = scoped_journal.find(current_time);

            check(journal_itr == scoped_journal.end(), "Entry already exists for this timepoint");

            scoped_journal.emplace(user, [&](journal_struct &_entry) {
                _entry.date = user.value;
                _entry.message = message;
            });

            print(user.to_string(), " added a new entry at ", current_time);
        }

        ACTION edit(name& user, uint32_t& timepoint, string& message) {
            require_auth(user);

            journal_t scoped_journal = journal_t(get_self(), user.value);
            auto journal_itr = scoped_journal.require_find(timepoint, "entry was not found");
   
            scoped_journal.modify(journal_itr, user, [&](journal_struct &_entry) {
                _entry.message = message;
            });

            print(user.to_string(), " updated entry at ", timepoint);
        }

        ACTION remove(name& user, uint32_t& timepoint) {
            require_auth(user);

            journal_t scoped_journal = journal_t(get_self(), user.value);
            auto journal_itr = scoped_journal.require_find(timepoint, "entry was not found");
            scoped_journal.erase(journal_itr);

            print(user.to_string(), " removed journal entry at ", timepoint);
        }

    private:
        // table: journal, scope: name
        TABLE journal_struct {
            uint32_t date;
            string message;
        
            uint32_t primary_key() const {
                return date;
            }
        };

        typedef multi_index<name("journal"), journal_struct> journal_t;

        uint32_t get_current_time() {
            return eosio::current_block_time().to_time_point().sec_since_epoch();
        }
};

// Trevor Wessel - 2023

Reading Data from Table Iterators

In some cases, you may need to read directly from a table in a contract.

You can use the iterator to directly access the data.

The code below is based on the Scoped CRUD Operations

Code
cpp
journal_t scoped_journal = journal_t(get_self(), user.value);
auto journal_itr = scoped_journal.require_find(timepoint, "entry was not found");
print("Message at ", timepoint, " is ", journal_itr->message);

Listening for Token Transfers

The code below allows only the default UOS token with a precision of 8.

You must add the eosio.code permission to your account to use this.

Code
cpp
#include <eosio/eosio.hpp>
#include <eosio/print.hpp>
#include <eosio/asset.hpp>
#include <eosio/symbol.hpp>
#include <eosio/system.hpp>

using namespace std;
using namespace eosio;

CONTRACT hello : public eosio::contract {
    using eosio::contract::contract;
    
    public:
        [[eosio::on_notify("eosio.token::transfer")]] void deposit(name from, name to, eosio::asset amount, std::string memo) {
            check(amount.amount > 0, "deposit amount should be positive");

            // We want to ignore any transfers not going to us
            // We want to make sure we are ignoring transfers out from ourselves
            if (to != get_self() || from == get_self()) {
                return;
            }

            check(memo.size() >= 1);
            check(amount.symbol == eosio::symbol('UOS', 8), "Not the token we need. Bye.");
            
            // You can check a memo here after an 'order' is created
            // An order can be given a string value
            // The memo can then be used to find a table entry
        }
};

Listening for Uniq Transfers

If you want to listen for transfers from eosio.nft.ft see onIssue Example.