Search code examples
javascriptblockchainsolidityweb3js

Solidity - When deploying the contract I get "SyntaxError: Unexpected token o in JSON at position 1"


I just started learning solidity, but I am not able to deploy the contract successfully. When I npm run test I get: SyntaxError: Unexpected token o in JSON at position 1

My contract Inbox.sol:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract Inbox {
    string public message;

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

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

My compiler 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: {
            '*': {
                '*': [ '*' ]
            }
        }
    }
}; 

var output = JSON.parse(solc.compile(JSON.stringify(input)))

module.exports = output.contracts["Inbox.sol"]["Inbox"];

My mocha test Inbox.test.js:

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

var accounts;
var inbox;

beforeEach(async () => {
    accounts = await web3.eth.getAccounts();

    inbox = await new web3.eth.Contract(JSON.parse(evm))
        .deploy({ data: abi, arguments: ['Hi there!'] })
        .send({ from: accounts[0], gas: '1000000' })
})

describe('Inbox Contract', ()=> {
    it('Can test', ()=> {
        console.log(inbox)
    })
})

I am not sure what part of JSON is wrong since it can't parse it correctly. When I log abi in Inbox.test.js I get this:

Inbox Contract
[ { inputs: [ [Object] ],
    stateMutability: 'nonpayable',
    type: 'constructor' },
  { inputs: [],
    name: 'message',
    outputs: [ [Object] ],
    stateMutability: 'view',
    type: 'function' },
  { inputs: [ [Object] ],
    name: 'setMessage',
    outputs: [],
    stateMutability: 'nonpayable',
    type: 'function' } ]

Logging evm gives me a very large block of code I won't be pasting here.


Solution

  • In version pragma solidity ^0.8.9, my working code looks like this

    Inbox.sol

    pragma solidity ^0.8.9;
    
    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');
    
    const input = {
        language: 'Solidity',
        sources: {
            'Inbox.sol': {
                content: source,
            },
        },
        settings: {
            outputSelection: {
                '*': {
                    '*': ['*'],
                },
            },
        },
    };
    
    module.exports = JSON.parse(solc.compile(JSON.stringify(input))).contracts['Inbox.sol'].Inbox;
    

    Inbox.test.js

    const assert = require('assert');
    const ganache = require('ganache-cli');
    const Web3 = require('web3');
    const web3 = new Web3(ganache.provider());
    
    const { abi, evm } = require('../compile');
    
    let accounts;
    let inbox;
    
    beforeEach(async () => {
        // Get a list of all accounts
        accounts = await web3.eth.getAccounts();
        inbox = await new web3.eth.Contract(abi)
            .deploy({
                data: evm.bytecode.object,
                arguments: ['Hi there!'],
            })
            .send({ from: accounts[0], gas: '1000000' });
    });
    
    describe('Inbox', () => {
        it('deploys a contract', () => {
            console.log(inbox);
        });
    });