Search code examples
design-patternsblockchainsoliditysmartcontractshardhat

Role Object Pattern implementation in Solidity


I am implementing Role Object Pattern in solidity. My implementation looks like this.

interface IEmployee{
    function getName() external  view returns (string memory);
    function getAge() external  view returns (uint256);
    function addRole(address account, EmployeeRole abc) external;

  }

contract EmployeeCore is IEmployee {
    string name;
    uint age;
    mapping(address => EmployeeRole)  role;

    constructor  (string memory name1,uint age1) {
     name = name1;
     age = age1;
    }


    function getName() public  virtual override view returns (string memory){
        return name;

    }
    function getAge() public  virtual override view returns (uint256){
        return age;
    }

    function addRole(address account, EmployeeRole er) public virtual override {
        role[account] = er;
    }

}

abstract contract EmployeeRole is IEmployee{

    EmployeeCore core;
    function getName()  override public view  returns (string memory){
    return core.getName();
    }

    function getAge() override public view  returns (uint256){
    return core.getAge();
    }


    function addRole(address account, EmployeeRole er) public override{
        core.addRole(account,er);
   }
}

contract Manager is EmployeeRole{
    function manageInventory() pure  public returns (string memory){
        
        string memory job = "Manage Inventory";
        return job;
    }

    
}

contract Supplier is EmployeeRole{
    function manageSupplies() public pure  returns (string memory){
        string memory job = "Manage Supplies";
        return job;
    }

    
}

Now in another contract I instantiate my classes and assign roles like this:

    IEmployee emp1 = new EmployeeCore("Samuel", 21);
     Manager m1= new Manager();
     emp1.addRole(address("0XJJJJJ"),m1);

     m1.getAge();
     m1.getName();

I am getting the following error on the last 2 i.e m1.getName(), m1.getAge() :

Error: cannot estimate gas; transaction may fail or may require manual gas limit (reason="execution reverted", method="estimateGas"

AND

error: ProviderError: execution reverted

I think my execution of transaction on the last two function calls is getting rejected as somehow I am not correctly accessing these functions. Does anyone know what am I doing wrong here?


Solution

  • Probably, it is about the wrong address of a contract with non-payable function. For instance, the following code snippet is working:

        //SPDX-License-Identifier: MIT
    pragma solidity >=0.8.7;
    import "hardhat/console.sol";
    
    interface IEmployee{
        function getName() external payable returns (string memory);
        function getAge() external  payable returns (uint256);
        function addRole(address account, EmployeeRole abc) external;
    
      }
    
    contract EmployeeCore is IEmployee {
        string name;
        uint age;
        mapping(address => EmployeeRole)  role;
    
        constructor  (string memory name1,uint age1) {
         name = name1;
         age = age1;
        }
    
        function getConractAddressEmployeeCore() public view returns(address){
            return address(this);
        }
    
    
        function getName() public  virtual override payable returns (string memory){
            return name;
    
        }
        function getAge() public  virtual override payable returns (uint256){
            return age;
        }
    
        function addRole(address account, EmployeeRole er) public virtual override {
            role[account] = er;
            console.log("account of the EmployeeCore role", account);
    
        }
    
    }
    
    abstract contract EmployeeRole is IEmployee{
    
        EmployeeCore core;
        function getName()  override public payable  returns (string memory){
        return core.getName();
        }
    
        function getAge() override public payable  returns (uint256){
        return core.getAge();
        }
    
    
        function addRole(address account, EmployeeRole er) public override{
            core.addRole(account,er);
            console.log("account of the EmployeeRole role", account);
        }
    
        function getContractAddressEmployeeRole() public view returns(address) {
            return address(this);
        }
    }
    
    contract Manager is EmployeeRole{
        function manageInventory() pure  public returns (string memory){
            
            string memory job = "Manage Inventory";
            return job;
        }
    
        function getContractAddressManager() public view returns(address) {
            return address(this);
        }
    
    
        
    }
    
    contract Supplier is EmployeeRole{
        function manageSupplies() public pure  returns (string memory){
            string memory job = "Manage Supplies";
            return job;
        }
    
        
    }
    
    contract Test {
        function testFunction() public {
        IEmployee emp1 = new EmployeeCore("Samuel", 21);
        Manager m1= new Manager();
        console.log("manage inventory logging", m1.manageInventory());
        emp1.addRole(m1.getContractAddressManager(), m1);
        m1.getAge();
        //m1.getName();
        }
    }
    

    You can deploy the Test contract and call the testFunction() method.