A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Errores

14/21
Recursos

Aportes 20

Preguntas 7

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

Errores

  • Dan informaci贸n espec铆fica sobre el fallo
  • Revierte los cambios aplicados para dar conciencia a la ejecuci贸n (El valor del gas cobrado por la ejecuci贸n no se devuelve a quien llama el contrato)

JESUS ! en lo que voy de cursos de blockchain me doy cuenta que el gas en ethereum es un incordio de proporciones mayores O.O ! ahora ya se de donde salieron tant铆simas otras 鈥渆thereum killers鈥

Espero les sirva los comentarios que dejo, se los dejo con amor 鉂わ笍

// SPDX-License-Identifier: GPL-3.0
 pragma solidity >=0.7.0 <0.9.0;
 
 contract platziProject{
     //Aqui creamos nuestras variables
     bool isFundable;
     uint256 Goal; 
     uint256 totalFunded;
     address owner;
     uint256 requiredFunds;
     
     //Inicializamoslos valores, hay que recordar que el constructor se ejecuta solo una vez cuando se crea el contrato
     constructor(){
         Goal = 0;
         owner = msg.sender;
         totalFunded = 0;
         isFundable = true;
     }
     //No te  preocupes por esto,luego loaprenderemos. El modifier permite cambiar el comppoprtamiento de funciones, ene ste caso solo queria asegurarme que solo el creador del contrato pudiera mover el Goal
     modifier onlyOwner{
         require(msg.sender == owner, "You need to be thhe owner from this contract to change the goal");
         _;
     }
     //Creamos el evento el cual va a necesitar quien lo hizo y en este caso  preferia que cambie la meta de fndeo
     event changeGoal(
         address editor,
         uint256 Goal
         );
         
     //Aqui ponemos la meta a recaudar,solamente el que iniciaiza el contrato puede cambiar este valor
     function setGoal(uint256 goal) public onlyOwner {
         Goal = goal;
         emit changeGoal(msg.sender, goal);
     }
     
     function viewGoal() public view returns(uint256) {
         return Goal;
     }
     //Creamos el evento para notificar a los demas que el autor decidio cerrar el fondeo  temporalmente
     event changeState(
         address editor,
         bool change);
         
     function changeProjectState(bool change)public onlyOwner{
         require(isFundable != change, "Can not change the state with the actual state");
         isFundable = change;
         emit changeState(msg.sender, change);
     }
     //Aqui inicia la funcion para fondear el proyecto
     function fundproject() public payable {
         //Primero evaluamos si el owner del contrato mantiene abiertas las donaciones (tal vez necesita reevaluar algo)
         require(isFundable, "Owner has decided to stop this fundraising for a while. Stay tuned");
         //Comprobamos que el total que se ha fondeado sea menor a la meta
         require(totalFunded < Goal, "Goal already achieved so you are  not able to fund this anymore");
         //Despues nos aeguramos que la persona mande un minimo,en este caso arriba de 0
         require(msg.value != uint(0), "Please add some funds to  contribuite to Platzi project");
         //Comprobamos que el valor que quiere fondear no exceda con a meta que tenemos
         require(totalFunded + msg.value <= Goal,"unable to add more funds, check amount remaining for our goal");
         //Actualizamos el total que se ha fondeado al contrato
         totalFunded += msg.value;
     }
     //Esta funcion nos sirve para que lla persona pueda ver cuanto se necesita para alcanzar la meta, asi no tendra que estar adivinando cuanto depositar maximo
     function viewRemaining() public view returns(uint256){
         uint256 remainingFunds = Goal - totalFunded;
         return remainingFunds;
     }
     
     
 }

Felipe es un muy buen profesor y ha logrado transmitir muy bien su conocimiento. Las clases est谩n siendo muy productivas.

Aplicando errores en el reto #4

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

contract CrowdFunding {
    string projectName;
    string projectDescription;
    uint256 goal;
    uint projectStatus;
    uint currentFunds;
    address payable ownerWallet;
    address owner;
    
    error statusIsCosed(uint projectStatus);
    error errorZeroFunds(uint amount);
    
    constructor(string memory _projectName, string memory _projectDescription, uint256 _goal) {
        projectName = _projectName;
        projectDescription = _projectDescription;
        goal = _goal;
        currentFunds = 0;
        
        // Owner Information
        ownerWallet = payable(msg.sender);
        owner = msg.sender;
        
        // Project Status Initialization
        // Status 0 = "Opened"
        // Status 1 = "Closed"
        projectStatus = 0;
    }

    function fundProject() public payable notOwner onlyActiveProjects {
        if (msg.value == 0) {
            revert errorZeroFunds(msg.value);
        }

        ownerWallet.transfer(msg.value);
        currentFunds += msg.value;
        emit NewFundNotification(msg.sender, msg.value);
    }

    function changeProjectStatus(uint newStatus) public onlyOwner {
        require(projectStatus != newStatus, "Project has that state already, choose another!");
        projectStatus = newStatus;
        emit NewStatusChange(newStatus);
    }

    event NewFundNotification(
        address sender,
        uint fundAmount
    );
    
    event NewStatusChange(
        uint newStatus
    );

    modifier onlyActiveProjects() {
        if (projectStatus == 1) { 
            revert statusIsCosed(projectStatus);
        }
        _;
    }

    modifier notOwner() {
        require(owner != msg.sender, "Owners shouldnt send funds to its own projects!");
        _;
    }

    modifier onlyOwner() {
         require(owner == msg.sender, "You must be the project owner!");
         _;
    }

    function getGoal() public view returns(uint) {
        return goal;
    }
    
    function getStatus() public view returns(uint) {
        return projectStatus;
    }
    
    function getFunds() public view returns (uint) {
        return currentFunds;
    }
    
}

Reto clase anterior

pragma solidity ^0.7.0;


contract KickstarterPoor {
        
    string name;
    string description;
    string state = "opened";
    uint256 goal;
    uint256 funds;
     address private owner;
    
    address payable creatorPayable;
    
    
    constructor(string memory _name, string memory _description, uint256 _goal) payable{
        
        name = _name;
        description = _description;
        owner = msg.sender;
        creatorPayable = payable(owner);
        goal = _goal;
        funds = 0;
        
    }
    
   
    
    event newFunds(
        address sender,
        uint256 funds
        );
        
    event projectState(
        uint256 goal,
        uint256 funds,
        string state
        );
    
    
    function checkStatus () public view returns (string  memory){
        
    return state;
    }
    
    function getFunds() public view returns (uint256){
        return funds;
    }
        
    
    
    modifier noFundOwner (){
          require(msg.sender != owner, "You can't donate to yourself, I'll call the police.");
        _;
    }
    
   modifier onlyOwner (){
        require(msg.sender == owner, "You are not admin, go away");
        _;
    }
    
     function FundProyect() public payable noFundOwner{
         creatorPayable.transfer(msg.value);
        funds += msg.value;
        emit newFunds(msg.sender,msg.value);
    }
    
    
    function changeProjectState(string calldata newState) public  onlyOwner{
        
        state = newState;
        
        emit projectState(goal,funds,state);
    }
    
    
}

Funcion de los errores

**Esto es en parte aportes, c贸digo del curso y una peque帽a parte de c贸digo propio espero que les sirva **

<// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract CrowFounding {

    string public id;
    string public name;
    string public description;
    address payable public author;
    string public state = "Opened";
    uint public funds;
    uint public fundraisingGoal;


    // constructor (solo se ejecutal al momento del despliegue)
    constructor(
        string memory _id,
        string memory _name,
        string memory _description,
        uint _fundraisingGoal) {
            id = _id;
            name = _name;
            description = _description;
            fundraisingGoal = _fundraisingGoal;
            author = payable(msg.sender);
    }

    // controlo q solo el due帽o pueda cambiar el estado
    modifier onlyOwner() {
        require(msg.sender == author, "Only owner can change the project state.");
        //la funci贸n es insertada en donde aparece este s铆mbolo
        _;
    }

    // controlo q el due帽o no pueda aportar
    modifier notOwner() {
        require(msg.sender != author, "Owner cannot add to the proyect.");
        //la funci贸n es insertada en donde aparece este s铆mbolo
        _;
    }

    event depositedAmount(
        address contributor,
        string projectId,
        uint amount
    );

    event projectStateChange(
        string id,
        string state
    );

    // funcion para aportar
    function fundProject() public payable notOwner {
        author.transfer(msg.value);
        funds += msg.value;
        emit depositedAmount(msg.sender, id , msg.value);
    }

    // funcion para cambiar el estado del proyecto
    function changeProjectState(string calldata newState) public onlyOwner {
        state = newState;
        emit projectStateChange( id, newState );
    }

}

> 


Para el reto ya tenia el contrato de fondeo con varios require de esta manera:

//IF the project is still alive
        require(Isfondeable, "The project is not longer available");

        //If the goal is not reach yet
        require(totalFunded < Goal, "The Goal is already reach");

        //Check valid amount
        require(msg.value != uint(0), "Please add a amount to contribute to the project");

        //Check not exceed the goal
        require(totalFunded + msg.value <= Goal, "unable to add more funds, check amount remaining for our goal");

Pero por tema del reto, agregue una validaci贸n con un if y error en el cambio de estado:

function ChangeProjectState(bool change) public OnlyOwner {
        if(Isfondeable == change) {
            revert IsSameState(change, "Can't change the state to same status");
        }
        Isfondeable = change;
        emit ProjectStateEvent(change, id);
    }

RETO 4:
Observaci贸n: Para comparar strings encontr茅 que se genera un hash con: keccak256(abi.encodePacked(str))

// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.7.0 <0.9.0;

contract projectFundPlatzi{
    string public name;
    bool public isFundable;
    uint public deposits;
    uint public depositsGoal;
    uint private depositTest;
    address private autor;
    string public state = "Open";
    string private tokenLog = "Log: project status changed";
    string private tokenFeedback = "Feedback: Gracias";
  
    constructor(
        string memory _name
        ){
            name = _name;
            isFundable = true;
            deposits = 0;
            depositsGoal=1000;
            autor = msg.sender; 
    }
    error stateNotDefined (string newState);

    event newFundFeedback(
        address autor,
        uint256 deposit,
        string Feedback
    );
    event newFundLog(
        uint256 depositsGoal,
        uint256 deposits,
        string Log
    );
    modifier notOnlyOwnerPay{
        require (autor != msg.sender, "El propietario no puede abonar fondos al proyecto" );
        //la funcion es insertada donde aparece este simbolo _
        _;
    }
    modifier ownerRequired {
        require (msg.sender == autor, "Esta accion es restringida al propietario.");
        _;
    }
    function viewDeposits() public view returns (uint){
        return deposits;
    }

    function viewRemaining() public view returns(uint256){
        return depositsGoal - deposits;
    }

    function fundProject(address payable benefactor) public payable notOnlyOwnerPay {     
        require (msg.value > 0, "No se acepta abonos sin valor.");
        depositTest = deposits + msg.value;
       
        if (isFundable == true && depositTest <= depositsGoal) {
            benefactor.transfer(msg.value);
            deposits +=  msg.value;
            emit newFundFeedback (autor, msg.value,tokenFeedback);
        }
        changeProjectState("Closed");
    }

    function changeProjectState(string memory _newState) public {
        require (keccak256(abi.encodePacked(_newState))  != keccak256(abi.encodePacked(state)), "El nombre de estado es igual al actual y no es actualizable");
        if (keccak256(abi.encodePacked(_newState)) == keccak256(abi.encodePacked("Open"))){
            isFundable = true;
            state = "Open";
        }else if (keccak256(abi.encodePacked(_newState)) == keccak256(abi.encodePacked("Closed"))){
            isFundable = false;
            state = "Closed";
        } else {
            revert stateNotDefined (_newState);
        }          
       isFundable = !isFundable;
       emit newFundLog (depositsGoal, deposits, tokenLog);
    }
}

aporto mi ejemplo al reto 4

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract CrowdFunding {
// variables (q uso en el contructor)
string public id;
string public name;
string public description;
address payable public author;

//variables ....q no uso en el costructor
//string public state = "Opened"; 0 open 1 close
uint public state = 0; // 0 open 1 close
uint256 public funds;
uint256 public fundraisingGoal;

// evento para saber quien aporto y cuanto queda
event ChangeFound(
    address editor,
    uint256 fundRestante

);

// constructor (solo se ejecutal al momento del despliegue)
constructor(
    string memory _id,
    string memory _name,
    string memory _description,
    uint256 _fundraisingGoal
) {
    id = _id;
    name = _name;
    description = _description;
    fundraisingGoal = _fundraisingGoal;
    author = payable(msg.sender);
}

// controlo q solo el due帽o pueda cambiar el estado
modifier onlyOwner() {
    require(msg.sender == author, "Only owner can change the project state.");
    //la funci贸n es insertada en donde aparece este s铆mbolo
    _;
}

// controlo q el due帽o no pueda aportar
modifier notOwner() {
    require(msg.sender != author, "Owner cannot add to the proyect.");
    //la funci贸n es insertada en donde aparece este s铆mbolo
    _;
}

// funcion para aportar
function fundProject() public payable notOwner {
    require(state == 0, "Proyect is closed");
    require(msg.value > 0, "Not mouse acepted.");
    author.transfer(msg.value);
    funds += msg.value;
    emit ChangeFound(msg.sender, fundraisingGoal - funds);
}


// funcion para cambiar el estado del proyecto
//function changeProjectState(string calldata newState) public onlyOwner {
    function changeProjectState(uint newState) public onlyOwner {
    require(newState == 0 || newState == 1, "Value not defined");
    state = newState;
}

}

Me encantan estas clases, aunque al principio era un poco confuso la sintaxis de sollidity, ya me voy familiarizando de a poco

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract CrowdFunding2 {
    string public id;
    string public name;
    string public description;
    address payable public author;
    uint256 public state = 0;
    uint256 public funds;
    uint256 public fundraisingGoal;

    constructor(
        string memory _id,
        string memory _name,
        string memory _description,
        uint256 _fundraisingGoal
    ) {
        id = _id;
        name = _name;
        description = _description;
        fundraisingGoal = _fundraisingGoal;
        author = payable(msg.sender);
    }
    modifier onlyOwner(){
        require(msg.sender == author,"Just the owner can do this action");
         _;
    }
    modifier excludeOwner(){
        require(msg.sender != author,"Owner can not do this action");
         _;
    }
    
    event projectFunded(uint256 lastfunds, uint256 income);
    event stateChanged(address editor, uint256 newState);

    error NoZeroFunds(uint256 unit);

    function fundProject() public payable excludeOwner {
        if(state == 1){
            require(state == 1, "The contract is already closed, funds are not acepted");
        }else if (state == 0){
            if (msg.value == 0){
                revert NoZeroFunds(msg.value);
            }
            author.transfer(msg.value);
            funds += msg.value;
            emit projectFunded(funds-msg.value, msg.value);
        }

    }

    function changeProjectState(uint256 newState) public onlyOwner {
        require(newState != state, "The contract is already in that state");
        state = newState;
        emit stateChanged(msg.sender, state);
    }
}

Mi soluci贸n al reto #4 馃槂

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract crowfundingContract {
    //Definir los datos iniciales de quien despliegue el contrato (i.e. el que empieza su crowfunding con la
    //estructura de este contrato)
    string public id;
    string public projectName;
    string public description;
    string public status = "Opened";
    uint public statusID = 0;
    address payable public author;
    uint public fundingGoal;
    uint public funds;

    event fundedBy (
        string project,
        address participant,
        uint vulue
    );
    event changedBy (
        string project,
        address author,
        string newStatus
    );

    // reto#4
    error noFundSelected (uint funds, string err);
    error statusAlreadySelected (uint status);
    error notAnOption (uint status);
    error projectClosed (string err);
    // reto#4

    //Crear el constructor que inicializa variables relevantes a qui茅n inicie un corwfunding
    constructor(string memory _id, string memory _projectName, string memory _description, uint _fundingGoal){
        author = payable(msg.sender);
        id = _id;
        projectName = _projectName;
        description = _description;
        fundingGoal = _fundingGoal;
    }
    //Crear una funci贸n que permita a qui茅n la llame aportar al crowfunding deseado
    function fundProject() public payable fundRestriction {
        if (statusID == 0){
            if (msg.value == 0){
            revert noFundSelected(msg.value, "You cannot fund with 0 wei!");
            }else{
                author.transfer(msg.value);
                funds += msg.value;
                emit fundedBy(id, msg.sender, msg.value);
            }
        }else{
            revert projectClosed ("Project is currently closed, you cannot fund it!");
        }
        
    }

    //Crear la funci贸n que permita cambiar el estado del proyecto
    function changeProjectStatus(uint newStatus) public changeStatusRestriction {
        if(newStatus != statusID){
            if (newStatus == 0){
            status = "Opened";
            statusID = newStatus;
            emit changedBy(id, msg.sender, status);
            }else if (newStatus == 1){
            status = "Closed";
            statusID = newStatus;
            emit changedBy(id, msg.sender, status);
            }else{
                revert notAnOption (newStatus);
            }
        }else {
            revert statusAlreadySelected (newStatus);
        }     
    }
    //Crear el modificador para que s贸lo qui茅n despliega el contraro en la red de ethereum pueda modificar el estado
    //del proyecto a financiar
    modifier changeStatusRestriction(){
        require(
            msg.sender == author,
            "Only the owner can change the status"
        );
        _;
    }
    //Crear la funci贸n modifier que evita que el creador del crowfunding aporte a su propio proyecto
    modifier fundRestriction(){
        require(
            msg.sender != author,
            "You as the author cannot fund this project"
        );
        _;
    }

}

Creo que por ahi puede ser鈥

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract CrowdFunding {
    string public id;
    string public name;
    string public description;
    address payable public author;
    // string public projectState = "Open"; //por defecto abierto a recibir aporte
    uint public funds;
    uint256 public fundGoal; //define cuanto espero ganar con la ronda de levantamento de capital
    
    uint public projectStatus;

    constructor(string memory _id, string memory _name, string memory _description, uint256 _fundGoal){
        id = _id;
        name = _name;
        description = _description;
        fundGoal = _fundGoal;
        // Owner Information
        author = payable(msg.sender); //msg.sender por defecto no recibe ETH pero la convertimos a 'payable'
        
        // Status 0 = "Close"
        // Status 1 = "Open"
        projectStatus = 1;
    }

    //registrar fondos del proyecto. Con 'event' compatimos los datos ala Blockchain
    event ProjectFunded(string projectId, uint256 value);

    event ProjectStateChanged(string id, uint state);

    // solo podemos modificar el estado del projecto siendo el propietario
    modifier onlyAuthor() {
        require(author == msg.sender ,
        "Only owner can change state of project"
        );
        _;
    }

    modifier noSelfFunds() {
        require(
             author != msg.sender,
            "Autofinance is not available"
        );
        _;
    }


    //Manjeo de errores
    error ProjectClosed(uint projectStatus);
    error NoZeroFunds(uint amount);

    //caulquier persona la puede ver y se puede enviar ETH sin problemas
    function fundProject() public payable noSelfFunds {

        //Project close
        require(projectStatus != 1, "Project is already close. No more funds are collected");
        
        //validacion para que no se puedan hacer aportes de 0
        if(msg.value == 0){
            revert NoZeroFunds(msg.value);
        }
        author.transfer(msg.value); //transfiere el valor del usuario al autor
        funds += msg.value; //despues lo agrego a los fundos del proyecto para registrar el aporte

        emit ProjectFunded(id, msg.value);
    }

    //modifica el estado del proyecto. Calldata ahorra gas, solo existe cuando se le llama a la funcion
    function changeProjectState(uint newState) public onlyAuthor{
        require(projectStatus != newState, "Project has already that state");
        projectStatus = newState;
        emit ProjectStateChanged(id, newState);
    }

}

Este es mi avance con los errores programados con el reto #4:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract Proyecto_Platzi{
    string public projectName;
    string public projectOwner;
    uint public projectState = 0;
    address payable ownerWallet;
    uint public goal;
    uint public currentFund;

    error SameStateChange(uint state);
    error StateClosed(string state);
    error FundZero(uint fundGiven);

    constructor(string memory _projectName, string memory _projectOwner, uint _goal){
    projectName = _projectName;
    projectOwner = _projectOwner;
    ownerWallet = payable(msg.sender);
    goal = _goal;
    }

    modifier onlyOwner() {
        require(
            msg.sender == ownerWallet,
            "Only owner can change the project state"
        );
        //la funci贸n es insertada en donde aparece este simbolo
        _;
    }


    modifier differentToTheOwner() {
        require(
            msg.sender != ownerWallet,
            "The owner can't fund the project"
        );
        //la funci贸n es insertada en donde aparece este simbolo
        _;
    }

    event ChangeState(
        uint previousState,
        uint newState
    );

    event FundValueGiven(
        uint fundGiven,
        uint valueToGoal,
        string greetingMessage
    );

    function fundProject() public payable differentToTheOwner{
        if(projectState == 0){
            if(msg.value != 0){
                ownerWallet.transfer(msg.value);
                currentFund += msg.value;
                emit FundValueGiven(msg.value, (goal - msg.value), "Thanks for your contribution");
            }
            else if(msg.value == 0){
                revert FundZero(msg.value);
            }

        }
        else if(projectState == 1){
            revert StateClosed("Sorry, this project is closed");
        }
    }

    function changeProjectState(uint newState) public onlyOwner{
        if(msg.sender == ownerWallet){
            if(newState != projectState){
                emit ChangeState(projectState, newState);
                projectState = newState;
            }
            else{
                revert SameStateChange(newState);
            }
            
            
        }
    }
}

Esta muy bueno el curso, como esta manejando la clase y el proyecto al mismo tiempo, asi llevamos la teoria vista aplicada en la practica y poco a poco va tomando mas complejidad el contrato 馃槃

Reto #4

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.0;

contract CrowdFunding {
    string id;
    string projectName;
    uint targetAmount;
    uint amountFunded;
    bool isFundable;
    address payable authorAddress;
    
    // Events
    event projectFunded(
        address sender,
        uint amount
    );
    
    event projectStateChanged (
        string projectName,
        string message
    );
    // ./Events
    
    constructor(string memory _id, string memory _projectName, uint _targetAmount){
        id = _id;
        projectName = _projectName;
        targetAmount = _targetAmount;
        authorAddress = payable(msg.sender);
        amountFunded = 0;
        isFundable = true;
    }
    
    function fundProject() public payable isNotAuthor canFund {
        require(msg.value > 0, 'The funded amount can not be 0');
        authorAddress.transfer(msg.value);
        amountFunded += msg.value;
        emit projectFunded(msg.sender, msg.value);
    }
    
    function changeProjectState(string calldata newState) public isAuthor {
        string memory currentState = isFundable ? string('opened') : string('closed');
        
        require(keccak256(abi.encode(newState)) == keccak256(abi.encode('opened')) || keccak256(abi.encode(newState)) == keccak256(abi.encode('closed')), 'This state is not defined');
        require(keccak256(abi.encode(newState)) != keccak256(abi.encode(currentState)), string(abi.encodePacked('This project is already ', currentState )));
        
        if(keccak256(abi.encode(newState)) == keccak256(abi.encode('opened'))){
            isFundable = true;
        } else if(keccak256(abi.encode(newState)) == keccak256(abi.encode('closed'))) {
            isFundable = false;
        }
        
        emit projectStateChanged(projectName, isFundable ? 'Project opened' : 'Project closed');
    }
    
    // Function modifiers
    modifier isAuthor(){
        require(authorAddress == msg.sender, "You must be the project author!");
        _;
    }
     
    modifier isNotAuthor() {
        require(authorAddress != msg.sender, "As author you can not fund your own project!");
        _;
    }
    
    modifier canFund(){
        require(isFundable == true, "This project is not available for funding!");
        _;
    }
    // ./Function modifiers
    
    function getGoal() public view returns(uint){
        return targetAmount;
    }
    
    function getFunds() public view returns(uint){
        return amountFunded;
    }
    
    function getStatus() public view returns(string memory){
        return isFundable ? 'Opened': 'Closed';
    }
}

cuando nos muestra un error emite un JSON con el field StateNotDefined

para lanzar el error usamos revert