Payable Actions
Goal
This tutorial illustrates how to write a smart contract that has payable actions. Payable actions are actions that require you to transfer some tokens to actions prior to use other functionality of the smart contract. Also, the Antelope asset type is covered in this tutorial.
As for the logic of this smart contract, we're going to write a contract that accepts a particular token but will not allow the tokens to be withdrawn for a specific amount of time.
The token to HODL
First create a standard C++ class called "hodl" that extends eosio::contract.
#include <eosio/eosio.hpp>
using namespace eosio;
class [[eosio::contract("hodl")]] hodl : public eosio::contract{
private:
public:
}This contract needs to set up a few constraints:
What symbol/token does this contract accept?
When is the hodl over?
Let us now define these constraints as constants:
hodl_symbol: the symbol of tokens this contract accepts. In this case, we use the "SYS" symbol.the_partyconstant sets the hodl to end on Tuesday, February 22, 2022 10:22:22 PM.
Next, let's define a table to track the number of tokens the hodl contract has received.
In this multiple index table declaration, a new type called asset is used. An asset is a type designed to represent a digital token asset. See more details in the asset reference documentation.
The symbol member of an asset instance will be used as the primary key. By calling the raw() function the symbol variable will be converted into an unsigned integer so it can be used as a primary key.
Constructor
The constructor initializes the hodl_symbol as “SYS”, which is a token created in the Deploy, Issue and Transfer Tokens section.
Get current UTC time
In order to get time in UTC timezone throughout the code, create a function to easily access the current UTC time.
Next, we'll write the actions of the contract.
Deposit
To accept a transfer we need to have a deposit action.
This action should not introduce many new concepts if you have followed this tutorial from the beginning.
Firstly, the action checks that the contract is not transferring to itself:
The contract needs to do so because transferring to the contract account itself would create an invalid booking situation in which an account could have more tokens than the account has in the eosio.token contract.
Then this action checks a few other conditions:
The time to withdraw has not already passed
The incoming transfer has a valid amount of tokens
The incoming transfer uses the token we specify in the constructor
If all constraints are passed, the action updates the balances accordingly:
The important thing to note is the deposit function will actually be triggered by the eosio.token contract. To understand this behaviour we need to understand the on_notify attribute.
The on_notify attribute
The on_notify attribute is one of the EOSIO.CDT attributes that annotates a smart contract action.
Annotating an action with an on_notify attribute ensures any incoming notification is forwarded to the annotated action if and only if the notification is dispatched from a specified contract and from a specified action.
In this case, the on_notify attribute ensures the incoming notification is forward to the deposit action only if the notification comes from the eosio.token contract and is from the eosio.token's transfer action.
This is also why we don't need to check if the hodler actually has the appropriate amount of tokens he or she claimed, as the eosio.token contract would have done this check prior to the transfer notification reaching the hodl deposit action.
Party!
The party action will only allow withdrawals after the configured the_party time has elapsed. The party action has a similar construct as the deposit action with the following conditions:
check the withdrawing account is the account which made the deposit initially
find the locked balance
transfer the token on behalf of the account to the account itself
The complete code listing is the following:
Great, let's deploy it.
Test deposit
First, create an account and deploy to it:
As mentioned in a previous tutorial, this contract needs an eosio.code permission:
Next, create a testing account:
Let's transfer some SYS tokens issued in the previous section to han:
Finally, transfer some SYS tokens to the hodl contract from han's account.
Test withdraw
To test the withdrawal feature, the the_party variable needs to be updated. Update the the_party variable to a point in time in the past so the withdrawal functionality can be tested.
Withdrawing the funds:
Should produce the following response:
Party time!
Last updated