2.1 Hello World!

优质
小牛编辑
135浏览
2023-12-01

在之前创建的contracts目录创建一个新目录命名为hello.或者通过系统GUI或cli创建一个名为hello的目录并按下enter.

cd /Users/zhong/coding/CLion/contracts
mkdir hello
cd hello

创建一个新文件:hello.cpp,并用你最喜欢的编辑器打开它.

touch hello.cpp

将需要的依赖包含进去:

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

为了让合约的内容更简洁, 请使用命名空间eosio.

using namespace eosio;
  • eosiolib/eosio.hpp加载了EOSIO C 和C++ API到你的合约上下文,这是你的新warchest.

创建一个标准的C++11类.这个合约需要继承eosio:contract.

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

using namespace eosio;

class hello : public contract {};

一个空的合约不需要做什么事情.添加一个public权限修饰符和using声明 .using声明会让我们编写的代码更简洁.

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

using namespace eosio;

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

这个合约需要做些什么.基于hello world的精神,写一个action接收一个"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, ", user);
      }
};

上面这个action可以接受一个类型为name 命名为user的参数.EOSIO提供了一些类型定义,name会是你最常遇到的之一.使用之前引入的eosio:print library,连接字符串并将user参数打印出来

这样,eosio.cdt的abi generator在没有参数的情况下不会知道hi()这一action.添加一个C++11的样式属性到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_ABI 宏来处理hello合约对actions的分发.

EOSIO_DISPATCH( hello, (hi))

所有事都完成了,这是完整的hello world合约:

#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.cdt的ABI Generator支持一些不同的参数样式,查看ABI使用指南 here

你能编译你的合约为 web assembly(.wasm):

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

当合约部署好了,它会被部署到一个账户,这个账户成为这个合约的接口.在这些教程的前面提到过,对所有的账户都使用相同的公钥以求简单.

cleos wallet keys

使用下面的命令创建一个账户 cleos create account:

cleos create account eosio hello EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV -p eosio@active

出现了error?

任何和链上的交互都需要将钱包解锁,或者你没有在教程的1.3部分设置alias(别称)

使用cleos set contract将编译好的wasm广播到区块链.

cleos set contract hello /Users/zhong/coding/CLion/contracts/hello -p hello@active

set contract是发布合约的命令,hello是发布合约的账户,/Users/zhong/coding/CLion/contracts/hello是包含WAST或WASM的文件,-p hello@active是授权账户和权限级别,如account@permission(默认为account@active)

很好!现在合约设置好了,push一个action给它.

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

结果:

zhongdeMacBook-Pro:hello zhong$ cleos push action hello hi '["bob"]' -p bob@active
executed transaction: 151987c8763a5f008229cf9fbcec1c07034717e533585c9fe33658bddc87db04  104 bytes  418 us
#         hello <= hello::hi                    {"user":"bob"}
>> Hello, bob
warning: transaction executed locally, but may not be confirmed by the network yet    ]

如我们所写的代码,合约允许任何账号对任何人 say hi

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

就和我们预想的一样,控制台输出了"Hello, bob".

当前,"alice"是给其授权的人,user只是一个参数. 修改合约让它需要权限.在当前的例子应该是"alice", 必须是同样的参数传入才能让合约相应hi这一action.使用require_auth函数.该函数会校验当前执行action的account是否拥有它所对应的权限.

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

重新编译合约:

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

然后更新它:

cleos set contract hello /Users/zhong/coding/CLion/contracts/hello -p hello@active

现在再尝试执行action,但这次会说权限不匹配.

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

就像预期的一样,require_auth停止了交易并抛出了一个错误:

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.

通过我们对合约的修改,验证提供的account_name user和我们授权用户一样.这次,在参数中传入"alice".

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

结果:

executed transaction: 31d2e756527e8afa6c8733cbb32ec85fd654f1a856f94168b8176b865e447b57  104 bytes  248 us
#         hello <= hello::hi                    {"user":"alice"}
>> Hello, alice
warning: transaction executed locally, but may not be confirmed by the network yet    ]