'Restrict function access ONLY to one other specific contract in Solidity

I have a security problem in my Solidity contracts and I can't figure out how to fix it.

The flow goes like this:

  • First, we create an instance of contract A;
  • Create an instance of contract B, which receives the contract A instance in the constructor (its address);
  • At some point, contract B calls a function 'foo' from contract A which tells contract A to send money to an address (the address is received as a parameter);
  • Contract A sees the msg.sender as the address of contract B;

My problem is:

  • I want to restrict the access for the function 'foo' in contract B only to be called by contract A (no calls made by humans manually);
  • I cannot make a modifier to check the address. Since I create Contract A before Contract B, I cannot know the address of Contract B in Contract A;
  • I cannot make the function internal as the contracts are not derived;

Can you please offer me advice on how to fix this problem or explain another approach on this? I am new to Solidity. Thank you!



Solution 1:[1]

I cannot make a modifier to check the address.

You can, but the address needs to be in a variable, set after the contract B has been deployed.

pragma solidity ^0.8;

contract ContractA {
    address contractB;
    
    modifier onlyContractB {
        require(msg.sender == contractB);
        _;
    }

    function foo() external onlyContractB {
    }
    
    function setContractBAddress(address _contractB) external {
        contractB = _contractB;
    }
}
pragma solidity ^0.8;

interface IContractA {
    function foo() external;
}

contract ContractB {
    IContractA contractA;
    
    constructor(address _contractA) {
        contractA = IContractA(_contractA);
    }

    function callFoo() external {
        contractA.foo();
    }

}
  1. Deploy contract A
  2. Deploy contract B, passing it the "A" address in the constructor
  3. Set the contractB value in "Contract A".

I left out any auth mechanism while setting the contractB address in ContractA for simplicity. In this example, anyone can set the address, which you probably don't want, and you should add a mechanism allowing only authorized senders to set the contractB value in ContractA.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Petr Hejda