Entendiendo las funciones fallback y receive

En solidity la función fallback es ejecutada cuando ninguna de las otras funciones del contrato coincide con el “function identifier” enviado en la transacción. La función receive se usará para recibir ether y no se le puede pasar ningún dato. Si algún dato es enviado, fallback será llamado en vez de receive.

Si se llama a un contrato SIN datos, se llamará a la función receive.

Si se llama a un contrato CON datos, se llamará a la función fallback.

Propiedades de un fallback function:

  • Solo se puede definir uno por contrato.
  • No tiene argumentos.
  • Una función fallback para poder recibir ether debe estar marcada como payable. Si no lo está, la transacción fallará.
  • No puede devolver nada.
  • Es ejecutado si se llama a una función inexistente en el contrato.
  • Se debe marcar como external.
  • Si la llamada al contrato se hace desde otro contrato (con .send() o .transfer()), hay un limite de 2300 gas. Si se sobrepasa ese límite, la transacción fallará.

Vamos a ver cómo un contrato sin la función receive y con una función fallback devuelve un error si ésta no contiene la palabra clave payable.

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

contract FallbackReceiver {
    string public metodo;

    fallback() external {
     metodo = "fallback";   
    }
}

Para desplegar el contrato usaremos Hardhat. Primero crearemos el proyecto con el siguiente comando.

npx hardhat init

Ahora lo que haremos será ejecutar el nodo en local donde poder desplegar e interactuar con nuestros contratos

npx hardhat node

Por último solo nos falta desplegar el contrato. Primero crearemos el script de despliegue y una vez creado procederemos a desplegarlo.

async function main () {
    const FallbackReceiver = await ethers.getContractFactory('FallbackReceiver');
    console.log('Deploying FallbackReceiver...');
    const fallbackReceiver = await FallbackReceiver.deploy();
    await fallbackReceiver.deployed();
    console.log('FallbackReceiver deployed to:', fallbackReceiver.address);
  }
  
  main()
    .then(() => process.exit(0))
    .catch(error => {
      console.error(error);
      process.exit(1);
  });
npx hardhat run --network localhost scripts/deploy.js

Ejecutamos los siguientes comandos para enviar la transacción que fallará.

npx hardhat console --network localhost

const contrato = '0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6';

const FallbackReceiver = await ethers.getContractFactory('FallbackReceiver');
const fallbackReceiver = await FallbackReceiver.attach(contrato);

const [account1] = await ethers.getSigners();

await account1.sendTransaction({to: contrato, value: ethers.utils.parseEther("1.0"),});
reason: "Error: Transaction reverted: there's no receive function, fallback function is not payable and was called with value 1000000000000000000",

Usaremos el siguiente contrato para probar las funciones fallback y receive.

pragma solidity ^0.8.0;

contract FallbackReceiver {
    uint public cantidad;
    string public metodo;

    fallback() payable external {
     cantidad = msg.value;
     metodo = "fallback";   
    }

    receive() payable external {
     cantidad = msg.value;
     metodo = "receive";   
    }
}

Una vez desplegado el contrato, para probar la función fallback ejecutaremos los siguientes comandos conectándonos al nodo local.

const contrato = '0x610178dA211FEF7D417bC0e6FeD39F05609AD788';
const FallbackReceiver = await ethers.getContractFactory('FallbackReceiver');
const fallbackReceiver = await FallbackReceiver.attach(contrato);

const [account1] = await ethers.getSigners();
await account1.sendTransaction({to: contrato, value: ethers.utils.parseEther("1.0"),});

Para ver la cantidad recibida y función que se ha ejecutado, invocaremos las siguientes funciones.

await fallbackReceiver.cantidad();
await fallbackReceiver.metodo();

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *