PlatONnetwork / client-sdk-js

A javascript interface for interacting with the PlatON network
Other
24 stars 22 forks source link

client-sdk-js 同时实例化多个 wasm 合约的情况下,abi 对象会被覆盖,导致合约调用失败 #76

Closed wuyahuang closed 3 years ago

wuyahuang commented 3 years ago

Node.js 代码:

module.exports = class smartContract {
  constructor() {
    // market contract abi and wasm
    let marketRawData = fs.readFileSync('abi/market.abi.json');
    let marketAbi = JSON.parse(marketRawData);
    this.marketContract = new web3.platon.Contract(marketAbi, config.get("Blockchain.marketContractAddress"), { vmType: 1 });

    // verify contract abi and wasm
    let verifyRawData = fs.readFileSync('abi/verify.abi.json');
    let verifyAbi = JSON.parse(verifyRawData);
    this.verifyContract = new web3.platon.Contract(verifyAbi, config.get("Blockchain.verifyContractAddress"), { vmType: 1 });

    // token contract abi and wasm
    let tokenRawData = fs.readFileSync('abi/token.abi.json');
    let tokenAbi = JSON.parse(tokenRawData);
    this.tokenContract = new web3.platon.Contract(tokenAbi, config.get("Blockchain.tokenContractAddress"), { vmType: 1 });

  }
}

抛出异常:

(node:2168) UnhandledPromiseRejectionWarning: Error: 通过名字 deal 找不到结构体
    at ABICoder.decodeParameters (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-eth-abi/src/index.js:823:15)
    at Contract._decodeMethodReturn (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-eth-contract/src/index.js:687:22)
    at Method.outputFormatter (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-eth-contract/src/index.js:1104:46)
    at Method.formatOutput (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-core-method/src/index.js:167:54)
    at sendTxCallback (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-core-method/src/index.js:588:33)
    at /home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-core-requestmanager/src/index.js:147:9
    at XMLHttpRequest.request.onreadystatechange (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-providers-http/src/index.js:102:13)
    at XMLHttpRequestEventTarget.dispatchEvent (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-providers-http/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:22)
    at XMLHttpRequest._setReadyState (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-providers-http/node_modules/xhr2-cookies/dist/xml-http-request.js:208:14)
    at XMLHttpRequest._onHttpResponseEnd (/home/yy/contracts/platon-hackathon/client/node_modules/web3/packages/web3-providers-http/node_modules/xhr2-cookies/dist/xml-http-request.js:318:14)
(node:2168) 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(). (rejection id: 1)
(node:2168) [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.
DavidRomy commented 3 years ago

使用方法有问题,在一个作用域连续创建contract对象方法,请参考: var Contract = require('web3-eth-contract'); Contract.setProvider('http://localhost:6789'); var contract = new Contract(abi, address, { vmType: 1, net_type: 'lat'});

wuyahuang commented 3 years ago

以下代码,只实例化一个合约,运行正常。

const fs = require('fs');
const Web3 = require('web3');
const web3 = new Web3('http://192.168.1.64:6789');

(async function () {
  // market contract abi
  let marketRawData = fs.readFileSync('../build/contracts/market.abi.json');
  let marketAbi = JSON.parse(marketRawData);
  const marketContract = new web3.platon.Contract(marketAbi, 'lat1a2z0hxhnetej5ytsguel7xh69rq5praufl2cmv', { vmType: 1 });

  // verify contract abi
  let verifyRawData = fs.readFileSync('../build/contracts/verify.abi.json');
  let verifyAbi = JSON.parse(verifyRawData);
  // const verifyContract = new web3.platon.Contract(verifyAbi, 'lat14d4gt0amcxfq24ll8pp8rm5anqzdlu28k0l4es', { vmType: 1 });

  let methodObj = marketContract.methods['get_deal_by_cid'].apply(marketContract.methods, ['QmbtDWW6eiw8ZoWoKKPfHMA7KKqimJAvXjLWU4xsatc3ku']);
  let ret = await methodObj.call({});
  console.log(ret);
})();

如果运行第 14 行代码,实例化第二个合约 verifyContract 则运行失败,报错如下。

(node:4603) UnhandledPromiseRejectionWarning: Error: 通过名字 deal 找不到结构体
    at ABICoder.decodeParameters (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-eth-abi/src/index.js:823:23)
    at Contract._decodeMethodReturn (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-eth-contract/src/index.js:687:22)
    at Method.outputFormatter (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-eth-contract/src/index.js:1104:46)
    at Method.formatOutput (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-core-method/src/index.js:167:54)
    at sendTxCallback (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-core-method/src/index.js:588:33)
    at /home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-core-requestmanager/src/index.js:147:9
    at XMLHttpRequest.request.onreadystatechange (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-providers-http/src/index.js:102:13)
    at XMLHttpRequestEventTarget.dispatchEvent (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-providers-http/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:22)
    at XMLHttpRequest._setReadyState (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-providers-http/node_modules/xhr2-cookies/dist/xml-http-request.js:208:14)
    at XMLHttpRequest._onHttpResponseEnd (/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-providers-http/node_modules/xhr2-cookies/dist/xml-http-request.js:318:14)

deal 为合约自定义结构体,在 web3-eth-contract 源代码第 154行,每次实例化新的合约都会执行

abi.setAbi(jsonInterface);

而且 web3-eth-abi 只保存最后一次的 abi 数据,所以上一次实例化的合约 abi 会被覆盖。

wuyahuang commented 3 years ago

按照你的建议直接使用 web3-eth-contract 也是一样的错误。

const fs = require('fs');
var Contract = require('/home/yy/contracts/platon-hackathon/contract/tests/node_modules/web3/packages/web3-eth-contract');
Contract.setProvider('http://192.168.1.64:6789');

(async function () {
  // market contract abi
  let marketRawData = fs.readFileSync('../build/contracts/market.abi.json');
  let marketAbi = JSON.parse(marketRawData);

  const marketContract = new Contract(marketAbi, "lat1a2z0hxhnetej5ytsguel7xh69rq5praufl2cmv", { vmType: 1, net_type: 'lat' });

  // verify contract abi
  let verifyRawData = fs.readFileSync('../build/contracts/verify.abi.json');
  let verifyAbi = JSON.parse(verifyRawData);
  const verifyContract = new Contract(verifyAbi, "lat14d4gt0amcxfq24ll8pp8rm5anqzdlu28k0l4es", { vmType: 1, net_type: 'lat' });

  let methodObj = marketContract.methods['get_deal_by_cid'].apply(marketContract.methods, ['QmbtDWW6eiw8ZoWoKKPfHMA7KKqimJAvXjLWU4xsatc3ku']);
  let ret = await methodObj.call({});
  console.log(ret);
})();
DavidRomy commented 3 years ago

合约call调用建议分开封装调用。

wuyahuang commented 3 years ago

问题:同时实例化多个 wasm 合约,web3-eth-abi 中的 this.abi 会被覆盖,仅保存最后一个合约的 abi 数据。 解决方案:在每次调用合约时,将该合约中保存的 jsonInterface 对象重新给 web3-eth-abi 中的 this.abi 赋值。 https://github.com/PlatONnetwork/client-sdk-js/pull/77

biganxin commented 3 years ago

已解决