Caver.js 사용 컨트랙트 함수 호출 문의

const Caver = require('caver-js')
const caver = new Caver('https://ennode.url.com/')

const abi = JSON.parse('[{"inputs" : [],"stateMutability" : "nonpayable","type" : "constructor"},....}]');

const contractAddress = '0xExample2E1f240b64e097FF0';

const contractInstance = new caver.contract(abi, contractAddress, { gasPrice: '25000000000' })

contractInstance.methods.totalSupply().call().then(console.log)  <-이렇게 해도 안됩니다.

async function testGetContractValue() { <- 이렇게도 해봤습니다.

    const contractInstance = new caver.contract(abi, contractAddress, { gasPrice: '25000000000' })
    contractInstance.options.gas = 5000000
    contractInstance.options.gasPrice = '25000000000000'

    try {
        const val = await contractInstance.methods['totalSupply()'].call();
        //const value = await contractInstance.methods.decimals().call()
        console.log(val.data)
    }
    catch (error) {
        console.log("error: ", error.message)
    }
}

아래와 같은 에러가 발생합니다.

(node:58001) UnhandledPromiseRejectionWarning: Error: Returned values aren't valid, did it run Out of Gas?
    at ABICoder.decodeParameters (/User/caver-js/node_modules/caver-js/packages/caver-abi/src/index.js:256:15)
    at Contract._decodeMethodReturn (/User/caver-js/node_modules/caver-js/packages/caver-contract/src/index.js:567:24)
    at Method.outputFormatter (/User/caver-js/node_modules/caver-js/packages/caver-contract/src/index.js:997:42)
    at _formatOutput (/User/caver-js/node_modules/caver-js/packages/caver-core-method/src/index.js:207:87)
    at Method.formatOutput (/User/caver-js/node_modules/caver-js/packages/caver-core-method/src/index.js:211:60)
    at /User/caver-js/node_modules/caver-js/packages/caver-core-method/src/index.js:240:25
    at /User/caver-js/node_modules/caver-js/packages/caver-core-requestmanager/src/index.js:162:17
    at XMLHttpRequest.request.onreadystatechange (/User//caver-js/node_modules/caver-js/packages/caver-core-requestmanager/caver-providers-http/src/index.js:119:13)
    at XMLHttpRequestEventTarget.dispatchEvent (/User/caver-js/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:22)
    at XMLHttpRequest._setReadyState (/User/caver-js/node_modules/xhr2-cookies/dist/xml-http-request.js:208:14)
(node:58001) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:58001) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

안녕하세요.

먼저 비슷한 코드로 따로 테스트를 해보았는데, 정상적으로 작동하는 것을 확인했습니다.
발생한 에러는 totalSupply의 리턴값이 유효하지 않을 경우 발생하는 에러입니다.
스크린샷 2021-01-28 오전 8.29.58

아래에 코드로 바오밥에 배포된 KIP-7 컨트랙트의 totalSupply 값을 조회할 수 있으니 참고 부탁드립니다.

const caver = new Caver('BAOBAB URL')
const contract = new caver.contract(
    [
        {
            constant: true,
            inputs: [],
            name: 'totalSupply',
            outputs: [{ name: '', type: 'uint256' }],
            payable: false,
            stateMutability: 'view',
            type: 'function',
        },
    ],
    '0x2e291dEBd4cc0DCDD2916158d93C7d9D2595714f'
)
contract.options.gas = 5000000
contract.options.gasPrice = '25000000000000'
const val = await contract.methods.totalSupply().call()
console.log(val)

이렇게 해보았는데요.

    const val = await contractInstance.methods['totalSupply()'].call();
    console.log(val)

결과가 아래와 같이 받아집니다.

{
  call: [Function: bound _executeMethod] {
    request: [Function: bound _executeMethod]
  },
  send: [Function: bound _executeMethod] {
    request: [Function: bound _executeMethod]
  },
  encodeABI: [Function: bound _encodeMethodABI],
  estimateGas: [Function: bound _executeMethod],
  arguments: [],
  _method: {
    inputs: [],
    name: 'totalSupply',
    outputs: [ [Object] ],
    stateMutability: 'view',
    type: 'function',
    signature: '0x18112333'
  },
  _parent: Contract {
    currentProvider: [Getter/Setter],
    _requestManager: RequestManager {
      provider: [HttpProvider],
      providers: [Object],
      subscriptions: {}
    },
    providers: {
      WebsocketProvider: [Function: WebsocketProvider],
      HttpProvider: [Function: HttpProvider],
      IpcProvider: [Function: IpcProvider]
    },
    _provider: HttpProvider {
      host: 'https://enode.rpcurl.com/',
      timeout: 0,
      headers: undefined,
      connected: false
    },
    setProvider: [Function],
    setRequestManager: [Function],
    BatchRequest: [Function: bound Batch],
    clearSubscriptions: [Function],
    options: {
      address: [Getter/Setter],
      jsonInterface: [Getter/Setter],
      from: [Getter/Setter],
      gasPrice: [Getter/Setter],
      gas: [Getter/Setter],
      data: [Getter/Setter]
    },
    defaultAccount: [Getter/Setter],
    defaultBlock: [Getter/Setter],
    methods: {
      totalSupply: [Function: bound _createTxObject],
      '0x18': [Function: bound _createTxObject],
      'totalSupply()': [Function: bound _createTxObject],
    },
    events: {
      Approval: [Function: bound ],
      '0x8': [Function: bound ],
      'Approval(address,address,uint256)': [Function: bound ],
      OwnershipTransferred: [Function: bound ],
      '0x8': [Function: bound ],
      'OwnershipTransferred(address,address)': [Function: bound ],
      Transfer: [Function: bound ],
      '0xd': [Function: bound ],
      'Transfer(address,address,uint256)': [Function: bound ],
      allEvents: [Function: bound ]
    },
    _address: '0x3',
    _jsonInterface: [
      [Object], [Object], [Object],
      [Object], [Object], [Object],
      [Object], [Object], [Object],
      [Object], [Object], [Object],
      [Object], [Object], [Object],
      [Object], [Object], [Object],
      [Object], [Object], [Object],
      [Object], [Object], [Object],
      [Object], [Object]
    ],
    _keyrings: KeyringContainer {
      _addressKeyringMap: Map {},
      keyring: [Function]
    },
    _gas: 5000000,
    _gasPrice: '25000000000000'
  },
  _klayAccounts: undefined,
  _keyrings: KeyringContainer {
    _addressKeyringMap: Map {},
    keyring: [class KeyringFactory] {
      privateKey: [class PrivateKey],
      singleKeyring: [class SingleKeyring extends AbstractKeyring],
      multipleKeyring: [class MultipleKeyring extends AbstractKeyring],
      roleBasedKeyring: [class RoleBasedKeyring extends AbstractKeyring],
      role: [Object],
      signatureData: [Function]
    }
  }
}

안녕하세요, 아래와 같이 호출해 보시겠어요?

const val = await contractInstance.methods.totalSupply().call();

안됩니다ㅠ

const Caver = require('caver-js')
const caver = new Caver('https://ennode.rpcurl.com/')

const contractAddress = '0x3';
const abi = require('./token_abi.json')

async function testGetContractValue() {

    const contractInstance = new caver.contract(abi, contractAddress)
    contractInstance.options.gas = 5000000
    contractInstance.options.gasPrice = '25000000000000'

    try {
        const val = await contractInstance.methods.totalSupply().call();
        console.log(val)
    }
    catch (error) {
        console.log("error: ", error.message)
    }
}

결과
$ node ./test.js
error: Returned values aren’t valid, did it run Out of Gas?

정확한 컨트랙트 주소나 ABI없이는 확인해 드리기 어려울 것 같습니다.

컨트랙트 주소가 정확한지 네트웍은 맞는지(Baobab, Cypress) 확인 부탁드리겠습니다.

내부 테스트 중인 서버입니다.
ABI의 경우 totalSupply, decimals 는 표준이라 똑같이 작성했는데, 차이가 있지 않습니다

{
    "inputs" : [],
    "name" : "totalSupply",
    "outputs" : [ 
        {
            "internalType" : "uint256",
            "name" : "",
            "type" : "uint256"
        }
    ],
    "stateMutability" : "view",
    "type" : "function"
},

혹시 구축해놓은 EN 서버에 모듈을 아래와 같이만 올려두었는데요.

$ curl -H “Content-Type: application/json” --data ‘{“jsonrpc”:“2.0”,“method”:“rpc_modules”,“params”:[],“id”:1}’ https://node.rpcurl.com
{“jsonrpc”:“2.0”,“id”:1,“result”:{“klay”:“1.0”,“rpc”:“1.0”,“web3”:“1.0”}}

모듈과의 관련은 없을까요?

혹시 빌드는 어떻게 하셨는지 알 수 있을까요? solidity compiler version을 알려주시면 좋을 것 같습니다. 현재 클레이튼은 constantinople EVM까지만 지원합니다.

저희가 사용하는 solidity 버전은
pragma solidity ^0.6.0;
입니다.

그럼 컴파일러 버전을 최소 0.6.0을 사용하실 것 같은데요, solc 빌드 명령을 알 수 있을까요? 트러플로 빌드하셨다면 그 정보를 주셔도 좋습니다.

아래 링크처럼 compiler사용시에 EVM target을 정할 수 있는데, 거기에 constantinople EVM으로 설정하고 다시 빌드 및 배포하고 확인 부탁드리겠습니다.

https://docs.soliditylang.org/en/v0.6.0/using-the-compiler.html#setting-the-evm-version-to-target

혹시 해결 되셨나요 저도 똑같은 문제를 겪고 있는데 어떻게 해결해야 할지 를 잘 모르겠습니다