Skip to content

Commit

Permalink
E2E: ERC721 Contract Interaction (#599)
Browse files Browse the repository at this point in the history
* E2E - ERC721

Signed-off-by: Georgi Yazovaliyski <georgi.yazovaliiski@gmail.com>
  • Loading branch information
georgiyazovaliiski committed Oct 14, 2021
1 parent 1ab4070 commit 04ff0e9
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class ContractResources {
public static final String INLINE_TEST_BYTECODE_PATH = bytecodePath("InlineTest");
public static final String INVALID_BYTECODE_PATH = bytecodePath("CorruptOne");
public static final String VALID_BYTECODE_PATH = HapiSpecSetup.getDefaultInstance().defaultContractPath();
public static final String ERC721_BYTECODE_PATH = bytecodePath("ERC721");
public static final String VERBOSE_DEPOSIT_BYTECODE_PATH = bytecodePath("VerboseDeposit");
public static final String GROW_ARRAY_BYTECODE_PATH = bytecodePath("GrowArray");
public static final String BIG_ARRAY_BYTECODE_PATH = bytecodePath("BigArray");
Expand Down Expand Up @@ -71,6 +72,18 @@ public class ContractResources {

public static final String BENCHMARK_GET_COUNTER = "{ \"inputs\": [], \"name\": \"counter\", \"outputs\": [ { \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }";

public static final String ERC721_MINT_ABI = "{ \"inputs\": [ { \"internalType\": \"address\"," +
" \"name\": \"player\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"tokenid\", \"type\": \"uint256\" } ]," +
" \"name\": \"mint\", \"outputs\": [ { \"internalType\": \"uint256\", " +
"\"name\": \"\", \"type\": \"uint256\" } ], " +
"\"stateMutability\": \"nonpayable\", \"type\": \"function\" }";
public static final String ERC721_APPROVE_ABI = "{ \"inputs\": [ { \"internalType\": \"address\", \"name\": \"to\", \"type\": \"address\" }, " +
"{ \"internalType\": \"uint256\", \"name\": \"tokenId\", \"type\": \"uint256\" } ], \"name\": \"approve\", \"outputs\": [], " +
"\"stateMutability\": \"nonpayable\", \"type\": \"function\" }";
public static final String ERC721_TRANSFER_FROM_ABI = "{ \"inputs\": [ { \"internalType\": \"address\", \"name\": \"from\", \"type\": \"address\" }, " +
"{ \"internalType\": \"address\", \"name\": \"to\", \"type\": \"address\" }, " +
"{ \"internalType\": \"uint256\", \"name\": \"tokenId\", \"type\": \"uint256\" } ], " +
"\"name\": \"transferFrom\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }";
public static final String CREATE_CHILD_ABI = "{\"constant\":false," +
"\"inputs\":[],\"name\":\"create\"," +
"\"outputs\":[]," +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCreate;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.fileCreate;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.CONTRACT_EXECUTION_EXCEPTION;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ERROR_DECODING_BYTESTRING;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INSUFFICIENT_GAS;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package com.hedera.services.bdd.suites.contract.openzeppelin;

/*-
* ‌
* Hedera Services Test Clients
* ​
* Copyright (C) 2018 - 2021 Hedera Hashgraph, LLC
* ​
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ‍
*/

import com.google.protobuf.ByteString;
import com.hedera.services.bdd.spec.HapiApiSpec;
import com.hedera.services.bdd.spec.queries.QueryVerbs;
import com.hedera.services.bdd.suites.HapiApiSuite;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

import static com.hedera.services.bdd.spec.HapiApiSpec.defaultHapiSpec;
import static com.hedera.services.bdd.spec.infrastructure.meta.ContractResources.ERC721_APPROVE_ABI;
import static com.hedera.services.bdd.spec.infrastructure.meta.ContractResources.ERC721_BYTECODE_PATH;
import static com.hedera.services.bdd.spec.infrastructure.meta.ContractResources.ERC721_MINT_ABI;
import static com.hedera.services.bdd.spec.infrastructure.meta.ContractResources.ERC721_TRANSFER_FROM_ABI;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCall;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCreate;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.fileCreate;
import static com.hedera.services.bdd.spec.utilops.CustomSpecAssert.allRunFor;
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.updateLargeFile;
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.withOpContext;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SUCCESS;

public class ERC721ContractInteractions extends HapiApiSuite {
private static final Logger log = LogManager.getLogger(ERC721ContractInteractions.class);

public static void main(String... args) {
new ERC721ContractInteractions().runSuiteSync();
}

@Override
protected Logger getResultsLogger() {
return log;
}

@Override
protected List<HapiApiSpec> getSpecsInSuite() {
return List.of(
callsERC721ContractInteractions()
);
}

private HapiApiSpec callsERC721ContractInteractions() {
final var PAYER = "tx_payer";
final var CONTRACT_CREATOR = "contractCreator";
final var NFT_SENDER = "sender";
final var CONTRACT_FILE_NAME = "ERC721ContractFile";
final var NFT_ID = 1;

final var CREATE_TX = "create";
final var MINT_TX = "mint";
final var APPROVE_TX = "approve";
final var TRANSFER_FROM_TX = "transferFrom";

return defaultHapiSpec("CallsERC721ContractInteractions")
.given(
cryptoCreate(PAYER).balance(ONE_HUNDRED_HBARS),
cryptoCreate(CONTRACT_CREATOR),
cryptoCreate(NFT_SENDER),
QueryVerbs.getAccountBalance(PAYER).logged(),
fileCreate(CONTRACT_FILE_NAME).payingWith(PAYER),
updateLargeFile(PAYER, CONTRACT_FILE_NAME, extractByteCode(ERC721_BYTECODE_PATH))
).when(
QueryVerbs.getAccountBalance(PAYER).logged(),
contractCreate("testContract")
.payingWith(CONTRACT_CREATOR)
.bytecode(CONTRACT_FILE_NAME)
.hasKnownStatus(SUCCESS)
.via(CREATE_TX)
).then(
QueryVerbs.getAccountInfo(CONTRACT_CREATOR).savingSnapshot(CONTRACT_CREATOR),
QueryVerbs.getAccountInfo(NFT_SENDER).savingSnapshot(NFT_SENDER),

withOpContext((spec, log) -> {
final var contractCreatorId = spec.registry().getAccountInfo(CONTRACT_CREATOR).getContractAccountID();
final var nftSenderId = spec.registry().getAccountInfo(NFT_SENDER).getContractAccountID();

final var mintParams = new Object[]{nftSenderId, NFT_ID};
final var approveParams = new Object[]{contractCreatorId, NFT_ID};
final var transferFromParams = new Object[]{nftSenderId, contractCreatorId, NFT_ID};

final var mint = contractCall("testContract",
ERC721_MINT_ABI, mintParams).payingWith(CONTRACT_CREATOR).via(MINT_TX);
allRunFor(spec, mint);

final var approve = contractCall("testContract",
ERC721_APPROVE_ABI, approveParams).payingWith(NFT_SENDER).via(APPROVE_TX);
allRunFor(spec, approve);

final var transferFrom = contractCall("testContract",
ERC721_TRANSFER_FROM_ABI, transferFromParams).payingWith(CONTRACT_CREATOR).via(TRANSFER_FROM_TX);
allRunFor(spec, transferFrom);
}),
QueryVerbs.getTxnRecord(CREATE_TX).logged(),
QueryVerbs.getTxnRecord(MINT_TX).logged(),
QueryVerbs.getTxnRecord(APPROVE_TX).logged(),
QueryVerbs.getTxnRecord(TRANSFER_FROM_TX).logged()
);
}

private ByteString extractByteCode(String path) {
try {
var bytes = Files.readAllBytes(Path.of(path));
return ByteString.copyFrom(bytes);
} catch (IOException e) {
e.printStackTrace();
return ByteString.EMPTY;
}
}
}

0 comments on commit 04ff0e9

Please sign in to comment.