1

I havae two contract Record and Register.

Register.sol looks like:

pragma solidity ^0.4.24;

contract Register {
    string private name;

    constructor(string entityname) public {
        name = entityname;
    }

    function getName() public view returns (string username) {
        return name;
    }
}

And in Record.sol:

pragma solidity ^0.4.24;

import "./Register.sol";

contract Record {    
    constructor(address ownerAddr, address providerAddr) public {
        Register(ownerAddr).getName();
        Register(providerAddr).getName();
    }
}

FYI, Record just want to call getName() method of Register contract in its constructor. In the test file I want to create new Record using the following code but got this error VM Exception while processing transaction: revert.

beforeEach('create new Register and Record contract', async () => {
    providerA = await Register.new("Dr Strange", {from: accounts[0]});
    providerB = await Register.new("Maybe", {from: accounts[1]});
    record = await Record.new(providerA.address, providerB.addresss);
})

What should I do?

  • Truffle v4.1.14 (core: 4.1.14)

  • Solidity v0.4.24 (solc-js)

  • Ganache v1.2.2

============================ UPDATE ==============================

I think its the problem of the contract iteself, not the test script. Because using Remix, Register contract can be deployed, but Record cannot even be deployed.

7
  • Change returns (string username) to returns (string). Commented Sep 3, 2018 at 7:14
  • Changed to returns (string). Problem exists.
    – Steven Luo
    Commented Sep 3, 2018 at 7:15
  • Also, run console.log(providerA.address, providerB.addresss). Make sure that they are not undefined. That would explain the revert exception. On web3.js v1 you should use _address, not address (though Truffle uses web3.js v0 as far as I'm aware of). Commented Sep 3, 2018 at 7:16
  • The output is 0x048964912779d7896841ecb0ab2ac2ca8a022d39 0x568d7256e3aa7789bc039f314eeebba7ff3005a9 and they exist in Ganache as CREATED CONTRACT ADDRESS.
    – Steven Luo
    Commented Sep 3, 2018 at 7:19
  • So maybe it's the fact that you're creating temporary instances. Try to declare the two instances first, and only then call the getName function. Commented Sep 3, 2018 at 7:21

3 Answers 3

1

guestA and guestB are not initialized yet. Therefore, their values will be 0. You can't call getName on address 0.

You'll have to initialize these variables with the addresses of the actual deployed Registers.

1
  • Thanks for the replay. But the previous post was misleading. As stated in the updated post, both Register contracts has been initialized in the test script
    – Steven Luo
    Commented Sep 3, 2018 at 5:35
1

Take a minute to think what does Register(ownerAddr) even mean.

The constructor of contract Register takes a string, not an address.

That said, here is how I would implement this:

File IRegister.sol:

pragma solidity ^0.4.24;

interface IRegister {
    function getName() public view returns (string);
}

File Register.sol:

pragma solidity ^0.4.24;

import "./IRegister.sol";

contract Register is IRegister {
    string private name;

    constructor(string entityname) public {
        name = entityname;
    }

    function getName() public view returns (string) {
        return name;
    }
}

File Record.sol:

pragma solidity ^0.4.24;

import "./IRegister.sol";

contract Record {
    constructor(address ownerAddr, address providerAddr) public {
        IRegister x = IRegister(ownerAddr);
        IRegister y = IRegister(providerAddr);
        string xName = x.getName();
        string yName = y.getName();
    }
}
1

Well, problem solved. But someone please tell me why.

The problem is solved by seperating the record contract initializer to it part, namely from

beforeEach('create new Register and Record contract', async () => {
    providerA = await Register.new("Dr Strange", {from: accounts[0]});
    providerB = await Register.new("Maybe", {from: accounts[1]});
    record = await Record.new(providerA.address, providerB.addresss);
})

to

beforeEach('create new Register and Record contract', async () => {
    providerA = await Register.new("Dr Strange", {from: accounts[0]});
    providerB = await Register.new("Maybe", {from: accounts[1]});
})

it("check record initializer", async () => {
    record = await Record.new(providerA.address, providerB.address, "Test");
    record.owner().then(patient => {
        assert.equal(patient, accounts[1], "Owner of the record is wrong!");
    })
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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