Getting Started

The eos Developer Hub

Welcome to the eos developer hub. You'll find comprehensive guides and documentation to help you start working with eos as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    Discussions

2.1 Hello World!

Create a new directory called "hello" in the contracts directory you previously created, or through your system GUI or with cli and enter the directory.

cd CONTRACTS_DIR
mkdir hello
cd hello

Create a new file, "hello.cpp" and open it in your favorite editor.

touch hello.cpp

Include the required libraries into the file.

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

To make things more concise in your contract use namespace eosio.

using namespace eosio;
  • eosiolib/eosio.hpp loads the EOSIO C and C++ API into the scope of your contract, this is your new warchest.

Create a standard C++11 class. The contract class needs to extend eosio::contract.

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

using namespace eosio;

class hello : public contract {};

An empty contract doesn't do much good. Add a public access specifier and a using-declaration. The using declaration will allow us to write more concise code.

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

using namespace eosio;

class hello : public contract {
  public:
      using contract::contract;
};

This contract needs to do something. In the spirit of hello world write an action that accepts a "name" parameter, and then prints that parameter out.

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

using namespace eosio;

class hello : public contract {
  public:
      using contract::contract;
  
      [[eosio::action]]
      void hi( name user ) {
         print( "Hello, ", name{user});
      }
};

The above action accepts a parameter called user that's an name type. EOSIO comes with a number of typedefs, one of the most common typedefs you'll encounter is name. Using the eosio::print library previously included, concatenate a string and print the user parameter. Use the braced initialization of name{user} to make the user parameter printable.

As is, the abi generator in eosio.cdt won't know about the hi() action without an attribute. Add a C++11 style attribute above the action, this way the abi generator can produce more reliable output.

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

using namespace eosio;

class hello : public contract {
  public:
      using contract::contract;

      [[eosio::action]]
      void hi( name user ) {
         print( "Hello, ", user);
      }
};

EOSIO_DISPATCH( hello, (hi))

Finally, add the EOSIO_DISPATCH macro to handle the dispatching of actions for the hello contract.

EOSIO_DISPATCH( hello, (hi))

Everything together, here's the completed hello world contract

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

using namespace eosio;

class hello : public contract {
  public:
      using contract::contract;

      [[eosio::action]]
      void hi( name user ) {
         print( "Hello, ", user);
      }
};

EOSIO_DISPATCH( hello, (hi))

The ABI Generator in eosio.cdt supports several different style of attributes, see the ABI usage guide here

You can compile your code to web assembly (.wasm) as follows:

eosio-cpp -o hello.wasm hello.cpp --abigen

When a contract is deployed, it is deployed to an account, and the account becomes the interface for the contract. As mentioned earlier these tutorials use the same public key for all of the accounts to keep things more simple.

cleos wallet keys

Create an account for the contract using cleos create account, with the command provided below.

cleos create account eosio hello YOUR_PUBLIC_KEY -p eosio@active

Broadcast the compiled wasm to the blockchain with cleos set contract.

Get an error?

Either your wallet needs to be unlocked, or you did not alias cleos as mentioned in step 1.3.

In previous steps you should have created a `contracts` directory and obtained the absolute path and then saved it into a cookie. Replace "CONTRACTS_DIR" in the command below with the absolute path to your `contracts` directory.
cleos set contract hello CONTRACTS_DIR/hello -p hello@active

Great! Now the contract is set, push an action to it.

cleos push action hello hi '["bob"]' -p bob@active
executed transaction: 4c10c1426c16b1656e802f3302677594731b380b18a44851d38e8b5275072857  244 bytes  1000 cycles
#    hello.code <= hello.code::hi               {"user":"bob"}
>> Hello, bob

As written, the contract will allow any account to say hi to any user

cleos push action hello hi '["bob"]' -p alice@active
executed transaction: 28d92256c8ffd8b0255be324e4596b7c745f50f85722d0c4400471bc184b9a16  244 bytes  1000 cycles
#    hello.code <= hello.code::hi               {"user":"bob"}
>> Hello, bob

As expected, the console output is "Hello, bob"

In this case "alice" is the one who authorized it and user is just an argument. Modify the contract so that the authorizing user, "alice" in this case, must be the same as the user the contract is responding "hi" to. Use the require_auth method. This method takes an name as a parameter, and will check if the user executing the action matches the provided paramter.

void hi( name user ) {
   require_auth( user );
   print( "Hello, ", name{user} );
}

Recompile the contract

eosio-cpp -o hello.wasm hello.cpp --abigen

And then update it

cleos set contract hello CONTRACTS_DIR/hello -p hello@active

Try to execute the action again, but this time with mismatched authorization.

cleos push action hello hi '["bob"]' -p alice@active

As expected, require_auth halted the transaction and threw an error.

Error 3090004: Missing required authority
Ensure that you have the related authority inside your transaction!;
If you are currently using 'cleos push action' command, try to add the [relevant](**http://google.com**) authority using -p option.

With our changes to the contract, verify the provided name user is the same as the authorising user. Try it again, but this time, with the authority of the "alice" account.

cleos push action hello hi '["alice"]' -p alice@active
executed transaction: 235bd766c2097f4a698cfb948eb2e709532df8d18458b92c9c6aae74ed8e4518  244 bytes  1000 cycles
#    hello <= hello::hi               {"user":"alice"}
>> Hello, alice