smartcontractkit / full-blockchain-solidity-course-py

Ultimate Solidity, Blockchain, and Smart Contract - Beginner to Expert Full Course | Python Edition
MIT License
10.75k stars 2.9k forks source link

[STUCK] LESSON 6: How can I fix - TypeError: unhashable type: 'list' #1429

Open DorianDaSilva opened 2 years ago

DorianDaSilva commented 2 years ago

Hi, I have been following along the course and managed to fix my previous issues but now I run into this error TypeError: unhashable type: 'list' when running brownie run scripts/deploy.py --network ganache-local

This error happened after we start cleaning the code using LOCAL_BLOCKCHAIN_ENVIRONMENT and Ganache UI. I have been searching online for the past 2 days for a fix but so far no luck.

Not sure what list is causing the issue, below is what the powershell returns when running the cmd line

File "C:\Users\doria\AppData\Roaming\Python\Python310\site-packages\brownie\project\scripts.py", line 149, in _import_from_path _import_cache[import_str] = importlib.import_module(import_str) File "C:\Program, line line, in in return _bootstrap._gcd_import(name[level:], package, level) File "<frozen, line line, in in File "<frozen, line line, in in File "<frozen, line line, in in File "<frozen, line line, in in File "<frozen, line line, in in File "<frozen, line line, in in File ".\scripts\deploy.py", line 2, in from scripts.helpful_scripts import ( File ".\scripts\helpful_scripts.py", line 8, in network.connect(LOCAL_BLOCKCHAIN_ENVIRONMENTS) File "C:\Users\doria\AppData\Roaming\Python\Python310\site-packages\brownie\network\main.py", line 31, in connect active = CONFIG.set_active_network(network) File "C:\Users\doria\AppData\Roaming\Python\Python310\site-packages\brownie_config.py", line 76, in set_activenetwork network = self.networks[id].copy() TypeError: unhashable type: 'list'

Below are my codes for deploy.py, helpful_scripts.py, brownie-config and .env

DEPLOY.PY

from brownie import FundMe, MockV3Aggregator, network, config
from scripts.helpful_scripts import (
    get_account,
    deploy_mocks,
    LOCAL_BLOCKCHAIN_ENVIRONMENTS,
)
from web3 import Web3

def deploy_fund_me():
    account = get_account()
    # if network.show_active() != "development":
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        price_feed_address = config["networks"][network.show_active()][
            "eth_usd_price_feed"
        ]
    else:
        deploy_mocks()
        price_feed_address = MockV3Aggregator[-1].address

    fund_me = FundMe.deploy(
        price_feed_address,
        {"from": account},
        publish_source=config["networks"][network.show_active()].get("verify"),
    )
    print(f"contract deployed to {fund_me.address}")

def main():
    deploy_fund_me()

HELPFUL_SCRIPTS.PY

from brownie import network, config, accounts, MockV3Aggregator
from web3 import Web3

LOCAL_BLOCKCHAIN_ENVIRONMENTS = ["development", "ganache-local"]
DECIMALS = 18
STARTING_PRICE = 2000

network.connect(LOCAL_BLOCKCHAIN_ENVIRONMENTS)

def get_account():
    #if network.show_active() == "development":
    if network.show_active() in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        return accounts[0]
    else:
        return accounts.add(config["wallets"]["from_key"])

def deploy_mocks():
    print(f"The active network is {network.show_active}")
    print("Deploying Mocks...")
    if len(MockV3Aggregator) <= 0:
        MockV3Aggregator.deploy(
            DECIMALS, Web3.toWei(STARTING_PRICE, "ether"), {"from": get_account}
        )
    print("Mocks Deployed!")

BROWNIE-CONFIG

dependencies:
  - smartcontractkit/chainlink-brownie-contracts@1.1.1

compiler:
  solc:
  remapping:
    - '@chainlink=smartcontractkit/chainlink-brownie-contracts@1.1.1'

dotenv: .env
networks:
  rinkeby:
    eth_usd_price_feed: "0x8A753747A1Fa494EC906cE90E9f37563A8AF630e"
    verify: True
  development:
    verify: False
  ganache-local:
    verify: false

wallets:
  from_key: ${PRIVATE_KEY}

.ENV FILE

    export PRIVATE_KEY=0xc893d45fe037d48b5f685e8e930fa9ef9449414df10465920efdef96c9a13081
    export WEB3_INFURA_PROJECT_ID=6147124a429040fd8eb1bdbf71f5f55e
    export ETHERSCAN_TOKEN=1AMEVWWGCF4X411K7MR43J6KJSASFN52GA

AND MOCKV3AGGREGATOR IN CASE IT IS NEEDED (Full code since import isn't working)

// SPDX-License-Identifier: MIT
//pragma solidity ^0.6.0;
pragma solidity >=0.6.6 <0.9.0;

//import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV2V3Interface.sol";
interface AggregatorInterface {
    function latestAnswer() external view returns (int256);

    function latestTimestamp() external view returns (uint256);

    function latestRound() external view returns (uint256);

    function getAnswer(uint256 roundId) external view returns (int256);

    function getTimestamp(uint256 roundId) external view returns (uint256);

    event AnswerUpdated(
        int256 indexed current,
        uint256 indexed roundId,
        uint256 updatedAt
    );

    event NewRound(
        uint256 indexed roundId,
        address indexed startedBy,
        uint256 startedAt
    );
}

interface AggregatorV3Interface {
    function decimals() external view returns (uint8);

    function description() external view returns (string memory);

    function version() external view returns (uint256);

    // getRoundData and latestRoundData should both raise "No data present"
    // if they do not have data to report, instead of returning unset values
    // which could be misinterpreted as actual reported values.
    function getRoundData(uint80 _roundId)
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );

    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
}

interface AggregatorV2V3Interface is
    AggregatorInterface,
    AggregatorV3Interface
{}

/**
* @title MockV3Aggregator
* @notice Based on the FluxAggregator contract
* @notice Use this contract when you need to test
* other contract's ability to read data from an
* aggregator contract, but how the aggregator got
* its answer is unimportant
*/
contract MockV3Aggregator is AggregatorV2V3Interface {
    uint256 public constant override version = 0;

    uint8 public override decimals;
    int256 public override latestAnswer;
    uint256 public override latestTimestamp;
    uint256 public override latestRound;

    mapping(uint256 => int256) public override getAnswer;
    mapping(uint256 => uint256) public override getTimestamp;
    mapping(uint256 => uint256) private getStartedAt;

    constructor(uint8 _decimals, int256 _initialAnswer) public {
        decimals = _decimals;
        updateAnswer(_initialAnswer);
    }

    function updateAnswer(int256 _answer) public {
        latestAnswer = _answer;
        latestTimestamp = block.timestamp;
        latestRound++;
        getAnswer[latestRound] = _answer;
        getTimestamp[latestRound] = block.timestamp;
        getStartedAt[latestRound] = block.timestamp;
    }

    function updateRoundData(
        uint80 _roundId,
        int256 _answer,
        uint256 _timestamp,
        uint256 _startedAt
    ) public {
        latestRound = _roundId;
        latestAnswer = _answer;
        latestTimestamp = _timestamp;
        getAnswer[latestRound] = _answer;
        getTimestamp[latestRound] = _timestamp;
        getStartedAt[latestRound] = _startedAt;
    }

    function getRoundData(uint80 _roundId)
        external
        view
        override
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        )
    {
        return (
            _roundId,
            getAnswer[_roundId],
            getStartedAt[_roundId],
            getTimestamp[_roundId],
            _roundId
        );
    }

    function latestRoundData()
        external
        view
        override
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        )
    {
        return (
            uint80(latestRound),
            getAnswer[latestRound],
            getStartedAt[latestRound],
            getTimestamp[latestRound],
            uint80(latestRound)
        );
    }

    function description() external view override returns (string memory) {
        return "v0.6/tests/MockV3Aggregator.sol";
    }
}

// MockOracle
// Function signatures, event signatures, log topics
DorianDaSilva commented 2 years ago

I deleted Ganache-Local from the variables and networks to run the same code using LOCAL_BLOCKCHAIN_ENVIRONMENTS including only "development" but now I run into a different error.

ConnectionError: Already connected to network 'development'

Can't seem to get around this one, looks lik I won't be able to work with ganache ui or finish the lesson.

tolivern commented 2 years ago

Hi! I am taking the same course as you; I have no idea what is going on, but mi helpful.scripts.py is like yours, except that I don´t have the line:

network.connect(LOCAL_BLOCKCHAIN_ENVIRONMENTS)

And it works. Can you try to comment that line and see what happens? (at least maybe the error is different...)