File Structure
The eosiocpp tool simplifies the work required to bootstrap a new contract. eosiocpp
will create the two smart contract files with the basic skeleton to get you started. These skeleton files are the same .hpp
and .cpp
files for the hello
contract covered in the hello world contract tutorial.
$ eosiocpp -n ${contract}
The above will create a new empty project in the ./${contract}
folder with two files:
${contract}.hpp ${contract}.cpp
hpp
${contract}.hpp
is the header file that contain the variables, constants, and functions referenced by the .cpp
file.
cpp
${contract}.cpp
is the source file that contains the implementations of the functions of the contract.
If you generate the .cpp
file using the eosiocpp
tool, the generated .cpp file would look similar to the following:
using namespace eosio;
class hello : public eosio::contract {
public:
using contract::contract;
/// @abi action
void hi( account_name user ) {
print( "Hello, ", name{user} );
}
};
EOSIO_ABI( hello, (hi) )
The generated skeleton file has one function, hi, that prints the name of the user data parameter passed in the command request.
apply
action handler and the EOSIO_ABI
macro
apply
action handler and the EOSIO_ABI
macroEvery smart contract must provide an apply
action handler. The apply
action handler is a function that listens to all incoming actions and performs the desired behavior. In order to respond to a particular action, code is required to identify and respond to specific actions requests. apply
uses the receiver
, code
, and action
input parameters as filters to map to the desired functions that implement particular actions. The apply
function can filter on the code
parameter using something like the following:
if (code == N(${contract_name}) {
// your handler to respond to particular action
}
Within a given code
, one can respond to a particular action by filtering on the action
parameter. This is normally used in conjunction with the code filter.
if (action == N(${action_name}) {
//your handler to respond to a particular action
}
The EOSIO_ABI
macro
EOSIO_ABI
macroTo simplify the work for contract developers, the EOSIO_ABI
macro encapsulates the lower level action mapping details of the apply
function, enabling developers to focus on their application implementation.
/* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
} \
} \
} \
A developer needs only to specify the code
and action
names from the contract in the macro, and all of the underlying C code mapping logic is generated by the macro. An example of use of the macro can be seen above, i.e., EOSIO_ABI( hello, (hi) )
where hello
and hi
are values from the contract.
In this example you can see there is one function, apply
. All it does is log the actions delivered and makes no other checks. Anyone can deliver any action at any time provided the block producers allow it. Absent any required signatures, the contract will be billed for the bandwidth consumed.
apply
apply
is the action handler, it listens to all incoming actions and reacts according to the specifications within the function. The apply
function requires two input parameters, code
and action
.
code filter
In order to respond to a particular action, structure the apply
function as follows. You may also construct a response to general actions by omitting the code filter.
if (code == N(${contract_name}) {
// your handler to respond to particular action
}
You can also define responses to respective actions in the code block.
action filter
To respond to a particular action, structure your apply
function as follows. This is normally used in conjuction with the code filter.
if (action == N(${action_name}) {
//your handler to respond to a particular action
}
wast
Any program to be deployed to the EOSIO blockchain must be compiled into WASM format. This is the only format the blockchain accepts.
Once you have the CPP file ready, you can compile it into a text version of WASM (.wast) using the eosiocpp
tool.
$ eosiocpp -o ${contract}.wast ${contract}.cpp
abi
The Application Binary Interface (ABI) is a JSON-based description on how to convert user actions between their JSON and Binary representations. The ABI also describes how to convert the database state to/from JSON. Once you have described your contract via an ABI then developers and users will be able to interact with your contract seamlessly via JSON.
The ABI file can be generated from the .hpp
files using the eosiocpp
tool:
$ eosiocpp -g ${contract}.abi ${contract}.hpp
The following is an example of what the skeleton contract ABI looks like:
{
"types": [{
"new_type_name": "account_name",
"type": "name"
}
],
"structs": [{
"name": "transfer",
"base": "",
"fields": {
"from": "account_name",
"to": "account_name",
"quantity": "uint64"
}
},{
"name": "account",
"base": "",
"fields": {
"account": "name",
"balance": "uint64"
}
}
],
"actions": [{
"action": "transfer",
"type": "transfer"
}
],
"tables": [{
"table": "account",
"type": "account",
"index_type": "i64",
"key_names" : ["account"],
"key_types" : ["name"]
}
]
}
You will notice that this ABI defines an action transfer
of type transfer
. This tells EOSIO that when ${account}->transfer
action is seen that the payload is of type transfer
. The type transfer
is defined in the structs
array in the object with name
set to transfer
.
...
"structs": [{
"name": "transfer",
"base": "",
"fields": {
"from": "account_name",
"to": "account_name",
"quantity": "uint64"
}
},{
...
The ABI has several fields, including from
, to
and quantity
. These fields have the corresponding types account_name
, and uint64
. account_name
is a built-in type used to represent base32 string as uint64
. To see more about what built-in types are available, check here.
{
"types": [{
"new_type_name": "account_name",
"type": "name"
}
],
...
Inside the above types
array we define a list of aliases for existing types. Here, we define name
as an alias of account_name
.
Updated less than a minute ago