Web3 interaction with ERC720Upgradeaple, AccessControlUpgradeable revert due to missing role

I have the following ERC720Upgradeable, AccessControlUpgradeable contract:

contract Account is ERC721PausableUpgradeable, AccessControlUpgradeable {
    bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
    .
    .
    .
}

There is a role ‘OPERATOR_ROLE’ which is required for any contract updates (writes).

When I try to interact with the contract using web3 and my account with OPERATOR_ROLE I get

ERROR	Error: execution reverted: Not an operator
0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000f4e6f7420616e206f70657261746f720000000000000000000000000000000000

When I use the same address, connect with etherscan and call the same write function, all works fine.

Here are the two inits I’ve tried to interact with the contract:

async function init(network) {
    const mnemonic = "my mnemonics with twelve words six seven eight nine ten eleven twelve"
    hdprovider = new this.HDWalletProvider(mnemonic, https://mainnet.infura.io/v3/+INFURA_KEY, 0, 1);
    console.log('hdprovider');
    console.log(this.hdprovider);
    web3 = new Web3(hdprovider);
    PROXYADMIN = new web3.eth.Contract(JSON.parse(PROXYADMIN_JSON.Body.toString()).abi, PROXYADMIN_ADDRESS);
    ACCOUNTIMPLADDRESS = await PROXYADMIN.methods.getProxyImplementation(ACCOUNT_PROXY_ADDRESS).call();
    ACCOUNT = new web3.eth.Contract(JSON.parse(ACCOUNT_JSON.Body.toString()).abi, ACCOUNTIMPLADDRESS);
    console.log("Account");
    console.log(ACCOUNT)
}

async function init(network) {
    const mnemonic = "my mnemonics with twelve words six seven eight nine ten eleven twelve"
    hdprovider = new this.HDWalletProvider(mnemonic, https://mainnet.infura.io/v3/+INFURA_KEY, 0, 1);
    console.log('hdprovider');
    console.log(this.hdprovider);
    web3 = new Web3(hdprovider);
    ACCOUNT = new web3.eth.Contract(JSON.parse(ACCOUNT_JSON.Body.toString()).abi, ACCOUNT_PROX_ADDRESS);
    console.log("Account");
    console.log(ACCOUNT)
}

Here is the method with the write method changeStatus():

async function changeStatus(account, newStatus) {
    var oldStatus;
    try {
        oldStatus = await ACCOUNT.methods.status(accountId).call();
        await ACCOUNT.methods.changeClientStatus(accountId, newClientStatus).call();
        console.log("Status of account " + account + " changed from status " + oldStatus + " to status " + newtStatus);
        return true;
    } catch(err) {
        console.error("changeStatus() for account " + account + " from current status " + oldStatus + " to new status " + newStatus + " failed");
        console.error(err);
        return false;
    }
}

Here the same, more compact:

const Web3 = require('web3');
const fs = require('fs');
const HDWalletProvider = require('@truffle/hdwallet-provider');
const INFURA_API_RINKEBY = 'https://rinkeby.infura.io/v3/<myinfurakey>';
const ACCOUNT_ADDRESS_RINKEBY = '<Address of Account Proxy Address>'; 
const mnemonic = 'my mnemonics with twelve words six seven eight nine ten eleven twelve';
var hdprovider;
var web3;
var account;

async function main() {
    await init();
    console.log("Status 1234: ");
    console.log(await fiat24account.methods.status(1234).call());
    await account.methods.changeClientStatus(1234,1).call();
    console.log("New Status 1234: ");
    console.log(await account.methods.status(1234).call());
    hdprovider.engine.stop();
} 
async function init() {
    hdprovider = new HDWalletProvider(mnemonic, INFURA_API_RINKEBY);
    console.log('hdprovider');
    console.log(hdprovider);
    web3 = new Web3(hdprovider);
    const account_json = JSON.parse(fs.readFileSync('Account.json'));
    account = new web3.eth.Contract(account_json.abi, ACCOUNT_ADDRESS_RINKEBY);
}

main();

I do the same with the same mnemonics in the truffle console and it works fine.

And it works in that way as well:

async function changeClientStatus(accountId, clientStatus) {
    var method = account.methods.changeClientStatus(accountId, clientStatus).encodeABI();

    const tx = {
      from: hdprovider.addresses[0],
      to: account.options.address,
      gas: 5500000,
      data: method
    };
    var signedTx = await web3.eth.accounts.signTransaction(tx, '0x' + hdprovider.wallets[hdprovider.addresses[0]].privateKey.toString('hex'));
    try {
        var receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
        console.log(receipt);
        console.log("Changed the client status of account  " + accountId + " to client status " + clientStatus);
    } catch(err) {
        console.log(err.message);
    }
}

I assume, the wrong address is used for the call account.methods.changeClientStatus().

How do I properly interact with ERC720Upgradeaple, AccessControlUpgradeable using web3?

Thanks for your support.

For contract changes should have used

send({from: hdprovider.addresses[0]})

instead of

.call()

Did this fix your issue?

Yes, this issue is solved by calling .send() instead of .call().