ethers.js (node.js) вызывает функцию солидности, которая подлежит оплате

Я понимаю, что вы можете отправить Эфириум на смарт-контракт, хотя, когда вы делаете это, sendTransactionкажется, что вы не указываете функцию на смарт-контракте, когда делаете это. Я не совсем понимаю, чем это полезно. Однако то, что я не могу понять, как это сделать, это отправить эфириум функции, которая установлена ​​как подлежащая оплате. Я использую ethers.js и могу создать контракт и вызывать функции, которые доступны для просмотра (только для чтения) без проблем, но я не могу понять, как отправить эфириум с транзакцией в конкретную функцию.

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
  }
}

Любая помощь относительно того, почему звонок contract.requestAccessвозвращается на меня? Я не могу понять, как вызвать конкретную функцию и отправить эфир. Спасибо!

Ответ на комментарий

Итак, функция в контракте Solidity выглядит так:

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

Я закомментировал требование, чтобы попробовать это, но все равно возвращается. _addUser из контракта, от которого наследуется мой, и выглядит так:

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

usersесть Roles.Role private users;и сидит в родительском контракте

contract Users {
  using Roles for Roles.Role;

который импортирует из openzeppelin "openzeppelin-solidity/contracts/access/Roles.sol"

Поскольку возвращается код EVM, это означает, что вы можете взаимодействовать с контрактом, и поэтому проблема частично связана с кодом контракта. Не могли бы вы поделиться с нами кодом функции requestAccess?
Привет, спасибо за ответ, я отредактировал вопрос, чтобы ответить на ваш!
После тестирования я добавил в контракт анонимную функцию и попытался отправить 0,1 эфира из метамаски (та же учетная запись, которую использует код), и это сработало нормально. Так что это как-то связано с синтаксисом моих эфиров.....
Не могли бы вы также закомментировать файл users.add(account) и оставить только событие emit? Так мы точно будем знать, что проблема связана не с Solidity, а с ethers.js.
правильно, ваше неявное предположение, что это был код прочности, заставило меня продолжить поиски. Я на самом деле не могу быть уверен, что исправило это прямо сейчас, но транзакция сейчас проходит. Я не знаю почему. Вероятно, это произошло в результате изменения как твердости, так и эфирного кода, так как я разместил вопрос. Если я выясню, почему я не оставлю тебя в покое! СПАСИБО

Ответы (3)

Вы можете заметить в комментариях, что я не смог понять, что у меня не работает, но я не фанат ответов «это работает, спасибо», которые не помогают другим. Итак, я привел рабочий пример для всех, кто ищет это. Просто нужно внести некоторые изменения, чтобы они соответствовали вашей ситуации, но должны быть относительно простыми. https://gist.github.com/amlwwalker/89bc2c5a2b631527bb7def922b4c8306

Цитата с 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);

Я не пробовал код, но каждый раз, когда вы хотите отправить эфир вместе с методом, вам нужно «переопределить» его.

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 )

В объект переопределения вы можете вставить несколько вещей, таких как gasLimit

overrides.from - msg.sender (или CALLER) для использования во время выполнения кода

overrides.value - msg.value (или CALLVALUE) для использования во время выполнения кода

overrides.gasPrice - цена за газ (теоретически); поскольку транзакции нет, комиссия не взимается, но EVM по-прежнему требует значения для сообщения в tx.gasprice (или GASPRICE); большинству разработчиков это не потребуется

overrides.gasLimit — количество газа (теоретически), позволяющее узлу использовать во время выполнения кода; поскольку транзакций нет, комиссия не взимается, но EVM по-прежнему обрабатывает показания газа, поэтому такие вызовы, как gasleft (или GAS), сообщают значимые значения.

overrides.blockTag — тег блока для имитации исполнения, который можно использовать для гипотетического исторического анализа; обратите внимание, что многие серверные части не поддерживают это или могут потребовать платные планы для доступа, поскольку требования к хранилищу и обработке базы данных узла намного выше.