1

I'm using a simplified version of a contract provided by Solidity website. My contract is as follows:

pragma solidity ^0.4.4;

import "./ConvertLib.sol";
contract MetaCoin {
   address owner;
   uint val;    

   function MetaCoin() {
       owner= msg.sender;
  }

    modifier onlyOwner {
    require (msg.sender==owner);
    _;
  }
  function change() onlyOwner{
  val=55;
 }
 function get_owner() returns (address){
 return owner;
 }
}

And my test contract is as below:

pragma solidity ^0.4.2;

 import "truffle/Assert.sol";
 import "truffle/DeployedAddresses.sol";
 import "../contracts/MetaCoin.sol";

 contract TestMetacoin {

 function test1(){
 MetaCoin meta = MetaCoin(DeployedAddresses.MetaCoin());
 meta.change();
 }

 function test2(){
 MetaCoin meta = MetaCoin(DeployedAddresses.MetaCoin());
 Assert.equal(meta.get_owner(), msg.sender, "I must be the owner");
}
}

I'm using testrpc. So first I deploy the 1st contract: "truffle deploy" and then I run the test one: "truffle test".

Problem: test2 passes but test1 cannot. If I remove "onlyOwner" from change() then test1 can pass.

Question: Why cannot test1 pass and what is the solution?


Please note that both contracts are compiled without any error.

3
  • There's something wrong with your example since MetaCoin doesn't have a test method, it should fail always. Did you mean change instead of test? In such case can you put the exact error message from truffle?
    – Ismael
    Commented Aug 25, 2017 at 0:24
  • @Ismael thanks for your comment. Well truffle allows you to "deploy" and "test" your contract using the commands: truffle deploy and truffle test. You don't need to have any test "method" in your code. See here: truffleframework.com/docs/getting_started/testing
    – Aydin
    Commented Aug 25, 2017 at 8:45
  • I mean meta.test(); is incorrect because Metacoin doesn't have a test() method.
    – Ismael
    Commented Aug 25, 2017 at 8:52

1 Answer 1

5

It fails because the call is inside TestMetacoin.test1() and when a contract A makes a call to another contract B, then msg.sender inside of B is the address of A.

  1. Owner calls TestMetacoin.test1()
  2. Inside TestMetacoin.test1() msg.sender equals owner address
  3. test1() calls MetaCoin.change()
  4. Inside MetaCoin.change() msg.sender is the address of TestMetacoin

You cannot change the sender from within a solidity contract, so I'd suggest to make that test from the javascript side which can easily change the sender adding {from: "0x...." } to the transaction.

1
  • 1
    Thanks for the clear answer! I cannot upvote you as I don't have enough "reputation" yet.
    – Aydin
    Commented Aug 25, 2017 at 9:16

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.