2

I want to test my truffle contract with multiple msg.sender addresses. Like "the first user sell token, the second user buys this token". For one address I simply write something like contract.buy.value(10 wei)();. But where I could get another address and how to send money from him?

I write my tests on solidity, not on javascript.

1
  • Consider writing your tests in Javascript. Sep 2, 2018 at 7:41

3 Answers 3

1

Yes you can, do your test in Javascript.

In your test you can initialize it like this:

const MyContract = artifacts.require('MyContract');

contract('MyContract', accounts => {
  const owner = accounts[0];
  const alice = accounts[1];
  const bob = accounts[2];

  it('should do something', async () => {
    const contract = await MyContract.deployed();
    await contract.buy(price, data, { from: alice });
    await contract.buy(price, data, { from: bob });
    assert.equal(...);
  });
});

Notice the accounts variable. Hope this helps.

2
  • He specifically said he's writing his tests in Solidity, not JavaScript Sep 2, 2018 at 16:29
  • Yes but just with Solidity it's not possible that I'm aware of. Just giving another approach. Sep 2, 2018 at 22:03
1

Contracts are also accounts! Pretty useful pattern:

First, we create the actual Thing we like.

pragma solidity ^0.8.10;

contract Thing {
    address public owner;
    uint argument;

    modifier restricted() {
        require(msg.sender == owner);
        _;
    }

    constructor (uint _argument) {
        owner = msg.sender;
        argument = _argument;
    }

    function doThing() public restricted {}
}

Then we make a thing to make, and thus own, more Things.

// test/ThingMaker.sol (truffle only runs
// files beginning with Test but you could 
// put it somewhere else too)
pragma solidity ^0.8.10;

import "../contracts/Thing.sol";

contract ThingMaker {
    function makeThing(uint argument) public returns (Thing) {
        Thing thing = new Thing(argument);
        return thing;
    }
}

Finally, we have a test for the Things which can use any number of Things they do, or do not, own (you can just make a Thing[] preOwnedThingArray if you like). All tests pass! Be sure to use actual error messages though.

// test/TestThing.sol
pragma solidity ^0.8.10;

import "../contracts/Thing.sol";
import "./ThingMaker.sol";

contract TestThing {
    Thing preOwnedThing;

    function beforeEach() public {
        uint arg = 123;
        ThingMaker maker = new ThingMaker();
        preOwnedThing = maker.makeThing(arg);
    }

    function testOwnerCanDoThing() public {
        uint arg = 123;
        Thing thing = new Thing(arg);
        thing.doThing();
    }

    function testNonOwnerCannotDoThing() public {
        try preOwnedThing.doThing() {
            assert(1==2);
        } catch {}
    } 

}

Now this covers the 0 and 1 unprivileged account case - if you instead want to interact with one contract with a bunch of accounts, you can flip the script and just create a ThingInteractor.sol, but I'm afraid you're probably going to have to make separate function in that contract (maybe there's some magic to avoid that, will have to try to remember to get back to you if I can think of some) to interact with whatever you like and then just create new ThingInteractors on demand.

0

I am not sure if this is possible, but you can use beforeAll/beforeEach hooks in Solidity tests to get the contract to desired state before testing.

So for your example, you add a before hook and manually set the state as if contract.buy.value(10 wei)(); was called by another account beforehand.

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.