0

I have 2 Smart Contracts: A & B. B has a function onlyA() which I want that only A can call. Below is my approach:

  • Make B Ownable, then add the onlyOwner() modifier to onlyA().
  • Add the interface of B in A so that A can call the function onlyA() from say callMe().
  • Transfer ownership of B to A after deploying it.
  • Now, user can call callMe().

My usecase:

I'm building a Protocol Smart Contract (A) that has an NFT Contract (B) linked to it. I don't want anyone to directly mint an NFT from B, but only by calling a function mintNFT() in the Protocol Smart Contract (A) which in turn calls the function onlyA() in B which internally mints the NFT.

Protocol.mintNFT() -> NFT.onlyA() -> ERC721._mint()

So I was thinking of using the above approach I listed. But I have to add the interface of my NFT Smart Contract to my Protocol Contract which I don't want to do. It just seems to me like an anti-pattern. It is considered bad practice to add interfaces like this?

I would highly appreciate any suggestions for an approach different from the one listed above. Also, any suggestions on the overall re-design of my Protocol Smart Contracts are also welcome.

Update:

Since both contracts are part of the same project, I was also wondering about simply importing the NFT contract in the Protocol Contract rather than defining the NFT interface. Which one is a better way, gas-wise & Solidity best practices wise?

2 Answers 2

0

Make B Ownable, then add the onlyOwner() modifier to onlyA().

You can just create a new modifier that would restrict the function so only A can call it, and pass A's address inside of B's constructor, no need to use ownable. Like

contract B {
address addressA;

modifier onlyACanCall() {
    require(msg.sender == addressA);
}
constructor(address _A) {
    addressA = _A;
}
function onlyA() external onlyACanCall {
    // ... 
}
}

But I have to add the interface of my NFT Smart Contract to my Protocol Contract which I don't want to do

This is extremely common in smart contracts, why would you want to avoid it?

3
  • I can't pass address _A in B's constructor as I have to deploy B before A. Because I have to pass address B in A's constructor since its function callB() has to call B(address B).onlyA(). This will require address B to be passed in A's constructor. That's why I wanted to make B Ownable Oct 22, 2022 at 4:15
  • Since both contracts are part of the same project, I was also wondering about simply importing the NFT contract in the Protocol Contract rather than defining the NFT interface. Which one is a better way, gas wise & Solidity best practices wise? Oct 22, 2022 at 10:30
  • @DiamondDust, if you can set everything in a single contract, (size and business logic are not an issue) that would make it more efficient than having two contracts communicating with each other. (If you know how to program in solidity).
    – Sky
    Oct 22, 2022 at 10:45
0

Make B Ownable, then add the onlyOwner() modifier to onlyA().

You can just create a new modifier that would restrict the function so only A can call it, and pass A's address inside of B's constructor, no need to use ownable. Like

1
  • I can't pass address _A in B's constructor as I have to deploy B before A. Because I have to pass address B in A's constructor since its function callB() has to call B(address B).onlyA(). This will require address B to be passed in A's constructor. Oct 22, 2022 at 11:58

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.