1

I'm using truffle V5.1.13 and when I run truffle test the res variable contains a transaction receipt rather than the expected 2. I notice if I remove everything that has to do with the library things work as expected.

Why is this happening? How can I use my library?

Contract code:

pragma solidity ^0.5.1;

library TestLib{
    struct DataSet {
        uint a;
    }

    function assign(DataSet storage self) internal {
        self.a = 2;
    }

    function getA(DataSet storage self) internal view returns(uint) {
        return self.a;
    }
}

contract TestContract {
    using TestLib for TestLib.DataSet;
    TestLib.DataSet set;

    function getBalanceInEth() public returns(uint) {
        set.assign();
        return set.getA();
    }
}

Test code:

    const TestContract = artifacts.require('TestContract')

    contract('TestContract', async accounts => {
        let TestContractInstance

        beforeEach('setup contract for each test', async function() {
           TestContractInstance = await TestContract.deployed()
        })

        it('Should return 2', async () => {
           let res = await TestContractInstance.getBalanceInEth()
           console.log(res)
           assert.equal(res, 2)
        })
    })

Migration Code:

const TestContract = artifacts.require('TestContract')
const TestLib = artifacts.require('TestLib')
module.exports = function(deployer) {
  deployer.deploy(TestLib)
  deployer.link(TestLib, TestContract)
  deployer.deploy(TestContract)
}

console.log(res) gives:

{
  tx: '0x1f05b5fa7ed635aaa619cc548a0a37ff9d9d57398d85ecb3f8000ed7e124373c',
  receipt: {
    transactionHash: '0x1f05b5fa7ed635aaa619cc548a0a37ff9d9d57398d85ecb3f8000ed7e124373c',
    transactionIndex: 0,
    blockHash: '0xe6bc488fce167970b781588d1c70c0b4a452834c78daf4f052c1a045575fd959',
    blockNumber: 3,
    from: '0x627306090abab3a6e1400e9345bc60c78a8bef57',
    to: '0xf12b5dd4ead5f743c6baa640b0216200e89b60da',
    gasUsed: 42158,
    cumulativeGasUsed: 42158,
    contractAddress: null,
    logs: [],
    status: true,
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    rawLogs: []
  },
  logs: []
}

  • await TestContractInstance.getBalanceInEth returns a receipt because function getBalanceInEth is not declared pure or view. – goodvibration Feb 28 at 8:37
  • If I'm not mistaken, then you may be able to obtain the actual value by using await TestContractInstance.getBalanceInEth.call() – goodvibration Feb 28 at 8:39
  • @goodvibration I can't use view because getBalanceInEth changes TestLib.DataSet set. Nevertheless i tried your suggestion and get the following during compile TypeError: Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. set.assign(); – Conviley Feb 28 at 8:43
  • I didn't say that you should declare it view, I said that it returns a transaction receipt to your off-chain script because it is not declared view. It doesn't mean that you can declare it view without actually implementing it as one. – goodvibration Feb 28 at 8:52
  • And BTW, what do you mean "I notice if I remove everything that has to do with the library things"? If you remove that, then the function does nothing! Please be more specific, and show exactly how you change the function. – goodvibration Feb 28 at 8:54
0

A possible solution to this problem is to change the contract code to the following:

contract TestContract {
    using TestLib for TestLib.DataSet;
    TestLib.DataSet set;

    function setBalanceInEth() public {
        set.assign();
    }

    function getBalanceInEth() public view returns(uint) {
        return set.getA();
    }
}

And change the test code accordingly:

const TestContract = artifacts.require('TestContract')

contract('TestContract', async (accounts) => {
  let TestContractInstance

  beforeEach('setup contract for each test', async function() {
    TestContractInstance = await TestContract.deployed()
  })

  it('Should return 2', async () => {
    await TestContractInstance.setBalanceInEth()
    let res = await TestContractInstance.getBalanceInEth()
    console.log(res)
    assert.equal(res, 2)
  })
})
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.