WEB3DEV Español

Cover image for Entiende cómo las direcciones se usan para transferir en/fuera del Contrato Inteligente
Hector
Hector

Posted on

Entiende cómo las direcciones se usan para transferir en/fuera del Contrato Inteligente

Un contrato inteligente es un contrato que se autoejecuta con los términos del acuerdo directamente escritos en el código. Estos contratos se ejecutan en la red blockchain y automáticamente imponen, facilitan o verifican la negociación o performance de un contrato, permitiendo transacciones con confianza y descentralizadas. Hay muchos artículos que explican qué es un contrato inteligente y cómo puede ser usado en los negocios del mundo real, por favor refiérete a Smart Contract - From beginning to engineering para tener más detalles.

En este artículo, no te diré los conceptos básicos sobre los contratos inteligentes. En cambio, te mostraré algo que confunde a las personas cuando empiezan a trabajar con los contratos inteligentes, especialmente codear en Solidity para transferir eth de ida y vuelta.

Dirección de la Cuenta

Una dirección de una cuenta blockchain usualmente referida como “dirección blockchain” o “dirección de la cartera”, es un identificador único usado en una red blockchain para enviar, recibir y almacenar activos digitales. Cada dirección corresponde a un usuario o entidad en particular en la blockchain. Una parte confusa es que puede que veas que puedes cambiar a una red Ethereum distinta a través de Metamask pero tu dirección de la cuenta es la misma, la cual es una larga cadena de caracteres alfanuméricos.

Las direcciones de cuentas blockchain no son las mismas entre las diferentes redes blockchain. Cada blockchain tiene su propio formato y estándares de dirección y las direcciones de una blockchain son, generalmente, no son válidas en otros.

Sin embargo, las direcciones de cuenta blockchain dentro de la red Ethereum (incluyendo sus diferentes forks y las redes compatibles) son usualmente las mismas o son compatibles porque comparten la misma tecnología, protocolos y métodos de generación de dirección subyacentes.

Image description

En el diagrama de arriba, la misma cuenta en la cartera conecta con 3 redes Ethereum distintas y obtiene el mismo valor de la dirección. El proceso de la generación de la dirección es el mismo que ethereum y todas las cadenas ethereum compatibles. Así que cuando creas una cuenta, metamask o cualquier otra cartera digital usa la misma frase semilla para generar la clave privada y luego, la clave privada generaría la misma dirección porque el proceso es exactamente el mismo.

Hay algunos casos de uso comunes para la dirección:

  • Enviar y Recibir Ether: Las direcciones Ethereum son principalmente usadas para enviar y recibir Ether, la criptomoneda de la red Ethereum.
  • Transacciones del Token: Las direcciones Ethereum también pueden ser usadas para enviar y recibir tokens, incluyendo estándares populares como los tokens ERC-20 y ERC-721.
  • Contratos Inteligentes: Las direcciones Ethereum son usadas para interactuar con los contratos inteligentes, Las transacciones para contratar las direcciones desencadenan la ejecución del código predefinido en la Máquina Virtual de Ethereum (EVM).
  • Aplicaciones Descentralizadas (DApps): Los usuarios usualmente usan sus direcciones Ethereum para acceder y usar aplicaciones descentralizadas (DApps) en la red Ethereum.

Direcciones del Contrato

Las direcciones del contrato y las direcciones de una cuenta son usadas en las redes blockchain, pero sirven otros propósitos y tienen características distintas.

Una dirección de contrato es asociada con un contrato inteligente desplegado en la blockchain. No está asociada con un individuo o entidad como una dirección de cuenta, pero representa el lugar donde un contrato inteligente reside en la blockchain.

Las direcciones del contrato son generadas basados en la transacción que despliega el contrato inteligente. La dirección es usualmente derivada desde la dirección de la cuenta del emisor y el nonce (un número que representa la cuenta de la transacción del remitente). Es determinístico y esto quiere decir que el mismo contrato desplegado por el mismo emisor siempre resultará en la misma dirección del contrato.

¿Cómo se usan esas direcciones en Solidity?

Entendemos que ambos, la cuenta individual y el contrato inteligente tiene las direcciones y la diferencia entre ellos. Llegó la hora de saber cómo usarlos en Solidity.

Puedes que veas el código de Solidity como:

function getContactBalance() public view returns (uint256) {
       return address(this).balance;
}
Enter fullscreen mode Exit fullscreen mode

La address es un tipo en Solidity y aquí convierte this a una dirección. this es una variable que representa el contrato actual. Su tipo es el tipo del contrato. Ya que cualquier tipo de contrato, básicamente hereda desde el tipo de dirección, esto siempre es convertible a la dirección y en este caso contiene su propia dirección.

El balance desde la dirección te da el balance para un contrato. Si, es un concepto interesante cuando escuchaste por primera vez que un contrato contiene ether en la blockchain.

Ahora veamos otro código de Solidity:

function getSenderBalance() public view returns (uint256) {
       return address(msg.sender).balance;
   }
Enter fullscreen mode Exit fullscreen mode

En Solidity hay variables y funciones especiales que siempre existen globalmente y son usadas principalmente para proporcionar información sobre la blockchain. msg es usualmente usada en los contratos de Solidity para las tareas como la verificación de la transacción y la interacción con los usuarios. Mira de nuevo el código de arriba, msg.sender nos da la dirección de la persona que llamó el método getSenderBalance en este contrato. Es actualmente la dirección de la cuenta en vez de la dirección del contrato. El balance es el mismo que el del balance de la dirección, como el ejemplo anterior.

Además del sender del objeto msg, hay otros campos útiles desde el msg que puedes usar en tu contrato:

  1. msg.sender: esta propiedad indica la cantidad de Ether (en wei) enviado junto a la transacción. Permite a los contratos inteligentes acceder al valor (Ether) adjunto a la transacción.
  2. msg.data: esta propiedad proporciona la carga útil de la transacción, el cual usualmente incluye el selector de la función y cualquier argumento para la funciones de llamadas hechas al contrato.
  3. msg.gas: esta propiedad especifica la cantidad de gas enviado con la transacción. El gas es usado para cubrir los costos computacionales y de almacenamiento para ejecutar las funciones del contrato.
  4. msg.gasprice: esta propiedad indica el precio de gas (en wei por unidad de gas) que el emisor está dispuesto a pagar para la ejecución de la transacción. Es usada para calcular la tasa de la transacción.
  5. msg.sig: esta propiedad contiene los primeros cuatro bytes del hash de la firma de la función y la función que fue llamada. Puede ser usada para identificar la función llamada dentro del contrato.

Los veremos en capítulos futuros, usados en algunos ejemplos.

Transferencia en/fuera de un Contrato Inteligente

En el mundo del contrato inteligente, no sólo una cuenta tiene un fondo (ether). Un contrato por sí mismo puede tener ether para algún propósito como el ejemplo mostrado en capítulos previos. Por ejemplo, los contratos inteligentes pueden ser usados para facilitar las campañas de recaudación colectiva (crowdfunding). Los contribuyentes envían Ether al contrato inteligente, el cual mantiene los fondos hasta que se alcance un objetivo de financiación predefinido o se llegue a un día límite. Si las condiciones se cumplen, los fondos se liberan al dueño del proyecto, si no son reembolsados a los contribuyentes.

Veamos el código de abajo como ejemplo para hacer el crowdfunding:

contract CrowdfundingEscrow {

 ...

 constructor() {
       projectOwner = msg.sender;
 }

 function contribute() public payable goalNotReached afterDeadline {
       require(msg.value > 0, "Contribution amount must be greater than zero");

       contributions[msg.sender] += msg.value;
       totalFunds += msg.value;

       emit FundingReceived(msg.sender, msg.value);

       if (totalFunds >= fundingGoal) {
           fundingGoalReached = true;
           emit FundingGoalReached(totalFunds);
       }
   }

 function withdrawFunds() public onlyOwner goalNotReached {
       uint256 amountToTransfer = totalFunds;
       totalFunds = 0;
       fundingGoalReached = false;

       payable(projectOwner).transfer(amountToTransfer);
       emit FundsTransferred(projectOwner, amountToTransfer);
   }

   function refundContributors() public goalNotReached afterDeadline {
       require(contributions[msg.sender] > 0, "You have not contributed to this project");

       uint256 refundAmount = contributions[msg.sender];
       contributions[msg.sender] = 0;

       payable(msg.sender).transfer(refundAmount);
       emit FundsRefunded(msg.sender, refundAmount);
   }
}
Enter fullscreen mode Exit fullscreen mode

Los contribuyentes pueden enviar Ether al contrato usando la función contribute. El contrato mantiene el rastreo de las contribuciones y si la meta de la financiación se alcanza, se desencadena el evento FundingGoalReached. Si la meta de la financiación no se logra para la fecha límite, los contribuyentes pueden solicitar un reembolso usando la función refundContributors.

Como puedes ver, el método transfer es usado en este ejemplo para transferir fondos a direcciones distintas. En el método withdrawFunds, llama a payable(projectOwner).transfer(amountToTransfer); para transferir desde el contrato a la cuenta del propietario del proyecto. En el método refundContributors, llama a payable(msg.sender).transfer(refundAmount); para transferir desde el contrato a la cuenta del contribuyente.

Sin embargo, no hay un método transfer llamado en el método contribute el cual, se supone que debería enviar los fondos desde el que llama al contrato. La cantidad que el contribuyente quiere enviar no se especifica tampoco desde el método del parámetro. La magia sucede en el msg.value el cual representa la cantidad que el llamante quiere enviar al contrato. Cuando el que llama invoca este método, necesita especificar el value como parte de la entrada de la transacción (revisa este artículo sobre cómo la transacción funciona en la red blockchain).

Para el frontend javascript, puede usar una biblioteca web3 para enviar la cantidad junto a la transacción del contrato, como se muestra en el ejemplo de abajo:

async function sendEtherToContract() {
   try {
       const contract = new web3.eth.Contract(contractABI, contractAddress);
       // Envía el ether al contrato
       await contract.methods.contribute().send({
           to: contractAddress,
           value: etherToSend,
       });
   } catch (error) {
       console.error('Error:', error);
   }
}
Enter fullscreen mode Exit fullscreen mode

Como puedes ver, el value: etherToSend es la cantidad enviada al contrato, el cual es igual al msg.value que puede accederse dentro del contrato inteligente.

Conclusión

En este artículo, discutimos sobre las diferencias entre las distintas cuentas y contratos inteligentes. También explicamos cómo usarlas y te mostramos cómo puedes retirar fondos desde el contrato y cómo puedes transferir fondos al contrato en un código simple de Solidity. Con suerte, puede que aclare confusiones para algunas personas que codean en los contratos inteligentes.

Referencias

Este artículo es una traducción de Joey Yi Zhao, hecha por Héctor Botero. Puedes encontrar el artículo original aquí.
Sería genial escucharte en nuestro Discord, puedes contarnos tus ideas, comentarios, sugerencias y dejarnos saber lo que necesitas.
Si prefieres puedes escribirnos a @web3dev_es en Twitter.

Discussion (0)