Have a contract access internal methods of 2 tokens

The intent of my contract is to have a contract that handles various game logic and calls internal methods of 2 other token contracts, Weapons and Characters. They are both ERC721 and have various properties associated with them. I have a pared down example of what I’m trying to do below:

import "./4_Weapons.sol";
import "./5_Weapons.sol";

contract Game is Weapons, Characters{

    uint256 number;
    Weapons weapons;
    Characters characters;

    constructor() {
        weapons = new Weapons();
        characters = new Characters();
    }
    
    function battle() public {
        //Modifies Characters
        //Modifies Weapons
    }
   
}

.
contract Weapons is ERC721{

    uint256 number;

    /**
     * @dev Store value in variable
     * @param num value to store
     */
    function store(uint256 num) internal {
        number = num;
    }

    /**
     * @dev Return value 
     * @return value of 'number'
     */
    function retrieve() internal view returns (uint256){
        return number;
    }
}

.

contract Characters is ERC721{

    uint256 number;

    /**
     * @dev Store value in variable
     * @param num value to store
     */
    function store(uint256 num) internal {
        number = num;
    }

    /**
     * @dev Return value 
     * @return value of 'number'
     */
    function retrieve() internal view returns (uint256){
        return number;
    }
}

The idea is that we would be able to call internal functions above, however we obviously cannot inherit 2 different ERC721. I’m wondering if there is a pattern or best practice we could do to securely have Game call these and not have them public?

1 Like

If the contract can not inherit the ERC721 contract, then I think the functions you want to call has got to be public or external, if you expect that only your contract can call it rather than someone else, you can add a role for this function, such as

function ERC721_Function() public {
    require(hasRole(CALL_ROLE, msg.sender), "must have call role to call");
}

For more details, you can have a look at this contract:
openzeppelin-contracts/AccessControl.sol

1 Like

This looks like a duplicate of: Limiting access to a sub-contract to the address that initialized it.

Though @skyge’s answer has a nice example (which I didn’t have :smile:).