1

Hello World!

在先前创建的contracts目录中创建一个名为“hello”的新目录,或者通过系统GUI或cli创建一个名为“hello”的目录并进入目录。

cd CONTRACTS_DIR
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加载到合约范围内,这是你的新战争。

创建一个标准的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的精神编写一个接受“name”参数的action,然后输出该参数。

#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类型,EOSIO附带了许多类型定义,你会遇到的最常见的类型定义之一是name,使用先前包含的eosio::print库,连接字符串并打印user参数,使用name{user}的支撑的初始化使user参数可打印。

同样,eosio.cdt中的abi生成器不知道没有属性的hi()action,在action上方添加C++ 11样式属性,这样abi生成器可以产生更可靠的输出。

#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合约的操作。

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生成器支持几种不同类型的属性,请参阅ABI使用指南

你可以将代码编译为Web assembly(.wasm),如下所示:

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

部署合约时,会将其部署到一个帐户,该帐户将成为合约的接口,如前所述,这些教程对所有帐户使用相同的公钥,以使事情更简单。

cleos wallet keys

使用cleos create account创建合约帐户,使用下面提供的命令。

cleos create account eosio hello YOUR_PUBLIC_KEY -p eosio@active

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

遇到错误?

你的钱包需要解锁。

在之前的步骤中,你应该创建一个contracts目录并获取绝对路径,将下面命令中的“CONTRACTS_DIR”替换为contracts目录的绝对路径。

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

很好!现在合约已经设定,向它推送一个操作。

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

如上所述,合约将允许任何帐户向任何用户打招呼。

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”的用户相同,使用require_auth方法,此方法将name作为参数,并将检查执行操作的用户是否与提供的参数匹配。

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

重新编译合约:

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

然后更新它:

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

尝试再次执行操作,但这次授权不匹配。

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.

通过我们对合约的更改,验证提供的name user与授权用户相同,再试一次,但这一次,十使用“alice”帐户的权限。

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

上一篇:创建测试帐户
下一篇:部署、发行和转移代币

博弈
2.5k 声望1.5k 粉丝

态度决定一切


引用和评论

0 条评论