Contract 를 활용한 transfer 호출시 revert error 문의

안녕하세요,

Smart contract 를 활용한 token transfer 를 연습해보고 있는데요,
revert 오류가 발생하는데 원인 파악이 어려워 문의 요청 드립니다.

작성한 contract 는

interface IERC20 { ... }

contract TransferTest {
    function test(address recipient, address token, uint256 amount) public returns (bool) {
        return IERC20(token).transfer(recipient, amount);
    }

    function onKIP7Received(address _operator, address _from, uint256 _amount, bytes memory _data) public returns(bytes4) {
        return bytes4(keccak256("onKIP7Received(address,address,uint256,bytes)"));
    }
}

이며, 해당 contract 를 caver-js 를 활용해 호출한 코드는 다음과 같습니다.

... (생략) ...

const kxrpContract = caver.contract.create(iERC20ContractMeta.abi, kxrpAddress);
const approveRes = await kxrpContract.send({
  from: testAddress,
  gas: 10_0000,
}, 'approve', contractAddress, amount);
console.log(approveRes);  // success

const transferTestContract = caver.contract.create(transferTestContractMeta.abi, contractAddress);

// revert execution error 1
await transferTestContract.send({
  from: testAddress,
  gas: 100_0000,
}, 'test', otherUserAddress, kxrpAddress, amount);

// revert execution error 2
await transferTestContract.send({
  from: testAddress,
  gas: 100_0000,
}, 'test', contractAddress, kxrpAddress, amount);

error 1, erro 2 모두 revert 오류가 발생하는데 해당 코드의 어느 부분에 문제가 있는지 도움 받을 수 있을까요?

안녕하세요

주신 정보만으로는 에러의 원인을 파악하기 어렵습니다.
직접 노드를 운영하고 계시다면 debug의 traceTransaction으로 에러의 원인을 파악할 수 있습니다.

caver-js는 evm reverted가 나는 경우 해당 에러메세지만 받아 반환하므로 그 에러 메세지만으로는 에러를 파악할 수 없습니다.
만약 도움이 필요하시다면 에러를 재현하기 위하여 사용된 스마트컨트랙트의 전체 코드와 테스트코드가 필요합니다.

1개의 좋아요

답변 감사합니다! :slight_smile:

traceTransaction 을 통한 debugging 은 상당히 어렵네요.
아래는 traceTransaction 을 실행한 결과 입니다.

{
  failed: true,
  gas: 34741,
  returnValue: "",
  structLogs: [{
      depth: 1,
      gas: 69000,
      gasCost: 0,
      memory: [],
      op: "PUSH1",
      pc: 0,
      stack: [],
      storage: {}
  }, {
      depth: 1,
      gas: 68997,
      gasCost: 0,
      memory: [],
      op: "PUSH1",
      pc: 2,
      stack: ["0000000000000000000000000000000000000000000000000000000000000080"],
      storage: {}
  }, {
      depth: 1,
      gas: 68994,
      gasCost: 12,
      memory: ["0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000"],
      op: "MSTORE",
      pc: 4,
      stack: ["0000000000000000000000000000000000000000000000000000000000000080", "0000000000000000000000000000000000000000000000000000000000000040"],
      storage: {}
  }, {
      depth: 1,
      gas: 68982,
      gasCost: 12,
      memory: ["0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000080"],
      op: "PUSH1",
      pc: 5,
      stack: [],
      storage: {}
  }, ... ]
}

이 외에 여러가지 방법을 찾아보다가 해결이 되었는데요, 아래와 같이 solidity 코드를 수정하고 해결이 되었습니다.

function test(address recipient, address token, uint256 amount) public returns (bool) {
    (bool success, bytes memory data) = token.delegatecall(abi.encodeWithSignature("transfer(address,uint256)", recipient, amount));
    return success;
}

기본적으로 solidity compiler 가 method 호출을 call 로 compile 하여, 기대했던 msg.sender 값이 실제와 달랐던 것 같아요.

1개의 좋아요