I would like to know if it's possible to change the address of the message sender of contract's function call when writing unit tests in solidity. It really should be, I was trying to find out how but could not.
`pragma solidity ^0.4.4;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
contract A {
event Test(address add);
function test() {
Test(msg.sender);
}
}
contract TestA {
function test01() {
A a = A(DeployedAddresses.A());
a.test(); // <--- msg.sender is address(this), but how do we use a different account from testrpc?
}
}`
In gitter I got a response so I have tried to run it like this:
a.test({from: 0xf6a948bff792e4f42d7f17e5e4ebe20871d160f2});
It gives the following error:
TypeError: Wrong argument count for function call: 1 arguments given but expected 0.
a.test({from: 0xf6a948bff792e4f42d7f17e5e4ebe20871d160f2});
You can't change msg.sender in Solidity. Its value will always be the address making the call.
a.test({from: 0xf6a948bff792e4f42d7f17e5e4ebe20871d160f2}); is JavaScript code, not Solidity.
Is it possible to implement this? Along with the possibility of a change of msg.value and the likes? To be frank, I am surprised that this isn't possible currently since it should play a major part of the test cases given the scope.
It's already possible with Javascript tests, which is what most people use.
Read more here: http://truffleframework.com/docs/getting_started/javascript-tests
I know, except that I am getting eth_call: invalid opcode error when I am calling functions with parameters. Still, given that there is a possibility of writing tests in solidity, a way to access 'from' field should exist.
@berar - You can always take the hard way, by having a "testMethod" that instantiates a contract, that will then call your specified method, that way the msg.sender is the "new instance", thus allowing you to test for cases where the "code needs to revert / throw" in case of a different sender.
Just remember you will most likely need to use the low level "call" and check for true / false on the execution.
Problem with call is that you can only use it to determine if execution was successful or not. And in order to retrieve the method's return value you're going to have to go into assembly and do some memory assignment yourself.
It's nice to think of "solidity tests" as unit tests, and JS ones as integration, but in reality you probably want to stick to JS, as that's what everyone seems to be using these days.
Hi all,
@micky has the correct answer here - if you want to change your msg.sender in solidity tests, you need to make your test contract (TestSomething.sol) the owner of contract under test.
invalid opcode and revert are separate issues; what they mean is that your Solidity code had a runtime error when executing your transaction. _Why_ it had a runtime error depends on your code.
I'd recommend using the Truffle debugger any time you run into this error.
I'm going to close this ticket as @micky's answer is correct. Cheers!
@tcoulter but what if i want to test if my contract is properly storing/responding to multiple addresses?
E.g. if I have a Contract attribute of type array or some mapping with key being the sender address, i want to make sure the array is properly storing multiple users data.
I can only interact with my solidity test contract under 1 address?
I think I found an example how to do it in JS, which seems to be more capable: https://github.com/gustavoguimaraes/smart-contract-testing-javascript-example-/blob/master/test/fundRaise.js
UPDATE: Since 1.5 years I only use JS for testing Solidity contracts.
@EnchanterIO Did you find something in solidity to do it? Having hard time to switch b/w accounts in testrpc . How can i interact with my solidity test contract with more then 1 address?
Bug was probably introduced in 5.0.31. 5.0.30 works for me on Linux.
@digulla this issue is not a bug, it's the way msg.sender works in solidity, you probably have the wrong thread.
For those looking for a way to manipulate msg.sender in unit tests written in solidity, here's an alternative approach I've been using effectively:
SenderContract and a ReceiverContract, each one will have its own address and when they call the CUT functions msg.sender will be set to their deployed addresses
Most helpful comment
@berar - You can always take the hard way, by having a "testMethod" that instantiates a contract, that will then call your specified method, that way the msg.sender is the "new instance", thus allowing you to test for cases where the "code needs to revert / throw" in case of a different sender.
Just remember you will most likely need to use the low level "call" and check for true / false on the execution.
Problem with call is that you can only use it to determine if execution was successful or not. And in order to retrieve the method's return value you're going to have to go into assembly and do some memory assignment yourself.
It's nice to think of "solidity tests" as unit tests, and JS ones as integration, but in reality you probably want to stick to JS, as that's what everyone seems to be using these days.