hello 라는 이름의 디렉토리를 contracts directory 에 생성하자.

cd CONTRACTS_DIR
mkdir hello
cd hello

hello.cpp 를 생성하고 에디터로 열자.

touch hello.cpp

필요한 라이브러리를 이 파일에 include 한다.

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

코드를 간결하게 해줄 eosio 네임스페이스를 contract 에 추가한다.

using namespace eosio;
  • eosiolib/eosio.hpp 가 EOSIO C 와 C++ API 를 당신의 contract 스코프에 로드한다.

표준 C++11 클래스를 생성한다. 이 contract class 는 eosio::contract 를 확장해야한다.

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

using namespace eosio;

class hello : public contract {};

비어있는 contract 는 좋지 않으니, public 접근 지정자와 using 선언을 추가하자. 이 using 선언은 좀 더 간결한 코드를 쓸 수 있도록 도움을 줄것이다.

이제 contract 는 어떤 작업을 하도록 구성한다. hello world 의 정신을 받아 “name” 파라메터를 수신하고, 파라메터를 출력하는 작업을 해보자.

#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});
      }
};

위의 동작은 user 라는 이름의 파라메터를 name type 으로 전달 받는다.
EOSIO 는 몇개의 typedef 를 선언하고 있는데, 이 중에 흔한 하나가 바로 이 name 이다.
eosio::print를 사용함으로써, 문자열을 user 파라미터와 붙여 출력한다.
괄호를 이용한 초기화 name{user}user 파라메터가 출력될 수 있도록 해준다.

eosio.cdt 의 abi 생성자는 atttrubite 없이는 hi() 의 동작을 알 수 없다. c++11 스타일의 attribute 를 action 의 상위에 추가하여 abi generator 가 신뢰 할 수 있는 출력을 할 수 있도록 한다.

#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))

마지막으로, EOSIO_DISPATCH 매크로를 추가하여 hello contract 의 dispatch 액션을 처리하도록 한다.

이제 web assembly 를 통해 컴파일해보자.

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

contract 가 배포되면, 계정으로 배포되어 이 계정이 contract 의 인터페이스가 된다.
이 튜토리얼의 이전에 언급하였듯, 같은 public key 를 모든계정에서 사용하여 간단히 할 수 있다.

cleos wallet keys

이 contract 를 위한 계정을 생성하기 위해 cleos create account 를 사용한다.

cleos create account eosio hello YOUR_PUBLIC_KEY -p eosio@active

컴파일된 wasm 을 cleos set contract 를 통해 블록체인으로 broadcast 한다.

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

훌륭하다! 이제 contract 가 설정 되었고, action 을 push 해보자.

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

예상했던대로 hello, bob 이 출력된다.

이번 경우, “alice” 가 권한이 있고 user 는 단순한 argument 이다. contract 를 수정하여 권한이 있는 유저가 “hi” 를 받을 유저와 동일한 경우에만 동작하도록 해보자.
require_auth 메소드를 사용한다.
이 메소드는 name 을 파라메터로 받아서 action 을 수행하는 사용자가 제공된 파라메터와 일치하는지 확인한다.

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

다시 컴파일 한다.

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

그리고 update 한다.

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

실행하되, 이번에는 권한이 일치 않도록 한다.

cleos push action hello hi '["bob"]' -p alice@active
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.

우리의 contract 수정으로, 제공된 name user 가 승인 유저와 동일한지 확인한다.
다시 실행하되, 이번엔 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