TransactionReceipt값에 Null이 출력되는 문제가 있습니다

안녕하세요 :slight_smile:

현재 KRC 기반의 토큰을 Fee Delegation을 사용하여 전송해보는 테스트 중에 있습니다.

JAVA 11
Caver-JAVA 1.0.2

를 사용하여 개발 중이며

Caver caver = Caver.build(apiUrl);
KlayCredentials credentials = KlayCredentials.create(fromPK);
Function function = new Function(
“transferFrom”,
Arrays.asList(
new Address(fromAddress),
new Address(toAddress),
new Uint256(sendValue)
), // inputParameters
Collections.emptyList() // outputParameters
);
String data = FunctionEncoder.encode(function);
TransactionManager transactionManager = new TransactionManager.Builder(caver, credentials).setChaindId(ChainId.MAINNET).build();
SmartContractExecutionTransaction smartContractExecution =
SmartContractExecutionTransaction.create(
credentials.getAddress(), // fromAddress
tokenContractAddress, // contractAddress
BigInteger.TEN, // value
Numeric.hexStringToByteArray(data), // data
BigInteger.valueOf(300_000) // gasLimit
);
String senderRawTransaction = transactionManager.sign(smartContractExecution, true).getValueAsString();
log.debug("]-----] senderRawTransaction [-----[ {}", senderRawTransaction);
KlayCredentials feePayer = KlayCredentials.create(
“feePrivateKey”,
“feeAddress”
);
FeePayerManager feePayerManager = new FeePayerManager.Builder(caver, feePayer).setChainId(ChainId.MAINNET).build();
feePayerManager.executeTransaction(senderRawTransaction);

기능 구현을 위해 상기 코드를 사용하여 메인넷에서 테스트 해보던 도중 지속적으로 Transaction Receipt값이 Null이 출력되고 있는 에러를 마주하게 되었으며,

해당 에러에 대한 확실한 원인을 파악하지 못해 조언을 부탁드리게 되었습니다.

감사합니다.

1 Like

안녕하세요. 먼저 클레이튼 포럼에 질문을 남겨주셔서 감사합니다. :slight_smile:

알려주신 샘플코드로 테스트해보니 문제없이 Transaction Receipt 값이 생성되었습니다.

알려주신 상황으로 추측을 해보면 Klaytn network로 전달된 트랜잭션이 블록에 기록되기 전에 PollingTransactionReceiptProcessor가 동작을 마쳤기때문에 생기는 문제로 보입니다.

위 코드를 기준으로 Transaction receipt을 가지고오기 위해서 feePayerManager.executeTransaction(senderRawTransaction);

를 실행하면 FeePayerManager의 TransactionReceiptProcessor instance의 waitTransactionReceipt을 호출하게 됩니다.

FeePayManager의 Instance를 생성 시, TranasctionReceiptProcessor를 따로 Setter function을 통해 설정하지않으면 PollingTransactionReceiptProcessor instance를 자동으로 생성하여 설정하는데

이 PollingTransactionReceiptProcessor는 주어진 주기 및 횟수를 기준으로
특정 시간의 주기로 getTransactionReceipt를 호출하여 TransactionReceipt을 가지고 오기위해 시도합니다.

결론은, FeePayerManager의 자동으로 생성된 PollingTranasctionReceiptProcessor는 1초 주기로 총 15회의 getTransactionReceipt를 호출하게됩니다.

아래코드는 1초 주기로 30회를 getTransactionReceipt을 호출하는 PollingTransactionReceiptProcessor를 FeePayerManager에 등록하는 코드입니다.

TransactionReceiptProcessor transactionReceiptProcessor = new PollingTransactionReceiptProcessor(caver, 1000, 30);
FeePayerManager feePayerManager = new FeePayerManager.Builder(caver, feePayer)
            .setChainId(LOCAL_CHAIN_ID)
            .setTransactionReceiptProcessor(transactionReceiptProcessor)
            .build();

위 코드와 같이 PollingTransactionReceiptProcessor의 설정값을 조절해서 다시 한번 테스트 부탁드립니다.

1 Like

친절한 답변 감사드립니다 :slight_smile:
블록 기록과 PollingTransactionReceiptProcessor 간의 싱크에서 오는 문제였군요.
에러 때문에 헤매고 있었는데 덕분에 해결할 수 있었습니다.
다시 한번 감사드립니다.

1 Like

안녕하세요. 우선 친절한 답변 정말 감사합니다 :slightly_smiling_face:

Caver caver = Caver.build(apiUrl);
KlayCredentials credentials = KlayCredentials.create(fromPK);
Function function = new Function(
“transferFrom”,
Arrays.asList(
new Address(fromAddress),
new Address(toAddress),
new Uint256(sendValue)
), // inputParameters
Collections.emptyList() // outputParameters
);
String data = FunctionEncoder.encode(function);
TransactionManager transactionManager = new TransactionManager.Builder(caver, credentials).setChaindId(ChainId.MAINNET).build();
SmartContractExecutionTransaction smartContractExecution =
SmartContractExecutionTransaction.create(
credentials.getAddress(), // fromAddress
tokenContractAddress, // contractAddress
BigInteger.TEN, // value
Numeric.hexStringToByteArray(data), // data
BigInteger.valueOf(300_000) // gasLimit
);
String senderRawTransaction = transactionManager.sign(smartContractExecution, true).getValueAsString();
log.debug("]-----] senderRawTransaction [-----[ {}", senderRawTransaction);
KlayCredentials feePayer = KlayCredentials.create(
“feePrivateKey”,
“feeAddress”
);
TransactionReceiptProcessor transactionReceiptProcessor = new PollingTransactionReceiptProcessor(caver, 1000, 30);
FeePayerManager feePayerManager = new FeePayerManager
.Builder(caver, feePayer)
.setTransactionReceiptProcessor(transactionReceiptProcessor)
.setChainId(ChainId.MAINNET).build();
feePayerManager.executeTransaction(senderRawTransaction);

도움 주신 코드로 테스트해본 결과 정상적으로 블록이 생성되는 것을 확인할 수 있었습니다.
하지만 해당 코드로 TransferFrom 메소드를 실행한 결과 “Fail : ErrExecutionReverted - uint(0x09)” 에러가 출력 됩니다.
따라서, 아래 두 가지 내용에 대해 문의 드리고자 합니다.
1.토큰 전송 시 트랜잭션 Sender의 서명 후 FeePayer의 서명을 진행하였는데
혹시, 해당 순서로 인해 "Fail : ErrExecutionReverted - uint(0x09)"에러가 출력된 것인지 궁금합니다.
2.만약 1번 문제가 아니라면 어떤 이유로 “Fail : ErrExecutionReverted - uint(0x09)” 에러가 출력 되는 것인지 궁금합니다.

다시 한번 빠른 답변 감사합니다 :slightly_smiling_face:

============================================================

더불어, 테스트 Transaction Hash Value 첨부드리니 참고 부탁드립니다. (https://scope.klaytn.com/tx/0x3f5341995c2a87b82c6d6015e34a8f4f35470d40715ae3b7e9ab46bd4e81c8bc?tabId=internalTx)

1 Like

Transaction Error code 0x09는 Smart contract의 function을 실행하다가 생긴 에러입니다.

1번 질문과는 관련없는 내용입니다.

Smart contract의 function을 실행하기 위한 조건을 다시한번 확인해봐주시면 감사하겠습니다.

2 Likes

네 감사합니다 :slight_smile: Smart Contract의 Function 을 다시한번 확인해보도록 하겠습니다.

2 Likes