4

First, I'm aware of a similar question, but that answer is not sufficient.

Say I deployed an contract A, then I deploy another contract B some time later. I want to make sure that a function A.f1() in A can only be called from contract B. To do so, I implement a function register(address trusted_contract) to register B to A, which basically stores B's address to an array in A.. Since I own A, I'm the only one who can call it to register an address.

Now if B calls A.f1(), then within f1(), I check if msg.sender is in the array and decide if to serve the call.

Is this the right way to do it?

If it is, I still have a questions. What prevent another contract C to send a msg and claims that it is B? My understanding is that unlike an external account, a contract does not have a private key and thus can not sign a message. If so, how does receiver A verify the caller is contract B, not some bad actor C?

2 Answers2

1

Is this the right way to do it?

Yes, except instead of an array you should use a map for efficient look up.

If so, how does receiver A verify the caller is contract B, not some bad actor C?

There are 2 ways an "attacker" can act:

  1. Send a transaction directly to your contract A.
  2. Send a transaction to some contract X (different from contract B), then inside the contract X a message call will be made to your contact A.

Inside the contract A two properties will be available:

  • tx.origin - the external account address.
  • msg.sender - the external account address for case 1; address of contract X for case 2.

msg.sender is what you will be checking to verify that the call is made from contract B.

In both cases the "attacker" can't fake to be contract B:

  • for the 1st case he would need to sign the transaction with the private key of contract B which does't exist;
  • for the 2nd case he doesn't have control over msg.sender because it's handled by the EVM: when a message call is made from contract X, the EVM must set the msg.sender to be the address of contract X.

So unless the "attacker" sends the transaction to contract B there will be no way for him to fake to be contract B.

medvedev1088
  • 10,996
  • 5
  • 35
  • 63
  • Thank you! What in my mind was attack 2, and what you said cleared up my doubts. "he doesn't have control over msg.sender because it's handled by the EVM"! – user3839198 Feb 01 '18 at 20:46
0

Yes that is correct. What prevents an account from sending a transaction as contract B is that the account would need the private/public keypair to sign the transaction under the identity of the contract.

hextet
  • 1,583
  • 7
  • 28