[Python] Solidity Contract Call Reverting with No Reason via Web3.py – How Can I Diagnose This?

Discussão em 'Python' iniciado por Stack, Março 17, 2025.

  1. Stack

    Stack Membro Participativo

    I’m developing a blockchain-based forensic evidence system using Solidity (deployed via Hardhat/Ganache), a Python Flask backend, and Web3.py. My smart contract is designed to store evidence details (including a file hash, filename, UNIX timestamp, investigator, and location). When I call the addEvidence function from my Flask app, the transaction reverts with no clear error reason.

    Error Message:

    Blockchain ContractLogicError: ('execution reverted: VM Exception while processing transaction: revert', {'hash': None, 'programCounter': 70, 'result': '0x', 'reason': None, 'message': 'revert'})


    Solidity Contract Code (EvidenceStorage.sol):

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.19;

    contract EvidenceStorage {
    struct Evidence {
    string fileHash;
    string fileName;
    uint timestamp; // UNIX timestamp
    string investigator;
    string location;
    }

    mapping(string => Evidence) private evidences;
    string[] private evidenceHashes;

    event EvidenceAdded(
    string fileHash,
    string fileName,
    uint timestamp,
    string investigator,
    string location
    );

    function addEvidence(
    string memory _fileHash,
    string memory _fileName,
    uint _timestamp,
    string memory _investigator,
    string memory _location
    ) public {
    // Revert if the evidence already exists.
    require(bytes(evidences[_fileHash].fileHash).length == 0, "Evidence already exists!");

    // Here we use block.timestamp rather than _timestamp
    uint currentTime = block.timestamp;

    Evidence memory newEvidence = Evidence({
    fileHash: _fileHash,
    fileName: _fileName,
    timestamp: currentTime,
    investigator: _investigator,
    location: _location
    });

    evidences[_fileHash] = newEvidence;
    evidenceHashes.push(_fileHash);

    emit EvidenceAdded(_fileHash, _fileName, currentTime, _investigator, _location);
    }

    function getEvidence(string memory _fileHash)
    public
    view
    returns (string memory, string memory, uint, string memory, string memory)
    {
    require(bytes(evidences[_fileHash].fileHash).length != 0, "Evidence not found!");
    Evidence memory e = evidences[_fileHash];
    return (e.fileHash, e.fileName, e.timestamp, e.investigator, e.location);
    }

    function getAllEvidenceHashes() public view returns (string[] memory) {
    return evidenceHashes;
    }
    }



    Python Code Snippet (from blockchain.py):


    from web3 import Web3
    import json
    import os
    from dotenv import load_dotenv

    load_dotenv()

    GANACHE_URL = os.getenv("GANACHE_RPC_URL")
    CONTRACT_ADDRESS = os.getenv("CONTRACT_ADDRESS")

    web3 = Web3(Web3.HTTPProvider(GANACHE_URL))
    assert web3.is_connected(), "Failed to connect to Ganache!"

    with open('hardhat_evidence/artifacts/contracts/EvidenceStorage.sol/EvidenceStorage.json') as f:
    contract_json = json.load(f)
    contract_abi = contract_json['abi']

    contract = web3.eth.contract(address=CONTRACT_ADDRESS, abi=contract_abi)
    account = web3.eth.accounts[0]

    def add_evidence(evidence_hash, filename, timestamp, investigator, location):
    txn = contract.functions.addEvidence(evidence_hash, filename, timestamp, investigator, location).transact({'from': account})
    web3.eth.wait_for_transaction_receipt(txn)


    Flask Code Snippet (from evidence_manager.py):

    from flask import Flask, render_template, request, redirect
    from app.blockchain import add_evidence, get_evidence, get_all_hashes
    from app.utils import calculate_hash, get_current_unix_timestamp, unix_to_readable
    import os

    app = Flask(__name__)

    TEMP_FOLDER = 'temp'
    if not os.path.exists(TEMP_FOLDER):
    os.makedirs(TEMP_FOLDER)

    @app.route('/', methods=['GET', 'POST'])
    def index():
    if request.method == 'POST':
    file = request.files['evidenceFile']
    investigator = request.form['investigator']
    location = request.form['location']

    if file:
    file_path = os.path.join(TEMP_FOLDER, file.filename)
    file.save(file_path)

    evidence_hash = calculate_hash(file_path)
    timestamp_unix = get_current_unix_timestamp()

    add_evidence(evidence_hash, file.filename, timestamp_unix, investigator, location)
    os.remove(file_path)
    return redirect('/view')

    return render_template('index.html')

    @app.route('/view')
    def view():
    hashes = get_all_hashes()
    evidence_list = []

    for h in hashes:
    evi = get_evidence(h)
    readable_time = unix_to_readable(evi[2])
    evidence_list.append({
    'hash': evi[0],
    'filename': evi[1],
    'timestamp': readable_time,
    'investigator': evi[3],
    'location': evi[4]
    })

    return render_template('view_evidence.html', evidence_list=evidence_list)

    if __name__ == '__main__':
    app.run(debug=True)



    My Environment: Ganache as the local Ethereum node. Hardhat for smart contract development. Python 3.10, Flask, and Web3.py for the backend.

    My Problem: When I try to add evidence (i.e., call addEvidence via my Flask app), the transaction reverts with:

    ContractLogicError: ('execution reverted: VM Exception while processing transaction: revert', {'hash': None, 'programCounter': 70, 'result': '0x', 'reason': None, 'message': 'revert'})



    The revert occurs even though: I’m sending the correct data types (all strings and a uint timestamp). My require in addEvidence should only revert if evidence with the same hash already exists.

    Questions: 1.How can I obtain a more detailed revert reason from the transaction? I see no reason (it’s None), so how can I debug or get more insight into what causes the revert?

    2.What are common pitfalls that might cause a revert in this context? For example, could it be due to an incorrect contract address, ABI issues, or is there something in my code logic that might lead to a failure?

    Any insights or debugging strategies would be very helpful!

    Continue reading...

Compartilhe esta Página