java.lang.IllegalArgumentException: Cannot find method with passed parameters. 오류 문의드립니다

CaverExtKAS caverExtKas = new CaverExtKAS();
caverExtKas.initKASAPI(ChainId.BAOBAB_TESTNET, accessKey, secretAccessKey);

BufferedReader br = new BufferedReader(new FileReader("Contract.json"));
KIP7Json kip7Json = new Gson().fromJson(br, KIP7Json.class);

CallObject params = createCallObject();

params.setFrom("0x30XXXX");
params.setTo("0xb7XXXX");
params.setValue(new BigInteger("10", 16));

// List<Type> returnedData = contract.call("transferFrom", "0x30XXXX", "0xb7XXXX", new BigInteger("10", 16));
List<Type> returnedData = contract.call("transferFrom", params);

위와 같이 제가 배포한 contract의 tranferFrom이라는 매소드를 호출하려고 합니다.
주석으로 막은 방벅으로 하다가 Callobject라는 걸 넘겨야 하는것 같아 CallObject를 선언하고 Set하는 방식으로 해보았는데 “java.lang.IllegalArgumentException: Cannot find method with passed parameters.” 오류가 발생했습니다.

같은 방식으로

List<Type> returnedData2 = contract.call("totalSupply");

함수는 호출해서 응답을 정상적으로 받았는데
“java.lang.IllegalArgumentException: Cannot find method with passed parameters.” 오류는 어떻게 해결하면 될까요?

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

TLDR : caver-java-examples/CaverExample.java at 2237e263617c20ea44017c8d4346bee851a25e81 · klaytn/caver-java-examples · GitHub 를 참고해보시기 바랍니다. call 대신 send 라는 메서드를 사용하셔야 합니다.

Description
우선 사용하신 contract.call에 대해서 설명드리겠습니다.
contract.call 을 호출 시퀀스를 따라가보면 아래와 같이 호출된다는 걸 확인해보실 수 있습니다.
(Break point를 사용하셔서 step by step으로 따라가보시는 걸 추천드립니다.)

  1. com.klaytn.caver.contract.Contract 클래스의 call 메서드 호출
  2. 호출하시고자 하는 메서드(ContractMethod)를 Contract 인스턴스 내부에서 찾고, 있다면 ContractMethod 클래스의 call 호출
  3. …(중략)
  4. com.klaytn.caver.contract.Klay 클래스의 call 메서드 호출

결국 마지막에 호출하는 것은 klay_call 로 링크에 있는 설명을 보시면 “블록체인에 트랜잭션을 생성하지 않고 즉시 새 메시지 호출을 합니다.” 라고 되어있습니다.

트랜잭션(= 상태의 변화)을 발생시키지 않는다는 건 상태 변화가 없는 액션이라는 뜻이고 현재 질문자분께서 호출하고자 하시는 transferFrom 이라는 메서드는 상태 변화(컨트랙트 스토리지에 저장되어 있는 값들의 변경)를 요구하기 때문에 지금과 같은 경우 맞지 않는 사용법입니다.

transferFrom 은 일반적으로 토큰 컨트랙트에서 특정 계정 주소에 매핑된 토큰 잔액 값에 대한 변경이 일어나는 액션이고 이는 곧 토큰 컨트랙트 상태의 변화를 의미합니다. 따라서 지금과 같은 경우 Contract 클래스의 call 메서드 대신 send라는 메서드를 사용하셔야 하는 상황입니다.

호출하신 totalSupply의 경우 컨트랙트의 상태 변경 없이 단순히 값만 읽어오는 메서드고 이런 경우에 call을 사용하시면 됩니다.

도움이 되었길 바랍니다.

@Denver

답변 감사합니다.
질문을 올리고 문서를 찾다가 send라는 메서드를 찾아서
테스트를 진행했었는데 해결되었다고 댓글을 안달았었네요…

send 메서드 호출 시 오류가 발생해
질문글을 올렸었는데 그 글도 혹시 확인이 가능하신가요??

https://forum.klaytn.foundation/t/caver-java-ext-kas/1883

@Denver

transferFrom을 테스트하다가 잘 동작하지 않는것 같아서
transfer를 호출하는 테스트를 진행하려고 합니다.

그럴때는 call 메소드를 호출하고 그때 from, to, value정보를 callObject로 넘기면 되는건가요??

List<Type> transferResult = contract.call("transfer", callObject);

이렇게 호출했을 때
java.lang.IllegalArgumentException: Cannot find method with passed parameters.
위와 같은 에러응답을 받았습니다

@ToTheMoon

call이 아닌 send를 사용하셔서 호출하셔야 합니다. transferFromtransfer 모두 상태를 변화시키기 때문입니다.

우선 이 둘의 차이점에 대해 기술한 제 첫번째 답변의 DescriptionTLDR에 첨부드린 링크를 따라가면 나오는 예제 코드 확인을 부탁드립니다.

첨부드린 링크를 따라가 보시면 나오는 코드는 아래와 같습니다.
SendOptions를 사용해주셔야 하고 transfer 호출에 필요한 매개변수들도 넘겨주셔야 합니다 :slight_smile:

        Contract contract = caver.contract.create(abi, contractAddress);
        SendOptions sendOptions = new SendOptions(deployerKeyring.getAddress(), BigInteger.valueOf(400000));
        TransactionReceipt.TransactionReceiptData transactionReceiptData = contract.send(
                sendOptions,
                "set",
                "k1",
                "v1"
        );
        System.out.println(objectToString(transactionReceiptData));

스마트 컨트랙트에 정의되어 있는 trasnfer 함수의 시그니쳐를 살펴보시고 어떤 파라미터를 받는지 파악하신 뒤 해당 파라미터들에 맞게 값을 넘겨주시면 에러 메시지는 해결될 거 같습니다.
도움이 되었길 바랍니다.