Тестирование платной функции в Solidity

#solidity #truffle

#солидность #truffle

Вопрос:

Итак, я пытаюсь протестировать платную функцию в следующем смарт-контракте, используя truffle framework:

 contract FundMe {
    using SafeMathChainlink for uint256;

    mapping(address => uint256) public addressToAmountFunded;
    address[] public funders;
    address public owner;
    AggregatorV3Interface public priceFeed;

    constructor(address _priceFeed) public {
        priceFeed = AggregatorV3Interface(_priceFeed);
        owner = msg.sender;
    }

    function fund() public payable {
        uint256 mimimumUSD = 50 * 10**18;
        require(
            getConversionRate(msg.value) >= mimimumUSD,
            "You need to spend more ETH!"
        );
        addressToAmountFunded[msg.sender]  = msg.value;
        funders.push(msg.sender);
    }
 

Я специально хочу протестировать функцию оплаты, и я видел несколько вещей в Интернете, где люди создают другие контракты с начальными балансами, а затем отправляют свой контракт на тестирование в eth. Но я просто хотел бы захватить локальный кошелек ganache и отправить немного eth в контракт, а затем проверить это, если бы кто-нибудь мог показать мне какой-нибудь тестовый код javascript, чтобы я мог понять это, это было бы очень ценно!

Ответ №1:

Чтобы контракт мог получать ETH (или любой собственный токен — BNB в Binance Smart Chain, TRX в сети Tron, …) без вызова какой-либо функции, вам необходимо определить хотя бы одну из этих функций receive() (docs) или fallback() (docs).

 contract FundMe {

    // intentionally missing the `function` keyword
    receive() external payable {
        // can be empty
    }

    // ... rest of your code
}
 

Затем вы можете отправить обычную транзакцию на адрес контракта в truffle (docs):

 const instance = await MyContract.at(contractAddress);
await instance.send(web3.toWei(1, "ether"));
 

Обратите внимание, что, поскольку receive() и fallback() не являются обычными функциями, вы не можете вызывать их с помощью автоматически созданных методов truffle: myContract.functionName()


Если вы хотите выполнить платную функцию, отправив ей ETH, вы можете использовать transaction params (docs) . Это всегда последний аргумент после всех обычных аргументов функции.

 const instance = await MyContract.at(contractAddress);
await instance.fund({
    value: web3.toWei(1, "ether")
});
 

Примечание: если fund() бы функция имела 1 аргумент (скажем, a bool ), transaction params он был бы 2-м:

 await instance.fund(true, {
    value: web3.toWei(1, "ether")
});
 

Комментарии:

1. Итак, если бы я хотел сделать что-то вроде обновления данной переменной или переадресации ее в другую функцию, это произошло бы в рамках этой функции приема?

2. @SonnyVesali Я также обновил свой ответ в этом случае. Сначала я понял ваш вопрос только как отправку ETH в контракт без выполнения какой-либо функции.

3. Это единственный способ заплатить ETH контракту сейчас? Ранее payable она могла быть отмечена для любой функции, но я получал необъяснимую ошибку возврата с последней версией Solidity до изменения моей payable функции на receive() external payable .

4. @Neo Вы можете использовать payable модификатор для любой функции. Полученный вами возврат, похоже, не связан с функцией payable .