kleros / court

The Kleros court user interface.
https://court.kleros.io
MIT License
21 stars 20 forks source link

Metaevidence dynamicScript with Web3.givenProvider #194

Open sneaker1 opened 3 years ago

sneaker1 commented 3 years ago

Hello,

i am using the metaevidence with a dynamicScript. It generally works and I think i know how to use it.

I need to load dynamic data from a contract. To connect to the blockchain I want to use metamask. I don't want to use a infura link. I use: const web3 = new Web3(Web3.givenProvider);

This does work in Firefox. In Chromium and Brave, unfortunately, Web3.givenProvider is null. And window.ethereum is undefined.

I have already tried different versions of metamask. Always the same.

Do you have any idea what could be the reason, why this is only working in Firefox?

Please take a look at it on case 919 on the Kovan testnet. https://court.kleros.io/cases/919 Watch the console output.

This is the dynamic script that is used.

const contractFile = require('../assets/contractFile.json');
const Web3 = require('web3');

const getMetaEvidence = async () => {

  console.log("dynamicScript is executing...");

  // Connect to the blockchain.
  if (typeof window.ethereum == 'undefined') {
    console.log("Metamask is NOT available");
    console.log("window.ethereum: " + window.ethereum);
    console.log("Web3.givenProvider: " + Web3.givenProvider);
    console.log("Web3.currentProvider: " + Web3.currentProvider);
  }
  else {
    console.log("Metamask is available");
    console.log("window.ethereum: " + window.ethereum);
    console.log("Web3.givenProvider: " + Web3.givenProvider);
    console.log("Web3.currentProvider: " + Web3.currentProvider);
  }

  const web3 = new Web3(Web3.givenProvider);

  // create the contract object to access the methods
  const contract = new web3.eth.Contract(contractFile.abi, scriptParameters.arbitrableContractAddress);

  // Get the transactionID of the dispute
  const txID = await contract.methods.disputeIDtoTXID(scriptParameters.disputeID).call();
  console.log("txID: " + txID);

  // Get the transaction with the transactionID
  const transaction = await contract.methods.txs(txID).call();

  resolveScript({
    // Return the description
    description: "Dear arbitratros, There is a dispute between traders on transaction " + txID + ". Please check trading protocol and the evidences to decide who has been honest and should receive the funds.",

    // Return the aliases. The metaevidence will be extended.
    aliases: {
      [transaction.offerer]: 'OFFERER (' + transaction.offerer + ')',
      [transaction.taker]: 'TAKER (' + transaction.taker + ')'
    }
  })

}

module.exports = getMetaEvidence

Regards, Sneaker

hbarcelos commented 3 years ago

The dynamic script should be standalone because it's sandboxed in an iframe for security reasons. In most environments it will fail reading parameters from the parent window.

IIRC Web3.givenProvider relies on the global environment (window) and so does window.ethereum (obviously). Modern browsers will restrict what you can do from within an iframe. While in the past things like window.parent.variableFromParentGlobalSope were allowed, this is no longer possible. When you try to access Web3.givenProvider inside an iframe, it's simply not there because it's on the parent window scope.

I can't know for sure, but I guess that the MetaMask extension on Firefox injects itself as the givenProvider for the main window and its children frames. Probably that is not possible in Chromium-based browsers. But this is just a hunch.

Lastly, we usually avoid depending on the user having MetaMask installed to simply see a dispute. Since it's just a matter of reading data, we recommend using a read-only RPC endpoint for this purpose.