brownie:ValueError: execution reverted: VM Exception while processing transaction: revert
Macbook Pro : Monterey
Intel Core i7
Brownie v1.17.2
I am learning solidity according to reference(https://www.youtube.com/watch?v=M576WGiDBdQ&t=25510s).
What I tried to do here, is use brownie to deploy a contract(FundMe) in a script (deploy.py),then write a test script(scripts/fund_and_withdraw.py.py)
I met the same error,the MockV3Aggregator deployed successfully, but the getEntrancePrice is 0 Googled it find this answer,don't quite follow.(https://ethereum.stackexchange.com/questions/114889/deploying-ganache-local-w-brownie-vm-exception-while-processing-transaction-in)
getPrice() isn't returning a number you want from the mock, somewhere in the vicinity of 2B. Think this is a bug with the Ganache implementation- performing the calculation (minimumUSD * precision) / price in getEntranceFee() gives you a number less than 1- and, since Solidity can't handle floats, Solidity simply sees it as a 0, and the whole thing errors out.
scripts/fund_and_withdraw.py
from brownie import FundMe
from scripts.helpful_scripts import get_account
def fund():
fund_me = FundMe[-1]
account = get_account()
entrance_fee = fund_me.getEntranceFee()
print(f"The entrance fee is : {entrance_fee} !")
print("funding")
fund_me.fund({"from": account, "value": entrance_fee})
print(f"Funded {entrance_fee} !")
def withdraw():
fund_me = FundMe[-1]
account = get_account()
fund_me.withdraw({"from": account})
def main():
fund()
withdraw()
deploy.py
from brownie import FundMe, network, config, MockV3Aggregator
from scripts.helpful_scripts import (
get_account,
deploy_mocks,
LOCAL_BLOCKCHAIN_ENVIRONMENT,
)
def deploy_fund_me():
account = get_account()
# if we have a persistent network like rinkeby,use the associated address
# otherwise ,deploy mocks
if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENT:
price_feed_address = config["networks"][network.show_active()][
"eth_usd_price_feed"
]
else:
deploy_mocks()
# just use the latest mockV3Aggregator
price_feed_address = MockV3Aggregator[-1].address
print("***********************************************************")
print(f"MockVeAggrator's address is {price_feed_address}")
fund_me = FundMe.deploy(
price_feed_address,
{"from": account},
publish_source=config["networks"][network.show_active()].get("verify"),
)
print("***********************************************************")
print(f"The Ether price is :{fund_me.getPrice()}\n")
print(f"Contract deployed to {fund_me.address}\n")
entrance_fee = fund_me.getEntranceFee()
print("***********************************************************")
print(f"The entrance fee is : {entrance_fee} !\n")
return fund_me
def main():
deploy_fund_me()
FundMe.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;
// we need tell brownie @chainlink means == what input in config,need to tell compiler
import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
import "@chainlink/contracts/src/v0.6/vendor/SafeMathChainlink.sol";
contract FundMe {
//using SafeMathChainlink for uint256;
mapping(address => uint256) public addressToAmountFunded;
address[] public funders;
address public owner;
AggregatorV3Interface public priceFeed;
// if you're following along with the freecodecamp video
// Please see https://github.com/PatrickAlphaC/fund_me
// to get the starting solidity contract code, it'll be slightly different than this!
constructor(address _priceFeed) {
// make price feed a parameter
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);
}
function getVersion() public view returns (uint256) {
return priceFeed.version();
}
function getPrice() public view returns (uint256) {
(, int256 answer, , , ) = priceFeed.latestRoundData();
return uint256(answer * 10000000000);
}
// 1000000000
function getConversionRate(uint256 ethAmount)
public
view
returns (uint256)
{
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
return ethAmountInUsd;
}
function getEntranceFee() public view returns (uint256) {
// mimimumUSD
uint256 mimimumUSD = 50 * 10**18;
uint256 price = getPrice();
uint256 precision = 1 * 10**18;
return (mimimumUSD * precision) / price;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function withdraw() public payable onlyOwner {
payable(msg.sender).transfer(address(this).balance);
for (
uint256 funderIndex = 0;
funderIndex < funders.length;
funderIndex++
) {
address funder = funders[funderIndex];
addressToAmountFunded[funder] = 0;
}
funders = new address[](0);
}
}
update the error disappear magicly (may be come back later),right now the error info is :list out of index actually i faced the same error in another project (Brownie test IndexError: list index out of range)
according the answer and brownie docs, I need to add account. what confused me is if I launched the ganache local blockchain already ,why I still need to add account or I added the wrong way?
Solution 1:
function getEntranceFee() public view returns (uint256) {
// mimimumUSD
uint256 mimimumUSD = 50 * 10**18;
uint256 price = getPrice();
uint256 precision = 1 * 10**18;
return (mimimumUSD * precision) / price;
}
You do not need to multiply with precison. currently, assuming eth price 3000, you are returning
(50 * (10^18) * (10^18)) / (3000 * 10^10)
(50 * (10^36)) / (3 * 10^13)
(50/3)*(10^23)
I think your return value should be
return mimimumUSD / price;