9

I want to create a viewable function (needs to return a string to the user) that searches a mapping for msg.sender and if the senders value is x, I want the contract to proceed accordingly. It all does work inside remix but if I upload it to ropsten, it doesn't anymore. Is this a known issue? I have tried tx.origin as well, same result. That's the problematic code I tried:

function getLink() public view returns(string){
    if(tokenBalances[msg.sender]>0){
        return link;
    }else{
        return "You need to purchase a token at first...";
    }
}

EDIT: I think the problem is, that when using a viewable function there is no msg.sender because there is no actual transaction? Is there a way to return a value to the user without using the "view" functions?

scoperationX
  • 127
  • 1
  • 9
  • Are you setting `from` in the `call()` to the account you want to set `msg.sender` to? – carver Aug 14 '18 at 18:48
  • @carver how do you mean that? – scoperationX Aug 14 '18 at 18:52
  • @carver Edited the post, that's the code I'm having problems with... – scoperationX Aug 14 '18 at 18:56
  • 2
    You'll need to show how you're calling the function (or tell us what tool). When calling a view function, the `from` address is optional, but if you provide it, `msg.sender` will have that value. – user94559 Aug 14 '18 at 20:11
  • 1
    @smarx The function should be called directly from myetherwallet. But for some reason, the view functions can't get msg.sender, it's always 0x0000... – scoperationX Aug 14 '18 at 20:16
  • @smarx as long as I try inside remix, it's all fine but when I try to use it from myetherwallet (ropsten network), it doesn't work... – scoperationX Aug 14 '18 at 20:17
  • My guess would be that myetherwallet doesn't specify a `from` address. I haven't looked at their code. – user94559 Aug 14 '18 at 21:04
  • @smarx is it possible to specify such settings for the contract? – scoperationX Aug 14 '18 at 21:09
  • I'm not sure what you're asking. If you're asking whether there's a way to get MyEtherWallet to specify a `from` address, I have no idea. (You'd probably get better results asking them.) – user94559 Aug 14 '18 at 21:10
  • Well thank you, the problem really seems to be at myetherwallet, so theres not much I can do right now... – scoperationX Aug 14 '18 at 21:18

1 Answers1

20

Short answer

msg.sender does work in a view function, although it is useless as an authorization scheme. The lookup tool you use should have a mechanism to set the sender.

Call vs Transaction

First, it's important to understand the difference between a call and a transaction.

It appears you're running a call, which runs quickly and does not alter the state of the blockchain. msg.sender is set in both a transaction and a call. In a transaction, it cannot be faked: you must have the private key associated with the given account. But in a call, you are free to set the sender to any value you like.

Setting the Sender

How you set the sender depends on what tool you are using to call. That tool might be web3.js, web3.py, Mist, MyEtherWallet, MyCrypto, etc. They all have (or might not have!) a mechanism to set the sender in a call.

MyEtherWallet

In the comments, you mention MyEtherWallet specifically. In a quick search, I didn't find anything about how to set the sender. There is this unanswered question on ethereum.stackexchange that seems worth following, since it is asking roughly the same question: How to check msg.sender balance with MyEtherWallet contract

Contract Workarounds

is it possible to specify such settings for the contract?

There is no way to help someone set the sender from inside the contract. But you can supply a different method that takes an address as an argument. Then tools like MyEtherWallet will allow you to set the address of interest. For example:

function getLink(address account) public view returns(string){
    if(tokenBalances[account] > 0){
        return link;
    }else{
        return "You need to purchase a token at first...";
    }
}

Hiding Data

It's worth noting that hiding data by checking msg.sender is useless. Anyone can set a fake sender in a call (or directly inspect blockchain state). So, it's trivial to bypass this "protection."

carver
  • 2,229
  • 12
  • 28
  • 4
    Thanks a lot, I wasn't really aware of the difference between a call and a transaction. I do know that hiding stuff behind msg.sender is pointless because of the visibility of, well, everything... I just needed this contract as a rather easy example. It seems like Myetherwallet doesn't get msg.sender in the call I made. I tested it with a simple return msg.sender call and indeed it just returns 0x000[...]. So again, thanks a lot for your extensive reply! – scoperationX Aug 14 '18 at 21:59