ethers.js (node.js) llama a la función de solidez que se paga

Entiendo que puede enviar ethereum a un contrato inteligente, aunque cuando hace esto sendTransactionno parece que especifique una función en el contrato inteligente cuando hace esto. No entiendo muy bien cómo esto es útil. Sin embargo, lo que no puedo averiguar cómo hacer es enviar ethereum a una función que está configurada como pagadera. Estoy usando ethers.js y puedo crear un contrato y llamar a funciones que son visibles (solo lectura) sin problema, pero no puedo averiguar cómo enviar ethereum con la transacción a una función específica

export const testContract = async (address, abi) => {
  const wei = Utils.parseEther("0.1")
  const url = "http://localhost:8545"
  const provider = new Providers.JsonRpcProvider(url)
    // Load the wallet to deploy the contract with
  const privateKey =
    "0x123"
  const wallet = new Wallet(privateKey, provider)

  var contract = new Contract(address, abi, wallet)

  const price = await contract.retrievePrice()
  console.log("price " + price) //logs the price set in the constructor when the contract was made (WORKS)
  const testAddress = await contract.isUser(
    "0x456"
  )
  console.log("testAddress ", testAddress) //checks if the given address is a user on the contract (WORKS)

  const gasPrice = await provider.getGasPrice()
  console.log("gas price: ", gasPrice.toString()) //returns the price of gas from the network (WORKS)
  try {
    const addToUsers = await contract.requestAccess({ //call function to request access, from the current wallet (REVERTS)
      value: wei
    })
    console.log("result of sending transaction ", addToUsers)
  } catch (error) {
    console.log("error.... ", error) //fires as the contract reverted the payment
  }
}

¿ Alguna ayuda sobre por qué las llamadas contract.requestAccessvuelven a mí? No puedo entender cómo llamar a una función específica y enviar Ether. ¡Gracias!

Respuesta al comentario

Bien, entonces la función en el contrato de solidez se ve así:

  function requestAccess() payable {
    require(msg.value == price, "Incorrect sum sent to contract");
    _addUser(msg.sender);
  }

Comenté el requerimiento, para probar eso, pero aún se revierte. _addUser es de un contrato del que hereda la mina, y parece

  function _addUser(address account) internal {
    users.add(account);
    emit UserAdded(account);
  }

userses Roles.Role private users;y se sienta en el contrato padre

contract Users {
  using Roles for Roles.Role;

que importa de openzeppelin "openzeppelin-solidity/contracts/access/Roles.sol"

Dado que es el código EVM el que se está revirtiendo, significa que puede interactuar con el contrato y, por lo tanto, el problema se debe en parte al código del contrato. ¿Podría compartir con nosotros el código de la función requestAccess?
Hola, gracias por responder, he editado la pregunta para responder a la tuya.
Después de la prueba, agregué una función anónima al contrato e intenté enviar 0.1 ether desde metamask (la misma cuenta que usa el código) y funcionó bien. Así que tiene algo que ver con la sintaxis de mi éter...
¿Podría intentar comentar también los usuarios. agregar (cuenta) y mantener solo el evento de emisión? De esta forma sabremos con certeza que el problema no está relacionado con Solidity sino con ethers.js
cierto, su sugerencia implícita de que era el código de solidez me hizo seguir buscando. En realidad, no puedo estar seguro de qué lo arregló en este momento, pero la transacción se está realizando ahora. no sé por qué Probablemente fue como resultado de cambiar tanto la solidez como el código ether desde que publiqué la pregunta. ¡Si averiguo por qué no te dejaré colgado! GRACIAS

Respuestas (3)

Puede notar en los comentarios que no pude resolver lo que no funcionaba para mí, pero no soy un fanático de las respuestas "funciona, gracias" que no ayudan a otros. Así que he puesto un ejemplo de trabajo en esencia para cualquiera que esté buscando esto. Solo necesita hacer algunos cambios para ser específico a su situación, pero debería ser relativamente sencillo. https://gist.github.com/amlwwalker/89bc2c5a2b631527bb7def922b4c8306

Cita de https://github.com/ethers-io/ethers.js/issues/563

let overrides = {
    // To convert Ether to Wei:
    value: ethers.utils.parseEther("1.0")     // ether in this case MUST be a string

    // Or you can use Wei directly if you have that:
    // value: someBigNumber
    // value: 1234   // Note that using JavaScript numbers requires they are less than Number.MAX_SAFE_INTEGER
    // value: "1234567890"
    // value: "0x1234"

    // Or, promises are also supported:
    // value: provider.getBalance(addr)
};

// Pass in the overrides as the 3rd parameter to your 2-parameter function:
let tx = await exchangeContract.ethToTokenSwapOutput(tokens_bought, deadline, overrides);

No probé el código, pero cada vez que desee enviar ether junto con un método, debe "anularlo".

Const overrides = {
      value: ethers.utils.parseEther("1.0"), //sending one ether  
      gasLimit: 30000 //optional

}

//call your payable method using and use the override as a parameter
await contract.requestAccess( overrides )

En el objeto de anulaciones, puede insertar varias cosas, como gasLimit

overrides.from - el msg.sender (o CALLER) para usar durante la ejecución del código

overrides.value - el msg.value (o CALLVALUE) para usar durante la ejecución del código

overrides.gasPrice - el precio a pagar por gas (teóricamente); dado que no hay transacción, no se cobrará ninguna tarifa, pero el EVM aún requiere un valor para informar a tx.gasprice (o GASPRICE); la mayoría de los desarrolladores no requerirán esto

overrides.gasLimit - la cantidad de gas (teóricamente) para permitir que un nodo use durante la ejecución del código; dado que no hay transacción, no se cobrará ninguna tarifa, pero el EVM aún procesa la medición de gas para que las llamadas como gasleft (o GAS) informen valores significativos

overrides.blockTag: una etiqueta de bloque para simular la ejecución, que se puede usar para un análisis histórico hipotético; tenga en cuenta que muchos backends no admiten esto, o pueden requerir planes pagos para acceder, ya que los requisitos de almacenamiento y procesamiento de la base de datos del nodo son mucho más altos