I have the following scenario.

Contract A {
  mapping (address => bool) public allowed;
  mapping (address => uint) public userData;

  function doSomething(address _user) public returns(bool){
      return true;
    } else
      return false;  

Contract B {
  function doSomethingWithA(){
     A contractA = A(_Aaddress);
       // Do something
       // don't

Contract A holds a mapping of which users are allowed to interact with it. Contract A has a function that should only be called by contract B.

ONLY the EOA interacting with B should be able to execute A's doSomething().

In the current scenario, anyone could call doSomething(address _user) and pass an allowed _user to get a valid result.

I could require(msg.sender == _user); in doSomething(address _user) but that would cause the function to fail as the msg.sender would always be contract B.

I know I could use tx.origin instead of msg.sender, but I was wondering if that would compromise the security of the contract.

So, my questions are:

  1. Is there any other way to solve this without using tx.origin?
  2. If the only way is with tx.origin. What should I have in mind in order to prevent an attack related to the usage of tx.origin?

1 Answer 1


ONLY the EOA interacting with B should be able to get true from checkIfAllowed(address _user).

Why? What difference does it make?

In the current scenario, anyone could call checkIfAllowed(address _user) and pass an allowed _user to get a valid result.

This is true, but I don't see why it's a problem. What's the attack you're trying to prevent? Everything on the blockchain is public, so anyone can always find out which users A will allow. So arbitrary accounts calling checkIfAllowed doesn't introduce any sort of security flaw.

From your simplified example, I assume the intent is that B doesn't let doSomething succeed unless the account calling into B is "allowed" by A. The current code appears to have that intended effect.

If there's some other goal, please elaborate on what it is.

  • I just updated the question and modified the code to make my intentions more clear. I want A's doSomething() to modify some state variables only if the caller EOA is allowed to do so. BUT, this function is not to be called directly from Contract A, it should only be called by another contract (In this case, Contract B). Commented Dec 21, 2017 at 18:33
  • I know the information is public, that is not an issue. The issue is that I want to prevent someone other than the EOA calling the function to modify the state, but that is done by first passing through contract B and in that case msg.sender will always be contract B. Commented Dec 21, 2017 at 18:34
  • What's special about contract B? Why not just (in contract A) require(msg.sender == addressForContractB);?
    – user19510
    Commented Dec 21, 2017 at 18:37
  • I'm essentially pushing back on the idea of "This should only happen if the EOA that started the transaction is X." tx.origin does that, but it's pretty much never really what you want. (For example, a malicious contract called by X could in turn call into A. X can mitigate that by reading the contract code he's calling into, but that's a somewhat weak mitigation.) If you want only X to be able to do something, let X call into contract A directly and then call into contract B.
    – user19510
    Commented Dec 21, 2017 at 18:40
  • Imagine Contract A is a contract that generates promo codes. a promo code is generated by Contract A to be used only by a certain address A specifies. Contract B is a store that wants to implement promo codes. So it would receive the call from the account, pass it to contract A, which will check if the user has been given allowed to use the promo code and if yes, it will mark it as used and return OK to the Store contract. The user should never interact with contract A, but with the Store that implements such promo code. Commented Dec 21, 2017 at 18:43

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.