No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Modificadores de funciones

12/21
Recursos

Solidity implementa un tipo de función especial denominada Modificadores que nos permiten ejecutar una pieza de código antes o después del comportamiento de la propia función.

Comportamiento de una función

Los usos más frecuentes de los modificadores suelen ser la validación de datos o la restricción de acceso a una función si el usuario no tiene permisos. Dichas validaciones puedesn realizarse con modificadores que además permiten ser reutilizadas.

Estos nos permiten hacer validaciones antes de ejecutar las funciones. De esta forma, podemos evitar comportamientos inesperados o que alguien sin autorización ejecute la función.

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

contract FunctionModifier {

    address public owner;

    constructor() {
        // Guardamos la información del dueño del contrato para validar al mismo
        owner = msg.sender;
    }

    // Modificador para validar que la llamada la realiza el dueño del contrato
    modifier onlyOwner() {
        require(msg.sender == owner, "No eres el owner");
        _;
    }

    // Solo el dueño del proyecto puede cambiar al mismo
    function changeOwner(address _newOwner) public onlyOwner {
        owner = _newOwner;
    }
}

La sintaxis de un modificador es sencilla, utilizando la palabra reservada modifier, declaramos la función y dentro del mismo utilizamos un require para realizar una validación y un _ para indicarle al compilador de Solidity que continúe ejecutando el resto de la función si la condición se cumplió correctamente.

En el caso de que la condición no se cumpla y el modificador rechace la transacción, el require realizará un revert para volver atrás todos los cambios de estado del contrato por nosotros y que no tengamos que preocuparnos. Las operaciones en Solidity son atómicas, lo que quiere decir que se ejecuta correctamente cada una de las instrucciones o no se ejecuta ninguna.

Finalmente, una función puede implementar el modificador en la declaración de la misma. A lo igual que indicamos que una función es public o pure, también le implementamos el nombre del modificador que utilizará.

 function changeOwner(address _newOwner) public onlyOwner { }

La lógica dentro del modificador puede ser del nivel de complejidad que necesitemos, usando condicionales u otros flujos de control. Con esta característica de Solidity, ya estás listo o lista para desarrollar contratos con permisos y validaciones de datos para que el flujo del mismo sea el esperado.


Contribución creada por: Luis Enrique Herrera y Kevin Fiorentino (Platzi Contributors).

Aportes 55

Preguntas 16

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Yo estaba haciendo cosas extrañas con el if para evitar eso que alguien mas cambiara el nombre, debi terminar la clase primero XD

Modificadores de funciones

  • Nos permiten hacer validaciones antes de ejecutar nuestra función, de esta forma podemos evitar comportamientos inesperados o que la función sea ejecutada por alguien que no tiene permisos de hacerlo.

El código está genial, pero si creo que deberían ponerle comentarios, no sé qué tan bueno sea esto para los Smart Contracts.

Ahora con modifier … muy chevere como fluye todo

// SPDX-License-Identifier: GPL-3.0

// enmarca las versiones del compilador que soporta el smart contract
pragma solidity >=0.7.0 <0.9.0;

// nombre del contrato 
contract FondosProyecto {
    
    
    // variables de estado del contrato
    // se etablecen a publicas para que se puedan ver 
    int public idProyecto;
    string public nameProyecto;
    uint256 public objetivoFondos;
    bool private recibeFondos;
    // esta variable es address payable por que maneja la cartera que vamos a recibir los fondos
    address payable public autor;
    // variable para almacenar el proietario de la wallet
    address private owner;
    
    uint256 public fondos;
    // constructor que permite registrar la informacion del proyecto y su objetivo 
    constructor (int _idProyecto, string memory _nameProyecto, uint256 _objetivoFondos){
        idProyecto = _idProyecto;
        nameProyecto=_nameProyecto;
        objetivoFondos = _objetivoFondos;
        autor = payable(msg.sender); // se inicializa con la cartera actual
        recibeFondos = true; // es verdareo cuando inicia a re¿cibir fondos
        //se inicializa la cartera del propuetario
        owner = msg.sender;
    }
    
    // esta funcion permite realizar la transaccion de una carte a la cartera propia 
    // no sin antes verificar si no se ha legado al tope del objetivo de los fondos
    function fundProyect () public payable {
        // si aun recibe fondos 
        if (recibeFondos){
            autor.transfer (msg.value);
            fondos += msg.value;    
        }
        // verifica si cumplio con el objetivo para no recibir mas fondos
        changeFundProyect(); // cambia el estado de la variable a falso
    }
    
    // modifier no permite abonar fondos por el propietario del proyecto 
    modifier notOnlyOwnerPay (){
        require (autor != owner, "El propietario no puede abonar fondos al proyecto" );
        //la funcion es insertada donde aparece este simbolo _
        _;
    }
    
    
    // cambia el estado de la variable si los fondos recibidos son superiores a los objetivo
    function changeFundProyect () public payable notOnlyOwnerPay {
        if (fondos > objetivoFondos) {
            recibeFondos = false;
        }
    }
    
    // funcion que retorna el estado de la variable si recibe fondos
    function getRecibeFondos () public view returns (bool){
        return recibeFondos;
    }
    
    // restringe a que solo el propietario de la Wallet permita cambiar un estado
    modifier onlyOwner (){
        require (msg.sender == owner, "Solo el propietario pude realizar estos cambios" );
        //la funcion es insertada donde aparece este simbolo _
        _;
    }
    
    
    // aplicamos la funcion modiifer para restringir el cambio del la ariable recibe-fondos 
    function changeRecibeFondos () public onlyOwner {
        if (recibeFondos) {
            recibeFondos = false;
        } else {
            recibeFondos = true;
        }
        
        
    }

}

Me parece que los modifiers son azucar sintactica que implementa el patron decorador, un poco parecido a los decoradores en Python
Mas info: https://medium.com/coinmonks/solidity-tutorial-all-about-modifiers-a86cf81c14cb

Hola, para comentarles que yo puse el mensaje del modifier en español y el compilador no me aceptó la ñ, uno creería que al ser un string no hay problema pero no, da error de “invalid character”.

Espero que a alguien le sirva.

Estaba medio loco en la anterior clase, pero ya voy avanzando y entendiendo … me esta gustandoo …!

aqui mi version

// SPDX-License-Identifier: GPL-3.0

// enmarca las versiones del compilador que soporta el smart contract
pragma solidity >=0.7.0 <0.9.0;

// nombre del contrato 
contract FondosProyecto {
    // variables de estado del contrato
    // se etablecen a publicas para que se puedan ver 
    int public idProyecto;
    string public nameProyecto;
    uint256 public objetivoFondos;
    bool private recibeFondos;
    // esta variable es address payable por que maneja la cartera que vamos a recibir los fondos
    address payable public autor;
    uint256 public fondos;
    // constructor que permite registrar la informacion del proyecto y su objetivo 
    constructor (int _idProyecto, string memory _nameProyecto, uint256 _objetivoFondos){
        idProyecto = _idProyecto;
        nameProyecto=_nameProyecto;
        objetivoFondos = _objetivoFondos;
        autor = payable(msg.sender); // se inicializa con la cartera actual
        recibeFondos = true; // es verdareo cuando inicia a re¿cibir fondos
    }
    
    // esta funcion permite realizar la transaccion de una carte a la cartera propia 
    // no sin antes verificar si no se ha legado al tope del objetivo de los fondos
    function fundProyect () public payable {
        // si aun recibe fondos 
        if (recibeFondos){
            autor.transfer (msg.value);
            fondos += msg.value;    
        }
        // verifica si cumplio con el objetivo para no recibir mas fondos
        changeFundProyect(); // cambia el estado de la variable a falso
    }
    
    // cambia el estado de la variable si los fondos recibidos son superiores a los objetivo
    function changeFundProyect () public payable {
        if (fondos > objetivoFondos) {
            recibeFondos = false;
        }
    }
    
    // funcion que retorna el estado de la variable si recibe fondos
    function getRecibeFondos () public view returns (bool){
        return recibeFondos;
    }

}

Este es el verdadero curso de Introducción a Solidity, no diré mas

Me ha costado un poco entener todo y tuve que corregir errores pero lo logré y me alegró el día jajajaja. Aquí les dejo el código:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

/**
 * @title Storage
 * @dev Store & retrieve value in a variable
 */
contract platziProject {
    string public id;
    string public name;
    string public description;
    address payable public author;
    string public state = "Opened";
    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,
            "Only owner can change the project state"
        );

        _;
    }

    modifier exceptOwner(){
        require(
            msg.sender != author,
            "Owner can't send funds"
        );

        _;
    }

    function fundProject() public payable exceptOwner{
        author.transfer(msg.value);
        funds += msg.value;
    }

    function changeProjectState(string calldata newState) public onlyOwner{
        state = newState;
    }
} 

Convalidacion del dueño(owner)

  • El constructor sólo se ejecuta 1 vez , y es al momento de crearlo por eso al colocar (owner=msg.sender) , solo se guarda nuestra dirección de wallet como “owner” que es nuestra direccion , el modifiere convalidara que la direccion de otras wallets(msg.sender) no se igual a la original “owner”.
    Asi evita que pueda ser cambiada.

Llamar la funcion modifiere onlyOwner para evitar modificaciones externas.

Solución reto 2

Notar que se puede agregar mas de un modifier por función:

function fundProject() public payable notOwner onlyWhenActive {
	owner.transfer(msg.value);
        founds += msg.value;
}
// SPDX-License-Identifier: MIT

pragma solidity ^0.5.0;

contract Project {
    
    string public name;
    bool public isActive;
    address payable public owner;
    uint public founds;
    uint public goal;
    
    constructor(string memory _name, uint _goal) public {
        name = _name;
        goal = _goal;
        isActive = true;
        owner = msg.sender;
    }
    
    modifier onlyOwner() {
        require(owner == msg.sender, "You are not the project owner");
        _;
    }
    
    modifier notOwner() {
        require(owner != msg.sender, "You cannot transfer to your own project");
        _;
    }
    
    modifier onlyWhenActive() {
        require(isActive, "This project is not active.");
        _;
    }
    
    function fundProject() public payable notOwner onlyWhenActive {
        owner.transfer(msg.value);
        founds += msg.value;
    }
    
    function changeProjectState() public onlyOwner {
        isActive = !isActive;
    }
}

```js // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Project { address public owner; // Guardará la dirección del dueño del contrato uint public fondos; // Guardará la cantidad de fondos bool public activo; // Indica si el proyecto está activo // Constructor: se ejecuta una sola vez cuando se despliega el contrato constructor() { owner = msg.sender; // 'msg.sender' es quien despliega el contrato (el dueño) activo = true; // El proyecto comienza activo por defecto } // Funcion que permite enviar ether a un proyecto function fundProject() public payable { require(activo, "El proyecto no esta activo."); // Verifica si el proyecto está activo fondos+=msg.value; // `msg.value` es la cantidad de ether que se envía } // Funcion que nos va a permitir cambiar el estado del proyecto function changeProjectState() public{ require(msg.sender == owner, "Solo el dueno puede cambiar el estado."); activo = !activo; // Cambia el estado: si está activo lo desactiva, y viceversa } } ```

RETO 2

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

contract Project {
    
    address projectId; //Project addresss for send fund
    string public projectName;
    string public descriptionProject;
    bool public projectState;
    address owner;
    
    constructor () {
        projectState = true; //initalizer state project 
        descriptionProject = "Everithing in one click";
        projectName = "Xevar";
        owner = msg.sender;// The owner is who deploy the contract
    }
    
    modifier onlyOwner () {
       require(msg.sender == owner, "This function only change for the owner");
       _;
    }
    modifier notYourself () {
       require(msg.sender != owner, "The author cannot send fund for yourself");
       _;
    }
    
    function fundProject(address payable receiver) public notYourself payable {
        require(projectState == true, "This project is closed!");
        receiver.transfer(msg.value);
    }
    
    function changeProjectState(bool state) public  onlyOwner returns(bool){
        projectState = state;
        return projectState;
    }
    
} 

Muy divertido el reto

.

<h5>Para evitar que el autor se fondee</h5>
	modifier notFundFronAuthor {
		require(
			msg.sender != author,
			"Author don't funding his ouw project"
		);
		_;
	}
<h5>Para evitar que un usuario que no se el author cambie el estado, a menos que ya se haya alcanzado el objetivo de fondo</h5>
	modifier onlyAuthorOrRaisingGoal {
		require(
			msg.sender == author || funds >= fundraisingGoal,
			"Only author can change state or if the fundraidingGoal is raising"
			);
			_; // identifica desde donde se inserta la función, define cuando se continua la función
	}
<h5>Para evitar que alguien fondee el proyecto cuando este esté en estado distinto al opened</h5>
	modifier onlyFundingIfOpened {
		require(
			keccak256(abi.encodePacked(string(state))) == keccak256(abi.encodePacked("Opened")) ||
			keccak256(abi.encodePacked(string(state))) == keccak256(abi.encodePacked("opened")),
			"Project isn't open"
		);
		_;
	}
modifier onlyOwner(){
        require(
            msg.sender == author, "Only the owner can change the state"
        );
        _;
    }
    
    modifier ownerNotFund(){
        require(
            msg.sender != author, "The owner can't fund"
        );
        _;
    }

Modificadores de funciones
-Es utilizado para modificar el comportamiento de tu contrato inteligente.
Uso:
-Nos permite reducir la redundancia del código; si estamos verificando la misma condición, podemos reutilizarlo siempre y cuando estemos realizando la misma condición.
Cuando lo debo usar?

  • Se usa antes de ejecutar una función de manera automática. Si la funcion NO CUMPLE con el requisito del modificador, lanzamos una excepcion y la ejecucion de la FUNCION se detiene.

NOTA: Para entender varios aspectos de los cuales se han hablado aqui, es importante tener conocimiento en POO.
(https://platzi.com/cursos/oop/)

// SPDX-License-Identifier: MIT

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 state = "Opened";
    uint public funds;
    uint public fundraisingGoal;

    constructor(string memory _id, string memory _name, string memory _description, uint _fundraisingGoal) {
        id = _id;
        name = _name;
        description = _description;
        fundraisingGoal = _fundraisingGoal;
        author = payable(msg.sender);
    }

    function fundProject() public payable {
        author.transfer(msg.value);
        funds += msg.value;
    }

    function changeProjectState(string calldata newState) public {
        state = newState;
    }

    modifier onlyAuthor() {
        require(
            msg.sender == author,
            "Only author can change the project name"
        );
        //la función es insertada en donde aparece este simbolo
        _;
    }

    function changeCrowdFundingName(string memory _crowdFundingName) public onlyAuthor {
        name = _crowdFundingName;
    }
}

Me va gustando como va todo!

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Crowdfunding {

    string public project_name;
    bool public status;
    uint256 public goal;
    uint256 public funded;
    address payable public owner;

    constructor(string memory _project_name, bool _status, uint256 _goal) payable {
        project_name = _project_name;
        status = _status;
        goal = _goal;
        funded = 0;
        owner = payable(msg.sender);
    }

     modifier owner_permission() {
        require(
            owner == msg.sender, 
            "Actualizar el proyeto solo es para el propietario."
        );
        // La funcion a modificar sera insertada en este simbolo, funciona como un decorador.
        _;  
    }

    modifier owner_fund() {
        require(owner != msg.sender, "El propietario no puede agregar dinero a su proyecto.");
        _;
    }

    function fundProject() public payable owner_fund {
        require(status, "No se aceptan mas entradas de dinero.");
        require(funded != goal, "Ya se llego a la meta, no se necesita mas dinero.");
        require(msg.value != uint(0), "Agregue dinero al proyecto.");
        require(funded+msg.value <= goal, "No se puede agregar mas dinero que la meta.");
        funded = funded + msg.value;
        owner.transfer(msg.value);
    }

    function chageProjectState(bool _status) public owner_permission {
        status = _status;
    }
}

Si antes han trabajado con frameworks que hacen uso de decoradores, los modificadores analogicamente funcionan parecido. Le dan un comportamiento adicional a las funciones donde se invocan.

Reto #2

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

contract Permission {

    address private owner;
    string public projectName="Platzi";
    string public state="Open";
    address payable public author;
    uint256 public funds;

    constructor() {
        // Guardamos la información del dueño del contrato para validar al mismo
        owner = msg.sender;
        author = payable(msg.sender);
    }

    // Modificador para validar que la llamada la realiza el dueño del contrato
    modifier onlyOwner() {
        require(msg.sender == owner, "No eres el owner");
        _;// indicarle al compilador de Solidity que continúe ejecutando el resto de la función si la condición se cumplió correctamente
    }

    // Modificador para validar que la llamada la realizan otros excepto el owner
    modifier projectFunders() {
        require(msg.sender != owner , "No puedes colaborar a tu propio proyecto");
        _;
    }

    //Todos pueden colaborar excepto el owner 
    function fundProject() public payable projectFunders {
        author.transfer(msg.value);
        funds += msg.value;
    }
    
    //Solo el dueño puede cambiar el estado
    function changeProjectState(string calldata newState) public onlyOwner {
        state = newState;
    }

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

pragma solidity >=0.7.0 <0.9.0;

contract Crowfunding {
    string public id;
    string public name;
    string public description;
    address payable public author;
    string public state = 'Opened';
    uint public funds;
    uint public fundraisingGoal;

    constructor(string memory _id, string memory _name, string memory _description, uint _fundraisingGoal) {
        id = _id;
        name = _name;
        description = _description;
        fundraisingGoal = _fundraisingGoal;
        author = payable(msg.sender);
    }

    modifier onlyOwner() {
        require(
            msg.sender == author,
            "Only owner can change the project state"
        );
        _;
    }

    modifier notOwner() {
        require(
            msg.sender != author,
            "The owner can't contribute to the project"
        );
        _;
    }

    function fundProject() public payable notOwner {
        author.transfer(msg.value);
        funds += msg.value;
    }

    function changeState(string calldata newState) public onlyOwner {
        state = newState;
    }
}

Mi aporte del reto 😃

  modifier onlyOwner() {
    require(
      msg.sender == author,
      'Only owner can do this operation!'
    );
    _;
  }

  modifier differentOwner() {
    require(
      msg.sender != author,
      'You can do this as owner'
    );
    _;
  }
// SPDX-License-Identifier: GPL - 3.0 

pragma solidity >=0.7.0 < 0.9.0; 

contract Crowfunding {
    // Variables de estado
    string idProject;
    string public nameProject; 
    string public descriptionProject; 
    string public stateProject  = "Open"; 
    address payable public walletProject; 
    uint public limiteFund; 
    uint public collectFund; 

    constructor(string memory _idProject, string memory _nameProject, string memory _descriptionProject, uint  _limiteFund  ){
        idProject = _idProject;
        nameProject = _nameProject;
        descriptionProject = _descriptionProject;
        limiteFund = _limiteFund;
        walletProject = payable(msg.sender);
    }

    function fundProject() public payable {
        walletProject.transfer(msg.value);   
        collectFund += msg.value;
    }

    function changeProjectState(string memory newState) public  {
        stateProject = newState;
    }

}

Aquí mi respuesta,

// 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 owner;
    string public state = 'Opened';
    uint public funds;
    uint public fundraisingGoal;

    constructor(string memory _id, string memory _name, string memory _description, uint _fundraisingGoal) {
        id = _id;
        name = _name;
        description = _description;
        fundraisingGoal = _fundraisingGoal;
        owner = payable(msg.sender);
    }

    modifier onlyNotOwner(){
        require(
            msg.sender != owner,
            "The owner can't fund is own project"
        );
        _;
    }

    function fundProject() public payable onlyNotOwner {
    owner.transfer(msg.value);
    funds += msg.value;
    }


    modifier onlyOwner(){
        require(
            msg.sender == owner,
            "Only owner can change the project name"          
        );
        _;
    }

    function changeProjectState(string calldata newState) public onlyOwner {
        state = newState;
    }

}

RETO #2

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract reto_dos{
   address payable public owner;
   string public state = 'Opened';

   constructor(){
        owner = payable(msg.sender);
   }
//mofifier que indica que solo el owner puede modificar el estado.
   modifier changeState(){
       require(owner == msg.sender, "solo el owner puede modificar el estado");
       _;
   }
  
   function stateFinally(string memory _state) public changeState{
       state = _state;
   }
//modifier que evita que el owner deposite en su propio proyecto.
   modifier onlyCommunity(){
       require(msg.sender != owner,"Los owners no pueden aportar a su propio proyecto");
       _;
   }
   function community() public onlyCommunity payable{
        owner.transfer(msg.value);
   }
}
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;
contract reto1{
    string public nameProject;
    string public projectState="open";
    address private owner;


     constructor(
         string memory _nameProject
     ){
         nameProject = _nameProject;
         owner=msg.sender;
     }
     modifier notOwnerfund(){
         require(
             msg.sender!=owner,"No puede depositar el owner"
         );
         _;
     }
     function fundProject(address payable direction)public payable notOwnerfund{
        direction.transfer(msg.value);
    }
    modifier onlyOwnerState(){
        require(
            msg.sender==owner,"No eres el owner"
        );
        _;
    }
    function changeProjectState(string memory _projectState) public onlyOwnerState{
        projectState=_projectState;
    }
}

RESUMEN CLASE 12:
MODIFICADORES
DE FUNCIONES

I.- FUNCTION MODIFIERS

  • Validan información al usar una función.

  • suelen llevar un require.

RETO 2:

// 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 state = "Opened";
    uint256 public funds;
    uint256 public fundraisingGoal;

    event ProjectFunded(string projectId, uint256 value);

    event ProjectStateChanged(string id, string state);

    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 isAuthor() {
        require(author == msg.sender, "You need to be the project author");
        _;
    }

    modifier isNotAuthor() {
        require(
            author != msg.sender,
            "As author you can not fund your own project"
        );
        _;
    }

    function fundProject() public payable isNotAuthor {
        author.transfer(msg.value);
        funds += msg.value;
        emit ProjectFunded(id, msg.value);
    }

    function changeProjectState(string calldata newState) public isAuthor {
        state = newState;
        emit ProjectStateChanged(id, newState);
    }
}

Así va quedando!

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract CreateProject {
    string public name;
    bool public isActive;
    address public owner;
    address payable ownerWallet;
    uint public totalFounded;

    constructor(string memory _name, bool _isActive){
        name = _name;
        isActive = _isActive;
        owner = msg.sender;
        ownerWallet = payable(msg.sender);
        totalFounded = 0;
    }

    modifier onlyOwner() {
        require(msg.sender == owner,
        "You aren't the owner of the project.");
        _;
    }

    modifier notOwner(){
        require(msg.sender != owner, 
        "You are the owner of the project.");
        _;
    }

    modifier onlyActive(){
        require(isActive, "The project isn't active.");
        _;
    }

    function fundProject() public payable notOwner onlyActive{
        ownerWallet.transfer(msg.value);
        totalFounded += msg.value;
    }

    function changeState(bool _newState) public onlyOwner{
        isActive = _newState;
    }

    function changeName(string calldata _newName) public onlyOwner{
        name = _newName;
    }
}

Agregados los modificadores. Antes había agregado los require dentro de las funciones.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Crowdfunding {

    address payable projectAddress;
    string projectName;
    uint256 fundraisingGoal;
    uint256 moneyReceived;
    bool isOpen;

    constructor (address payable _projectAddress, uint256 _fundraisingGoal){
        projectAddress = _projectAddress;
        projectName = "Crowdfunding";
        fundraisingGoal = _fundraisingGoal;
        moneyReceived = 0;
        isOpen = true;
    }

    modifier onlyOwner(){
        require(msg.sender == projectAddress, "Only owner can do this action");
        _;
    }

    modifier notOwnProject(){
        require(msg.sender != projectAddress, "Owner cannot fund his own project");
        _;
    }

    function fundProject () public notOwnProject payable{
        require(isOpen, "Crodwfunding is closed");
        require (moneyReceived + msg.value <= fundraisingGoal, "Fundarising is almost full. Fund with less money.");
        projectAddress.transfer(msg.value);
        moneyReceived = moneyReceived + msg.value;
    }

    function changeProjectState() public onlyOwner{
        isOpen = !isOpen;
    }

}

Modifiers

Parte 1

// Modifier to only the owner can change the state of the project
    modifier onlyOwner {
        require(msg.sender == author, "Only the owner can change the state of the project");
        _;
    }
    // Function to change the state of the project
    function changeState(string calldata newState) public onlyOwner{
        state = newState;
    }

Parte 2

// Modifier to evit that an author can apport to their own project
    modifier notAuthor {
        require(msg.sender != author, "You can't fund your own project");
        _;
    }    

    // Function to evit that an author can apport to their own project
    function fund(uint _amount) public payable notAuthor {
        funds += _amount;
    }

Con lo que llevamos visto hasta ahora y sin adelantar comparto mi solución, espero a alguien le pueda ayudar

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract crowdfunder {
    uint public goal;
    bool state;
    uint public funds;
    address owner;

    constructor(uint _goal, bool _state, uint _funds){
        goal = _goal;
        funds = _funds;
        state = _state;
        owner = msg.sender;
    }
    modifier onlyOwner{
        require(msg.sender == owner, "you need to be the owner to set the goal or change the state"); _;
    }
    modifier differentThenOwner{
        require(msg.sender != owner, "You cant fund your own proyect"); _;
    }
    function setGoal(uint Goal) public onlyOwner {
        goal = Goal;
    }
    function fundProyect(address payable receiver) public payable differentThenOwner returns(string memory message, uint total){
        if(funds < goal && state){
            funds += msg.value;
            total = funds;
            receiver.transfer(msg.value);
            message = "your founds have been received";
        }
        else {
            message = "we cant process your transaction";
            total = funds;
        }
    }
    function changeProjectState() public onlyOwner returns (bool status){
        state = !state;
        status = state;
    }
}

RESPUESTA

<// 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;
  
    constructor(
        string memory _name
        ){
            name = _name;
            isFundable = true;
            deposits = 0;
            depositsGoal=1000;
            autor = msg.sender; 
    }
      
    function viewDeposits() public view returns (uint){
        return deposits;
    }

    function viewRemaining() public view returns(uint256){
         return depositsGoal - deposits;
     }
    
    modifier notOnlyOwnerPay{
        require (autor != msg.sender, "El propietario no puede abonar fondos al proyecto" );
        //la funcion es insertada donde aparece este simbolo _
        _;
    }
    
    function fundProject(address payable benefactor) public payable notOnlyOwnerPay {     

        depositTest = deposits + msg.value;
       
        if (isFundable == true && msg.value>0 && depositTest <= depositsGoal) {
            benefactor.transfer(msg.value);
            deposits +=  msg.value;
        }
        else{
        changeProjectState();
        }
    }

    modifier ownerRequired {
        require (msg.sender == autor, "Esta accion es restringida al propietario.");
        _;
    }
    function changeProjectState() public ownerRequired {
       isFundable = !isFundable;
    }
}
> 

RETO 2

dejo mi ejemplo al reto 2

// 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";
uint256 public funds;
uint256 public fundraisingGoal;

// 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 {
    author.transfer(msg.value);
    funds += msg.value;
}


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

}

Los function modifiers permiten hacer validaciones antes de ejecutar una función, así podemos evitar comportamientos inesperados o que la función se ejecutada por alguien que no tenga los permisos para hacerlo.

En el codigo de ejemplo tenemos que en el constructor se guarda la dirección de quien lo despliega como owner. Solo el owner debe cambiar la variable de estado projectName.

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Permission {
    address private owner;
    string public projectName = "Platzi";

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can change the project name");
        //la función es insertada en donde aparece este símbolo
        _;
    }

    function changeProjectName(string memory _projectName) public onlyOwner {
        projectName = _projectName;
    }
}

Usamos la palabra “modifier” para definir el modificador, dentro de el llamamos a la función require, donde su primer parámetro es la condición que se va a validar, en nuestro caso validamos que el que ejecuta la función (msg.sender) es el owner. El segundo parámetro es un mensaje que se lanza en caso de que la validación falle.

El símbolo “;” identifica donde se insertara el código de la función. ¿Cuál función? La función que queremos validar con nuestro modificador. Es decir donde se encuentra “;” se insertaría el código de “changeProjectName”

Excelente clase, aveces se me hace bastante dificil enteder ya que soy totalmente nuevo en la programacion, pero la verdad es emocionante aprender y mas sobre smartcontracts 😄

Como comentario, creo que cuando eres nuevo lo mas dificil es es entender la funciones, variables y etc. hasta el punto que parece chino jajaja

Dejo mi ejercicio, usando un modifier y con un if directo en la función.
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract CrowdFunding {
string public idProject;
string public nameProject;
string public description;
address payable public author;
address private owner;
string public state = ‘Opened’;
uint public funds;
uint public fundraisingGoal;

constructor(string memory _idProject, string memory _nameProject, string memory _description, uint _fundraisingGoal){
    idProject = _idProject;
    nameProject = _nameProject;
    description = _description;
    fundraisingGoal = _fundraisingGoal;
    owner = msg.sender;
    author = payable(msg.sender);
}

modifier onlyOwner() {
  if (msg.sender == owner) {
     _;
  }
}

function fundProject() public payable {
    if (msg.sender != owner){
        author.transfer(msg.value);
        funds += msg.value;
    }
}

function changeProjectState(string calldata newState) public onlyOwner{
    state = newState;
}

}

// 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 state = "Opened";
    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");
         _;
    }

    function fundProject() public payable excludeOwner {
        author.transfer(msg.value);
        funds += msg.value;
    }

    function changeProjectState(string calldata newState) public onlyOwner {
        state = newState;
    }
}

Las validaciones que hice al contrato usando los modifiers:


  // Se valida que solo el autor pueda reaalizar ciertas operaciones en el contrato
     modifier onlyOwner {
         require(msg.sender == owner, "You need to be the owner from this contract to change the goalAmount");
         _;
     }
     
     // Se valida que el author no puede agregar fondos al proyeto
     modifier onlyOtherFunders {  
         require(msg.sender != owner, "The author of the contract can't fund the project");
         _;
     } 

Aqui el contrato

Mi código en respuesta al reto 2:

// 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 state = "Opened";
    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 chageState() {
        require(msg.sender == author, "Solo el autor puede cambiar el estado");
        _;
    }

    modifier canFund() {
        require(msg.sender != author, "El autor no puede invertir en su propio projecto");
        _;
    }

    function fundProject() canFund public payable {
        author.transfer(msg.value);
        funds += msg.value;
    }

    function changeProjectState(string calldata newState) chageState public {
        state = newState;
    }
}

Mi solución : D

// 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";
    address payable public author;
    uint public fundingGoal;
    uint public funds;

    //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 {
        author.transfer(msg.value);
        funds += msg.value;
    }

    //Crear la función que permita cambiar el estado del proyecto
    function changeProjectStatus(string calldata newStatus) public changeStatusRestriction {
        status = 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"
        );
        _;
    }

}

Mi solucion:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract CrowdFunding {
    string public id;
    string public name;
    string public descrition;
    address payable public author;
    string public state = "Opened";
    uint public funds;
    uint public fundraisingGoal;

    constructor(string memory _id, string memory _name, string memory _description, uint _fundtraisingGoal){
        id = _id;
        name = _name;
        descrition = _description;
        fundraisingGoal = _fundtraisingGoal;
        author = payable(msg.sender);
    }

    modifier onlyOwner(){
        require(
            msg.sender == author,
            "Only owner can change the project name"
        );
        // La funcion es insertada en donde aparece este simbolo
        _;
    }

    modifier differentFromOwner(){
        require(
            msg.sender != author,
            "Only owner can change the project name"
        );
        // La funcion es insertada en donde aparece este simbolo
        _;
    }

    function fundProject() public payable differentFromOwner{
        author.transfer(msg.value);
        funds += msg.value;
    }

    function changeProjectState(string calldata newState) public onlyOwner{
        state = newState;
    }

}

Este es mi avance del proyecto con los modifiers del reto #2:

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

contract Proyecto_Platzi{
    string public projectName;
    string public projectOwner;
    string public projectState = "Open";
    address payable ownerWallet;
    uint public goal;
    uint public currentFund;
    bool isOpenToFund;

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

    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
        _;
    }

    function fundProject() public payable differentToTheOwner{
        if(isOpenToFund == true){
        ownerWallet.transfer(msg.value);
        currentFund += msg.value;
        }
    }

    function changeProjectState(string calldata newState) public onlyOwner{
        if(msg.sender == ownerWallet){
            isOpenToFund = !isOpenToFund;
            if(isOpenToFund == true){
                projectState = newState;
            }
            else{
                projectState = newState;
            }
        }
    }
}

No me funciona el noSelfFunds()

// 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;
    bool public projectState = true; //por defecto abierto a recibir aporter
    uint public funds;
    uint256 public fundGoal; //define cuanto espero ganar con la ronda de levantamento de capital
    
    

    constructor(string memory _id, string memory _name, string memory _description, uint256 _fundGoal){
        id = _id;
        name = _name;
        description = _description;
        fundGoal = _fundGoal;
        author = payable(msg.sender); //msg.sender por defecto no recibe ETH pero la convertimos a 'payable'
        projectState = true;
    }


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

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


    //caulquier persona la puede ver y se puede enviar ETH sin problemas
    function fundProject() public payable noSelfFunds {
        
        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
    }

    //modifica el estado del proyecto. Calldata ahorra gas, solo existe cuando se le llama a la funcion
    function changeProjectState(bool newState) public onlyAuthor returns(bool){
        projectState = newState;
        return projectState;
    }

}

Permission.sol

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

contract Permission {
    address private owner;

    string public projectName = 'Solidity en Platzi';

    constructor(){
        owner = msg.sender;

    }

    //valida que el que ejecuta la funcion es el Owner del contracto 
    modifier onlyOwner() {
        require ( //require: 1er parametro la condicion que va a validad, 2do param mensaje cuando la validacion falla
            msg.sender == owner,
            'Only owner can change project name'
        );
        _; //el guion bajo identificara de donde se insertara el codigo de la funcion 
    }

    function changeProjectName(string memory _projectName) public onlyOwner{
        projectName = _projectName;
    }
}

No entendi mucho en el reto 1 pero ahora todo me queda mucho mas claro.

dejo mi codigo:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract crowdfounding {
    string public id;
    string public name;
    string public description;
    address payable public author;
    string public state = "Opened";
    uint public founds;
    uint public foundsGoal;

    constructor(string memory _id, string memory _name, string memory _description, uint _foundsGoal){
        id = _id;
        name = _name;
        description = _description;
        foundsGoal = _foundsGoal;
        author = payable(msg.sender);
    }

    modifier onlyAuthor(){
        require(
            msg.sender == author,
            "Only author can change the state"
        );
        //Modificacion por author
        _;
    }

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

    function fundProject() public payable noAuthorPay {
        author.transfer(msg.value);
        founds += msg.value;
    } 

    function changeProgectState(string calldata newState) public onlyAuthor {
        state = newState;
    }

}

RETO #2:

//SPDX-License-Identifier: GLP-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 state = 'Opened';
    uint public funds;
    uint public fundraisingGoal;
    
    constructor(string memory _id,
                string memory _name,
                string memory _description,
                uint _fundraisinGoal){
        id = _id;
        name = _name;
        description = _description;
        fundraisingGoal = _fundraisinGoal;
        author = payable(msg.sender);
                }
                
    modifier noauthor() {
        require(
            msg.sender != author,
            "Author cannot send money to his own project "
            );
            _;
                
    function fundProject() public payable {
        author.transfer(msg.value);
        funds += msg.value;
    }
    
     
    }
    modifier onlyauthor() {
        require(
            msg.sender == author,
            "Only author can change the project name"
            );
            _;
    }
    
    function changeProjectState(string memory _projectName) public  {
        projectName = _projectName;
    }
    
}

Pues este reto me gusto bastante. También por que por que me di cuenta que muchas veces la solución no es nada complejo, si no algo sencillo que mejora el proyeto:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.7 <0.9.0;

contract reto1 {
    
    string public id;
    string public name;
    string public description;
    address payable public author;
    string public state = "Opened";
    uint public dreamFounds;
    uint public totalFounds = 0;
    
    constructor(string memory _id, string memory _name, string memory _description, uint _dreamFounds) {
        id = _id;
        name = _name;
        description = _description;
        dreamFounds = _dreamFounds;
        author = payable(msg.sender);
    }
    
    modifier noAuthor() {
        require(author != msg.sender, "El author no puede enviar dinero a su propio proyecto");
        _;
    }
    
    function fundProject() payable public noAuthor{
        author.transfer(msg.value);
        totalFounds += msg.value;
    }
    
    modifier onlyAuthor() {
        require(author == msg.sender, "Solamente el propietario puede cerrar el contrato");
        _;
    }
    
    function changeProject(string calldata newState) public onlyAuthor{
        state = newState;
    }
}

Por lo que tengo entendido los strings son muy caros en GAS

Solución del reto nº 2, utilice el modifier dentro de la funcion para ahorrar lineas de codigo y funciona perfecto

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 state = 'Opened';
    uint public funds;
    uint public fundraisingGoal;
    
    constructor(string memory _id, string memory _name, string memory _description, uint _fundraisingGoal){
        id = _id;
        name = _name;
        description = _description;
        fundraisingGoal = _fundraisingGoal;
        author = payable(msg.sender);
    }
    
    modifier onlyOwner() {
        require(
            msg.sender == author,
            "Only author can change the project name");
            _;
    }
    
    function changeName(string memory _name) public onlyOwner {
        name = _name;
    }
    
    
    function fundProject() public payable  {
        require(
            msg.sender != author,
            "Author can't fund the project");
        author.transfer(msg.value);
        funds += msg.value;
    }
    
    function changeProyectState(string calldata  newState) public {
        state = newState;
    }
    
}

En pocas palabras le dije a la funcion que requiera que el inversor no sea el autor ( con esta operacion: != que limita exclusivamente al autor del contrato)

  modifier noAuthorFunds() {
        require(msg.sender != author, "The author can not fund the project");
        _;
    }
    
 
    function fundProject() public payable noAuthorFunds {
        author.transfer(msg.value);
        funds += msg.value;
    }
    
    modifier justAuthor() {
        require(msg.sender == author, "The project state can only be changed by the author");
        _;
    }

    function changeProjectState(string calldata newState) public justAuthor {
        state = newState;
    }
}

Me ayudo bastante esta clase para entender mejor como funciona el constructor.

Mi version utilizando function modifiers 💪

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

contract CrowdFunding {
    string projectName;
    string projectDescription;
    uint256 goal;
    bool isActive;
    uint currentFunds;
    address payable ownerWallet;
    address owner;
    
    constructor(string memory _projectName, string memory _projectDescription, uint256 _goal) {
        projectName = _projectName;
        projectDescription = _projectDescription;
        goal = _goal;
        currentFunds = 0;
        isActive = true;
        
        // Owner Information
        ownerWallet = payable(msg.sender);
        owner = msg.sender;
    }
    

    function sendFunds() public payable OnlyActiveProjects NotOwner {
        ownerWallet.transfer(msg.value);
        currentFunds += msg.value;
    }

    function changeFundStatus() public OnlyOwner {
        isActive = !isActive;        
    }
    
    modifier OnlyActiveProjects() {
        require(isActive == true, "Current project is not available!");
        _;
    }
    
    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(bool) {
        return isActive;
    }
    
    function getFunds() public view returns (uint) {
        return currentFunds;
    }
}

Los modificadores pueden tener la logica que queramos

Ojalá se pudieran dar Likes a estos cursos :')