lukso-network / lsp-smart-contracts

The reference implementation for universal profiles smart contracts
https://www.npmjs.com/package/@lukso/lsp-smart-contracts
Apache License 2.0
76 stars 50 forks source link

[LSP6 - Key Manager] Contract Interaction with Metamask Results in "Custom Error" #336

Closed jasperanders closed 11 months ago

jasperanders commented 2 years ago

Current Behavior

I am trying to restrict SET_DATA permissions to a specific address. This works fine when using a wallet address added to web3js with: const {address} = web3.eth.accounts.wallet.add(PRIVATE_KEY);, when I try the same thing using the Metamask provider (const accounts = await window.ethereum.request({method: "eth_requestAccounts"});), the transaction fails with an Error: Error encountered during contract execution [execution reverted] See on testnet.

Background

Below, you find the Code that I used to restrict the access:

export async function restrictAddressSetDataTo(
  profileAddress: ContractAddress,
  beneficiaryAddress: WalletAddress
){
  const accounts = await window.ethereum.request({
        method: "eth_requestAccounts",
      });
  const allowedEOA = accounts[0] 

  const encodedData = ERC725.encodeData(
    [
      {
        keyName: "AddressPermissions:AllowedERC725YKeys:<address>",
        dynamicKeyParts: beneficiaryAddress,
        value: [
          web3.eth.abi.encodeParameter(
            "bytes32",
            web3.utils.keccak256(STUDENT_STATUS)
          ),
        ],
      },
    ],
    [
      {
        name: "AddressPermissions:AllowedERC725YKeys:<address>",
        key: "0x4b80742de2bf90b8b4850000<address>",
        keyType: "MappingWithGrouping",
        valueType: "bytes32[]",
        valueContent: "Bytes32",
      },
    ]
  );

  const { keyManagerContract, universalProfileContract } = await getContracts(
    profileAddress
  ); // helper function that returns the contracts, for reference, see below.

  // encode the setData payload
  const abiPayload = await universalProfileContract.methods[
    "setData(bytes32,bytes)"
  ](encodedData.keys[0], encodedData.values[0]).encodeABI();

  //----- This fails with the above Error ------
  const result = await keyManagerContract.methods.execute(abiPayload).send({
    from: allowedEOA,
    gasLimit: 300_000,
  }); 
  return result;
}

// for reference
async function getContracts(profileAddress: string): Promise<{
  universalProfileContract;
  keyManagerContract;
  keyManagerAddress;
}> {
  const universalProfileContract = new web3.eth.Contract(
    UniversalProfile.abi as AbiItem[],
    profileAddress
  );

  const keyManagerAddress = await universalProfileContract.methods
    .owner()
    .call();
  const keyManagerContract = new web3.eth.Contract(
    KeyManager.abi as AbiItem[],
    keyManagerAddress
  );
  return { universalProfileContract, keyManagerContract, keyManagerAddress };
}

Expected Behavior

It is expected, that it should also work using Metamask and a more descriptive error would be very helpful.

Thanks for the help Cheers

CJ42 commented 1 year ago

@dzbo @Esanim any ideas about the issue?

dzbo commented 1 year ago

From quick look I noticed this miss additional execute wrapping before passing to KM contract.

Can you try with something like this:

const { keyManagerContract, universalProfileContract } = await getContracts(
    profileAddress
  ); // helper function that returns the contracts, for reference, see below.

+const executeAbiPayload  = universalProfileContract.methods
+      .execute(
+       0, // operation type, CALL = 0, CREATE = 1
+        beneficiaryAddress,
+       '0x0',
+        abiPayload
+      )
+      .encodeABI()

- const result = await keyManagerContract.methods.execute(abiPayload).send({      
+ const result = await keyManagerContract.methods.execute(executeAbiPayload).send({
    from: allowedEOA,
    gasLimit: 300_000,
  }); 
  return result;
CJ42 commented 11 months ago

Closing as stale and no activity. @jasperanders feel free to re-open if you are still experiencing the issue