I am new to Solidity and I'm having some trouble when calling a function of a smart contract from another one.
Basically I have smart contract A, which extends ERC20 and the Ownable contract from openzeppelin.
contract contractA is ERC20, Ownable {
constructor() ERC20("MyToken", "MTK") {
}
function mint(address account, uint256 amount) external onlyOwner {
_mint(account, amount);
}
}
Then I have smart contract B:
contract contractB is Ownable {
address contract_a;
constructor(address contract_address) {
contract_a = account;
}
function mint(address account, uint256 amount) public onlyOwner {
(bool success, ) = contract_a.call(
abi.encodeWithSignature("mint(address,uint256)", account, amount)
);
require(success, "call failed");
}
}
Both smart contracts are being deployed by the same user address, and I want that to be the owner of both smart contracts. I firstly deploy contractA, and then deploy contractB using the contractA's address.
When calling the mint
function in contractB, success
is always false, and I have no idea why this is failing. If I remove the onlyOwner
from the mint
function in contractA it starts working, so I believe it has something to do with this.
Does anyone know what's wrong here?
Thank you in advance.
Best Answer
You can think of the call from
contractB
tocontractA
as an additional "internal transaction", so it still has to adhere to the rules ofcontractA
. In other words, since yourmint
function can only be called by the owner, and the owner ofcontractA
is notcontractB
, the transaction fails.To remedy this, you could create your own modifier that checks if the caller (
msg.sender
) is either the owner orcontractB
.More specifically, the
onlyOwner
modifier checks thatmsg.sender
is the owner, andmsg.sender
is the address of the calling account, which in your case is the address ofcontractB
, not the address that signed the original transaction.