0

I am trying to create a simple role based access control system for the contracts I have created. I have two smart contracts, one named Users that stores all of the users details as well as the type of account created. The other smart contract is the logic main logic and functions a user can access. I have created a function in the Users contract to check if a user is of a specific user type, e.g. manufacturer. I have also created a modifier in the Users contract to require that this function is called to check if the user is a manufacturer and in turn the main function in the SupplyChain contract uses the correct modifier in the users contract to check the user type before accessing the logic of the function.

SupplyChain.sol

pragma solidity ^0.5.16;
import './Users.sol';

contract SupplyChain is Users{

mapping (uint => Item) items;

 struct Item {
    uint    sku;  // Stock Keeping Unit (SKU)
    uint    upc; // Universal Product Code (UPC), generated by the Farmer, goes on the package, can be verified by the Consumer
    address ownerID;
}
function pfunc(uint _upc, address _owner) public onlyManufacturer(msg.sender) view returns(address){
    return _owner;
  }

Users.sol

pragma solidity ^0.5.16;
contract Users {

    enum UserType{
        Producer,
        Manufacturer,
        Supplier,
        Retailer,
        Consumer
    }

    modifier onlyManufacturer(address _owner){
        require (isManufacturer(_owner), "Only Manufacturer's are allowed to access this function");
        _;
    }

function isManufacturer(address _userAddress) public view returns(bool){
        UserType temp = UserType.Manufacturer;
        if(users[_userAddress].userType == temp){
            return true;
        }else{
            return false;
        }
    }

When I call the 'isManufacturer' function straight from app.js to check the current users account type it returns that the user is a manufacturer however, when I try to call 'pfunc' with the same address it returns the following error:

MetaMask - RPC Error: [object Object] 
{…}
​
code: -32603
​
data: Object { message: "VM Exception while processing transaction: revert Only Manufacturer's are allowed to access this function", code: -32000, data: {…} }
​
message: "[object Object]"
​
stack: "i@moz-extension://2dd2e06e-9e5f-4fa5-819d-629e5b9dc759/background.js:1:1186307\na@moz-extension://2dd2e06e-9e5f-4fa5-819d-629e5b9dc759/background.js:1:1188007\ninternal@moz-extension://2dd2e06e-9e5f-4fa5-819d-629e5b9dc759/background.js:1:1188294\nf@moz-extension://2dd2e06e-9e5f-4fa5-819d-629e5b9dc759/background.js:1:1209307\n[512]</</t.exports/<@moz-extension://2dd2e06e-9e5f-4fa5-819d-629e5b9dc759/background.js:1:1208519\n"

This is how I am calling the function through web3:

App.contracts.SupplyChain.deployed().then(function(instance){
      instance.pfunc(1,App.metamaskAccountID).then(function(error, result){
        if(!error){
          console.log(result);
        }else{
          console.log(error);
        }
      })
    });

I don't know why I keep getting this error, pressumably the user address is not being recognised when passed from one smart contract to another, can anyone help me out?

  • That's related to an open issue about calling read-only (view) functions which revert with a message. The issue happens to be in both web3.js and geth (i.e., it needs to be fixed independently in both, and you need to upgrade both versions in your system). Remove the revert-message from the modifier, and you'll see identical behavior in both cases. – goodvibration May 21 at 12:13
  • Note that this issue is viable only when you call such function from the off-chain (e.g., a web3.js script, an app, Remix, MyEtherWallet, etc). It is not viable when you call it from the on-chain (i.e., from another function in this contract or in another contract). – goodvibration May 21 at 12:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.