Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2E: ERC721 Contract Interaction #599

Merged
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,111 @@
package com.hedera.services.bdd.suites.contract.openzeppelin;
georgiyazovaliiski marked this conversation as resolved.
Show resolved Hide resolved

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 OWNER = "owner";
final var RECEIVER = "receiver";
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(OWNER),
cryptoCreate(RECEIVER),
fileCreate(CONTRACT_FILE_NAME),
updateLargeFile(DEFAULT_PAYER, CONTRACT_FILE_NAME, extractByteCode(ERC721_BYTECODE_PATH))
).when(
contractCreate("testContract")
.payingWith(OWNER)
.bytecode(CONTRACT_FILE_NAME)
.hasKnownStatus(SUCCESS)
.via(CREATE_TX)
).then(
QueryVerbs.getAccountInfo(OWNER).savingSnapshot(OWNER),
QueryVerbs.getAccountInfo(RECEIVER).savingSnapshot(RECEIVER),

withOpContext((spec, log) -> {
final var ownerContractId = spec.registry().getAccountInfo(OWNER).getContractAccountID();
final var receiverContractId = spec.registry().getAccountInfo(RECEIVER).getContractAccountID();

final var mintParams = new Object[]{ownerContractId, NFT_ID};
final var approveParams = new Object[]{receiverContractId, NFT_ID};
final var transferFromParams = new Object[]{ownerContractId, receiverContractId, NFT_ID};

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

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

final var transferFrom = contractCall("testContract",
ERC721_TRANSFER_FROM_ABI, transferFromParams).payingWith(OWNER).via(TRANSFER_FROM_TX);
georgiyazovaliiski marked this conversation as resolved.
Show resolved Hide resolved
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;
}
}
}