안녕하세요. ERC6551 테스트를 web3j로 진행하고 있었습니다.
ERC6551에 관련된 Contract 모두 Baobab테스트넷에 배포하였고
NFT transferFrom 기능을 executeCall을 통해서 소유권을 이전하려고 합니다.
@Test
public void testERC6551Test() throws Exception{
HttpService httpService = new HttpService(caverKasNodeUrl);
httpService.addHeader("Authorization", okhttp3.Credentials.basic(accessKey, secretAccessKey));
httpService.addHeader("x-chain-id", kasChainId);
// web3j 객체생성
Web3j web3j = Web3j.build(httpService);
// NFT 컨트랙트 주소 토큰 ID, 구현 주소 설정
String nftAddress = "0xfc9160db4083b165c79ea72efd1b34cb742d5f0e"; // ERC721 Contract
BigInteger tokenId = BigInteger.valueOf(0);
String ERC6551RegistryAddress = "0x9ffba4e502e7334068fbdcc7507087cde0952ebc"; // ERC6551 Registry 주소
String ERC6551AccountAddress = "0x5aaa85ce664526c259375472b5d3159aa43896c3"; // ERC6551Account 주소
String receiverAddress = "0x980e41f0a74f1c3d749b8ec54d9e3de3279e1feb"; // 받는사람
BigInteger tokenAmount = BigInteger.valueOf(1); // NFT 구매금액
// ERC6551 Registry 컨트랙트의 account 함수를 호출하여 TokenBoundAccount 주소를 얻음
Function accountFunction = new Function(
"account",
Arrays.asList(new Address(ERC6551AccountAddress), new Uint256(1001), new Address(nftAddress), new Uint256(tokenId), new Uint256(0)),
Arrays.asList(new TypeReference<Address>() {})
);
log.info("======== accountFunction : {}", objectToString(accountFunction));
String encodedAccountFunction = FunctionEncoder.encode(accountFunction);
log.info("======== encodedAccountFunction : {}", objectToString(encodedAccountFunction));
// to : ERC6551Registry 컨트랙트 주소
EthCall ethCall = web3j.ethCall(
Transaction.createEthCallTransaction(null, ERC6551RegistryAddress, encodedAccountFunction),
DefaultBlockParameterName.LATEST
).send();
log.info("======== ethCall : {}", objectToString(ethCall));
String tokenBoundAccountAddress = (String) FunctionReturnDecoder.decode(
ethCall.getValue(),
accountFunction.getOutputParameters()
).get(0).getValue();
log.info("======= tokenBoundAccountAddress (Token Owner) : {}", tokenBoundAccountAddress);
// Account 조회 종료
// TokenBoundAccount 주소를 사용하여 Contract 객체 생성
Credentials credentials = Credentials.create("0x07f2066d045c19f72479cf3079a8161244bb3a9d0899a3487b6ec00c13596360"); // Token 0번 Owner (Baobab)
TransactionManager transactionManager = new RawTransactionManager(web3j, credentials);
ContractGasProvider gasProvider = new StaticGasProvider(BigInteger.valueOf(25_000_000_000L), BigInteger.valueOf(250_000_000_000L));
ERC6551Account erc6551Account = ERC6551Account.load(
ERC6551AccountAddress,
web3j,
transactionManager,
gasProvider
);
// NFT Transfer 함수 인코딩
Function function = new Function(
"transferFrom",
Arrays.asList(new Address(tokenBoundAccountAddress), new Address(receiverAddress), new Uint256(tokenId)),
Collections.emptyList()
);
// byte[] encodedFunction = FunctionEncoder.encode(function);
String encodedFunction = FunctionEncoder.encode(function);
byte[] data = Numeric.hexStringToByteArray(encodedFunction);
TransactionReceipt receipt = erc6551Account.executeCall(receiverAddress, tokenAmount, data, BigInteger.ZERO).send();
log.info("============= receipt : {}", receipt);
}
jUnit으로 테스트를 해보았는데
org.web3j.protocol.exceptions.TransactionException: JsonRpcError thrown with code -32000. Message: insufficient funds of the sender for value
at org.web3j.tx.Contract.executeTransaction(Contract.java:424)
at org.web3j.tx.Contract.executeTransaction(Contract.java:373)
at org.web3j.tx.Contract.executeTransaction(Contract.java:367)
at org.web3j.tx.Contract.lambda$executeRemoteCallTransaction$4(Contract.java:472)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
이렇게 오류가 발생했습니다
잔액부족이라고 발생했었는데 ERC6551RegistryAddress, tokenBoundAccountAddress, Token 0번 소유자 모두 Klay가 충분한 상태에서 발생했습니다
어떤 부분이 문제인지 모르겠네요…