Loading...
Searching...
No Matches
contract_executor_test.cpp
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
21
22#include <glog/logging.h>
23#include <gtest/gtest.h>
24
25#include <fstream>
26
27namespace resdb {
28namespace contract {
29namespace {
30
31using ::testing::Test;
32
33const std::string test_dir = std::string(getenv("TEST_SRCDIR")) + "/" +
34 std::string(getenv("TEST_WORKSPACE")) +
35 "/service/contract/executor/service/";
36
37std::string ToString(const Request& request) {
38 std::string ret;
39 request.SerializeToString(&ret);
40 return ret;
41}
42
43class ContractTransactionManagerTest : public Test {
44 public:
45 ContractTransactionManagerTest() {
46 std::string contract_path = test_dir + "test_data/contract.json";
47
48 std::ifstream contract_fstream(contract_path);
49 if (!contract_fstream) {
50 throw std::runtime_error(fmt::format(
51 "Unable to open contract definition file {}", contract_path));
52 }
53
54 nlohmann::json definition = nlohmann::json::parse(contract_fstream);
55 contracts_json_ = definition["contracts"];
56 }
57
58 Account CreateAccount() {
59 Request request;
60 Response response;
61
62 request.set_cmd(Request::CREATE_ACCOUNT);
63 std::unique_ptr<std::string> ret = executor_.ExecuteData(ToString(request));
64 EXPECT_TRUE(ret != nullptr);
65 response.ParseFromString(*ret);
66 return response.account();
67 }
68
69 absl::StatusOr<Contract> Deploy(const Account& account,
70 DeployInfo deploy_info) {
71 Request request;
72 Response response;
73
74 request.set_caller_address(account.address());
75 *request.mutable_deploy_info() = deploy_info;
76 request.set_cmd(Request::DEPLOY);
77
78 std::unique_ptr<std::string> ret = executor_.ExecuteData(ToString(request));
79 EXPECT_TRUE(ret != nullptr);
80
81 response.ParseFromString(*ret);
82 if (response.ret() == 0) {
83 return response.contract();
84 } else {
85 return absl::InternalError("DeployFail.");
86 }
87 }
88
89 absl::StatusOr<uint256_t> Execute(const std::string& caller_address,
90 const std::string& contract_address,
91 const Params& params) {
92 Request request;
93 Response response;
94
95 request.set_caller_address(caller_address);
96 request.set_contract_address(contract_address);
97 request.set_cmd(Request::EXECUTE);
98 *request.mutable_func_params() = params;
99
100 std::unique_ptr<std::string> ret = executor_.ExecuteData(ToString(request));
101 EXPECT_TRUE(ret != nullptr);
102
103 response.ParseFromString(*ret);
104
105 if (response.ret() == 0) {
106 return eevm::to_uint256(response.res());
107 } else {
108 return absl::InternalError("DeployFail.");
109 }
110 }
111
112 protected:
113 nlohmann::json contracts_json_;
114 ContractTransactionManager executor_;
115};
116
117TEST_F(ContractTransactionManagerTest, ExecContract) {
118 // create an account.
119 Account account = CreateAccount();
120 EXPECT_FALSE(account.address().empty());
121
122 std::string contract_name = "ERC20.sol:ERC20Token";
123 std::string contract_code = contracts_json_[contract_name]["bin"];
124 nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
125
126 // deploy
127 DeployInfo deploy_info;
128 deploy_info.set_contract_bin(contract_code);
129 deploy_info.set_contract_name(contract_name);
130
131 for (auto& func : func_hashes.items()) {
132 FuncInfo* new_func = deploy_info.add_func_info();
133 new_func->set_func_name(func.key());
134 new_func->set_hash(func.value());
135 }
136 deploy_info.add_init_param("1000");
137
138 absl::StatusOr<Contract> contract_or = Deploy(account, deploy_info);
139 EXPECT_TRUE(contract_or.ok());
140 Contract contract = *contract_or;
141
142 // query owner should return 1000
143 {
144 Params func_params;
145 func_params.set_func_name("balanceOf(address)");
146 func_params.add_param(account.address());
147
148 auto result =
149 Execute(account.address(), contract.contract_address(), func_params);
150 EXPECT_EQ(*result, 0x3e8);
151 }
152
153 Account transfer_receiver = CreateAccount();
154 EXPECT_FALSE(account.address().empty());
155 // receiver 0
156 {
157 Params func_params;
158 func_params.set_func_name("balanceOf(address)");
159 func_params.add_param(transfer_receiver.address());
160
161 auto result =
162 Execute(account.address(), contract.contract_address(), func_params);
163 EXPECT_EQ(*result, 0);
164 }
165
166 // transfer 400 to receiver
167 {
168 Params func_params;
169 func_params.set_func_name("transfer(address,uint256)");
170 func_params.add_param(transfer_receiver.address());
171 func_params.add_param("400");
172
173 auto result =
174 Execute(account.address(), contract.contract_address(), func_params);
175 EXPECT_EQ(*result, 1);
176 }
177
178 // query owner should return 600
179 {
180 Params func_params;
181 func_params.set_func_name("balanceOf(address)");
182 func_params.add_param(account.address());
183
184 auto result =
185 Execute(account.address(), contract.contract_address(), func_params);
186 EXPECT_EQ(*result, 600);
187 }
188
189 // receiver 400
190 {
191 Params func_params;
192 func_params.set_func_name("balanceOf(address)");
193 func_params.add_param(transfer_receiver.address());
194
195 auto result =
196 Execute(account.address(), contract.contract_address(), func_params);
197 EXPECT_EQ(*result, 400);
198 }
199}
200
201TEST_F(ContractTransactionManagerTest, DeployFail) {
202 // create an account.
203 Account account = CreateAccount();
204 EXPECT_FALSE(account.address().empty());
205
206 std::string contract_name = "ERC20.sol:ERC20Token";
207 std::string contract_code = contracts_json_[contract_name]["bin"];
208 nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
209
210 // deploy
211 DeployInfo deploy_info;
212 deploy_info.set_contract_bin(contract_code);
213 deploy_info.set_contract_name(contract_name);
214
215 for (auto& func : func_hashes.items()) {
216 FuncInfo* new_func = deploy_info.add_func_info();
217 new_func->set_func_name(func.key());
218 new_func->set_hash(func.value());
219 }
220 // deploy_info.add_init_param("1000");
221
222 absl::StatusOr<Contract> contract_or = Deploy(account, deploy_info);
223 EXPECT_FALSE(contract_or.ok());
224}
225
226TEST_F(ContractTransactionManagerTest, NoFunc) {
227 // create an account.
228 Account account = CreateAccount();
229 EXPECT_FALSE(account.address().empty());
230
231 std::string contract_name = "ERC20.sol:ERC20Token";
232 std::string contract_code = contracts_json_[contract_name]["bin"];
233 nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
234
235 // deploy
236 DeployInfo deploy_info;
237 deploy_info.set_contract_bin(contract_code);
238 deploy_info.set_contract_name(contract_name);
239
240 for (auto& func : func_hashes.items()) {
241 FuncInfo* new_func = deploy_info.add_func_info();
242 new_func->set_func_name(func.key());
243 new_func->set_hash(func.value());
244 }
245 deploy_info.add_init_param("1000");
246
247 absl::StatusOr<Contract> contract_or = Deploy(account, deploy_info);
248 EXPECT_TRUE(contract_or.ok());
249 Contract contract = *contract_or;
250
251 {
252 Params func_params;
253 func_params.set_func_name("balanceOf()");
254 func_params.add_param(account.address());
255
256 auto result =
257 Execute(account.address(), contract.contract_address(), func_params);
258 EXPECT_FALSE(result.ok());
259 }
260}
261
262} // namespace
263} // namespace contract
264} // namespace resdb
ContractTransactionManager executor_
nlohmann::json contracts_json_
void CreateAccount(ContractClient *client)
const std::string test_dir
TEST_F(ResDBTest, TestPBFTService)