2.1 hello world

我们现在将创建我们的第一个“hello world”合约。在先前创建的合约目录中创建一个名为“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;

接下来,我们将创建一个标准的C ++ 11类。 我们的合约类需要扩展eosio :: contract, 最终结果即是你的新合约。

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

using namespace eosio;

class hello : public contract {};

空合同对我们没有多大帮助。 首先,我们将添加一个公共访问说明符和一个using声明,using声明将允许我们编写更简洁的代码。

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

using namespace eosio;

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

接下来我们需要让这份合同做点什么。 本着hello world的精神,我们将编写一个接受“name”参数的动作,然后将该参数打印出来。

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

using namespace eosio;

class hello : public contract {
public:
using contract::contract;
void hi( account_name user ) {
print( "Hello, ", name{user} );
}
};

上面的操作接受一个名为user的参数,它是一个account_name类型。 EOSIO附带了许多typedef,你遇到的最常见的typedef之一是account_name。 使用我们导入的eosio :: print库,我们将连接一个字符串并打印user参数。 我们使用名称{user}的支撑初始化来使user参数可打印。
eosio.cdt中的abi生成器无法识别没有属性的hi()。 但在添加一个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( account_name user ) {
print( "Hello, ", name{user} );
}
};

最后,我们需要添加EOSIO_ABI宏来进行hello合约的调度。

EOSIO_ABI( 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( account_name user ) {
print( "Hello, ", name{user} );
}
};
EOSIO_ABI( hello, (hi))

eosio.cdt中的ABI Generator支持几种不同类型的属性,请参阅此处的ABI使用指南( here
您可以将代码编译为Web程序集(.wasm),如下所示:

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

正如本系列前面提到的,我们将为所有帐户使用相同的公钥,因此请记住您之前创建的密钥,因为我们需要为此合约创建一个帐户。 部署合约时,会将其部署到帐户,该帐户将成为合约的接口。
使用cleos create account创建合约帐户,使用下面提供的命令。 不要忘记将YOUR_PUBLIC_KEY替换为您之前生成的公钥。

cleos create account eosio hello YOUR_PUBLIC_KEY -p eosio@active

之前我们将清理器别名添加到您的docker容器中。 我们需要将合约文件移动到已安装的卷。 我们之前运行的docker run命令。
现在我们有了合约的帐户,您可以使用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”是授权它的人,用户只是一个参数。 让我们修改合约,以便在这种情况下授权用户“alice”必须与我们说“hi”的用户相同。 为此,我们将使用require_auth方法。 此方法将account_name作为参数,并将检查执行操作的用户是否与提供的参数匹配。

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

重新编译

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

更新

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

通过提供与授权操作的用户不同的account_name,再次执行操作。

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用户与授权用户相同。 所以让我们再试一次,但这一次,有了“爱丽丝”帐户的授权。

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

您已经了解了合约开发的基础知识,现在让我们继续部署eosio.token合约,及数字货币的部署,发布和转移。

原文链接:https://developers.eos.io/eosio-home/docs/your-first-contract