Web3js

solc-js 錯誤:“部署契約”的“每個之前”掛鉤:SyntaxError:位置 0 處 JSON 中的意外令牌 u

  • March 31, 2022

問題大概出在這裡:const { interface, bytecode } = require('../compile');.

interface在測試文件中是undefined.

收件箱/契約/Inbox.sol:

pragma solidity ^0.7.0;

contract Inbox {
   string public message;

   constructor(string memory initialMessage) {
       message = initialMessage;
   }

   function setMessage(string memory newMessage) public {
       message = newMessage;
   }
}

收件箱/compile.js:

const path = require('path');
const fs = require('fs');
const solc = require('solc');

const inboxPath = path.resolve(__dirname, 'contracts', 'Inbox.sol');
const source = fs.readFileSync(inboxPath, 'utf8');

var input = {
   language: 'Solidity',
   sources: {
       'Inbox.sol' : {
           content: source
       }
   },
   settings: {
       outputSelection: {
           '*': {
               '*': [ "abi", "evm.bytecode" ]
           }
       }
   }
};

module.exports = solc.compile(JSON.stringify(input));

收件箱/測試/收件箱.test.js:

const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const { interface, bytecode } = require('../compile');

let accounts;
let inbox;
beforeEach(async () => {
   //get a list of all accounts

   accounts = await web3.eth.getAccounts();

   //use one of those accounts to deploy the contract
   inbox = await new web3.eth.Contract(JSON.parse(interface))
       .deploy({ data: bytecode, arguments: ['Hi there!'] })
       .send({from: accounts[0], gas: '1000000'});
});

describe('Inbox', () => {
   it('deploys a contract', () => {
       console.log(inbox);
   })
})

執行npm run test時拋出:

 Inbox
   1) "before each" hook for "deploys a contract"


 0 passing (366ms)
 1 failing

 1) "before each" hook for "deploys a contract":
    SyntaxError: Unexpected token u in JSON at position 0
     at JSON.parse (<anonymous>)
     at Context.<anonymous> (test\Inbox.test.js:15:46)
     at processTicksAndRejections (internal/process/task_queues.js:97:5)

以這種方式解決:

const compile = require('../compile');
const interface = JSON.parse(compile).contracts["Inbox.sol"].Inbox.abi;
const bytecode = JSON.parse(compile).contracts["Inbox.sol"].Inbox.evm.bytecode.object;

我重命名了介面變數“abi”並從beforeEach測試文件中刪除了 Parse,因為這是在編譯器中完成的。

編譯.JS文件

// build path from compiler to solidity file
const path = require('path');
const fs = require('fs');
const solc = require('solc');

//for unix and windows
//take you from root dir to this inbox folder and both files
const inboxPath = path.resolve(__dirname, 'contracts', 'inbox.sol');

// read contents of file with encoding
const source = fs.readFileSync(inboxPath, 'utf-8');

var input = {
   language: 'Solidity',
   sources: {
       'inbox.sol' : {
           content: source
       }
   },
   settings: {
       outputSelection: {
           '*': {
               '*': [ '*' ]
           }
       }
   }
};


// parses solidity to English and strings 
var output = JSON.parse(solc.compile(JSON.stringify(input)));

var outputContracts = output.contracts['inbox.sol']['Inbox']

// exports ABI interface
module.exports.abi = outputContracts.abi;

// exports bytecode from smart contract
module.exports.bytecode = outputContracts.evm.bytecode.object;

收件箱.test.js

const assert = require('assert');
const ganache = require('ganache-cli');
// constructor
const Web3 = require('web3');
// new instance and to connect it to ganache
const web3 = new Web3(ganache.provider());

const {abi, bytecode} = require('../compile');


// set global variables
let accounts;
let inbox;

beforeEach(async () =>  {
   // get list of all accounts
   accounts = await web3.eth.getAccounts()

   // use account to deploy contract
   inbox = await new web3.eth.Contract((abi))
       .deploy({ data: bytecode, arguments: ['Hi there!']})
       .send({ from: accounts[0], gas: '1000000'});

});

describe('Inbox', () => {
   it('deploys a contract', () => {
       console.log(inbox)
   });
});

引用自:https://ethereum.stackexchange.com/questions/86557