WEB3DEV Español

Cover image for Implementar Transacciones Inmobiliarias con Contratos Inteligentes en Solidity
Gabriella Alexandra Martinez Viloria
Gabriella Alexandra Martinez Viloria

Posted on

Implementar Transacciones Inmobiliarias con Contratos Inteligentes en Solidity

Image description

Me gustaría compartir cómo los contratos inteligentes pueden ser implementados en el negocio de las inmobiliarias para que aprendas y disfrutes. Creo que hay un potencial significativo para los contratos inteligentes en las transacciones inmobiliarias. Para este caso de uso simple, desarrollé tres escenarios distintos para ilustrar las interacciones básicas entre el propietario del contrato y los vendedores en el proceso de la transferencia de la tierra. Es esencial tomar en cuenta que las implementaciones de contratos inteligentes para la inmobiliaria puede que requieran consideraciones adicionales, medidas de seguridad e interacción de usuario más allá de estos escenarios simplificados. Sin embargo, para el alcance de nuestro tutorial, nos enfocaremos en los escenarios básicos proporcionados.

Escenario para el Contrato del Propietario

  1. Despliegue del Contrato: la gobernanza, como el propietario del contrato, despliega el contrato inteligente en la blockchain para crear un sistema de registro de tierra descentralizada.

  2. Adición de Tierra: el propietario del contrato añade tierras al contrato llamando la función addLand con el lugar y costo de cada tierra.

  3. Acuerdo de los Aprobadores: el propietario del contrato facilita el acuerdo entre los compradores y vendedores en un acuerdo común por cada tierra transferida, llamando a la función agreeOnApprover.

Escenario para el Comprador:

  1. Encontrar una Tierra: el comprador identifica una tierra disponible a la venta en el contrato, revisando los detalles de la tierra usando la función getLand.

  2. Acierto con un Aprobador: el comprador se comunica con el vendedor y ambas partes acuerdan un aprobador en común para la transferencia de tierra.

  3. Iniciar la Transferencia: el comprador llama la función initiateTransfer, proporcionandoel ID de la tierra y la dirección del aprobador acordado como argumentos.

  4. Aprobación: el comprador aprueba la transferencia, llamando la función approveTransferAsBuyer.

  5. Finalización de la Transferencia: si el vendedor también aprueba la transferencia, llamando la función approveTransferAsSeller, la transferencia se completa, y el propietario de la tierra se transfiere al aprobador.

Escenario para el Vendedor

  1. Verificación de la Propiedad: el vendedor confirma el propietario de la tierra, revisando el token representando la tierra y asegurándose que le pertenezca.

  2. Acuerdo con el Aprobador: el vendedor se comunica con el comprador y ambas partes acuerdan un aprobador en común para la transferencia de tierra.

  3. Iniciar la Transferencia: el vendedor llama la función initiateTransfer, proporcionando el ID de la tierra y la dirección acordada del aprobador como argumentos.

  4. Aprobación: el vendedor después aprueba la transferencia, llamando la función approveTransferAsSeller.

  5. Finalización de la Transferencia: si el comprador también aprueba la transferencia, llamando la función approveTransferAsBuyer, la transferencia se completa y el propietario de la tierra se transfiere al aprobador.

Este es el contrato inteligente en Solidity, que implementa los escenarios descritos:

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyLandContract is ERC721Enumerable, Ownable {
   struct Land {
       string location;
       uint cost;
       uint landID;
       uint wantSell;
       address approver;
       bool buyerApproved;
       bool sellerApproved;
   }

   uint public totalLandsCounter; // número total de tierras a través de este contrato

   mapping (uint => Land) public lands;

   constructor() ERC721("MyContract", "LAND") {
       totalLandsCounter = 0;
   }

   // Evento para añadir tierra
   event Add(address indexed _owner, uint _landID);

   // Evento para añadir tierra
   event Transfer(address indexed _from, address indexed _to, uint _landID);

   // Modificador para revisar si el que llama es el propietario de una tierra en específico
   modifier isLandOwner(uint _landID) {
       require(_exists(_landID), "Land with this ID does not exist");
       require(ownerOf(_landID) == msg.sender, "Caller is not the owner of this land");
       _;
   }

   // Modificador para revisar si el que llama es el aprobador acordado para una transferencia de tierra específica
   modifier isAgreedApprover(uint _landID) {
       require(_exists(_landID), "Land with this ID does not exist");
       require(lands[_landID].approver == msg.sender, "Caller is not the agreed approver for this land transfer");
       require(lands[_landID].buyerApproved == false && lands[_landID].sellerApproved == false, "Approval already given");
       require(lands[_landID].wantSell == 1, "Land is not available for sale");
       require(lands[_landID].cost <= msg.value, "Insufficient payment");
       _;
   }

   // El propietario añadirá tierras a través de esta función
   function addLand(string memory _location, uint _cost) public onlyOwner {
       totalLandsCounter++;
       uint landID = totalLandsCounter;
       lands[landID] = Land({
           location: _location,
           cost: _cost,
           landID: landID,
           wantSell: 1,
           approver: address(0),
           buyerApproved: false,
           sellerApproved: false
       });

       _mint(msg.sender, landID);
       emit Add(msg.sender, landID);
   }

   // El comprador y vendedor acuerdan el aprobador después de iniciar el proceso de la transferencia
   function agreeOnApprover(uint _landID, address _approver) public isLandOwner(_landID) {
       require(lands[_landID].approver == address(0), "Approver already set");
       lands[_landID].approver = _approver;
   }

   // El comprador aprueba la transferencia
   function approveTransferAsBuyer(uint _landID) public {
       require(lands[_landID].approver == msg.sender, "Caller is not the agreed approver for this land transfer");
       require(lands[_landID].buyerApproved == false, "Transfer already approved by the buyer");
       lands[_landID].buyerApproved = true;
       checkAndCompleteTransfer(_landID);
   }

   // El vendedor aprueba la transferencia
   function approveTransferAsSeller(uint _landID) public isLandOwner(_landID) {
       require(lands[_landID].sellerApproved == false, "Transfer already approved by the seller");
       lands[_landID].sellerApproved = true;
       checkAndCompleteTransfer(_landID);
   }

   // La función revisa si ambos, el comprador y el vendedor, han aprobado la transferencia
   // Si se aprueba, completa la transferencia
   function checkAndCompleteTransfer(uint _landID) private {
       if (lands[_landID].buyerApproved && lands[_landID].sellerApproved) {
           _transfer(ownerOf(_landID), lands[_landID].approver, _landID);
           lands[_landID].ownerAddress = lands[_landID].approver;
           lands[_landID].wantSell = 0;
           address payable seller = payable(ownerOf(_landID));
           seller.transfer(lands[_landID].cost);
           emit Transfer(ownerOf(_landID), lands[_landID].approver, _landID);
       }
   }

   // Obtén detalles de la tierra de una cuenta
   function getLand(uint _landID) public view returns (string memory, uint, address, uint, uint) {
       require(_exists(_landID), "Land with this ID does not exist");
       Land memory land = lands[_landID];
       return (land.location, land.cost, ownerOf(_landID), land.landID, land.wantSell);
   }

   // Remueve la tierra de la venta
   function removeFromSale(uint _landID) public isLandOwner(_landID) {
       lands[_landID].wantSell = 0;
   }
}
Enter fullscreen mode Exit fullscreen mode

Vamos a analizar el código para explicar las funciones mayores:

En primer lugar, el contrato hereda dos contratos OpenZeppelin importantes: ERC721Enumerable y Ownable. Aprovechando el estándar ERC-721, el contrato permite la creación de tokens únicos y no fungibles. Cada token sirve como una representación de una parcela distinta de tierra.

La función addLand garantiza al propietario del contrato (gobernanza), la habilidad para añadir tierras al contrato. Esta función se configura como pública y viene con el modificador onlyOwner, el cual asegura que sólo el propietario del contrato pueda usarlo. Cuando se invoca, la función requiere dos parámetros: _location (el lugar de la tierra) y _cost (el costo de la tierra).

Como parte del proceso, totalLandCounter se incrementan por uno para generar un landID único para la nueva tierra añadida. Una nueva estructura Land se crea, capturando los atributos proporcionados como lugar y precio, junto a las configuraciones por defecto para aprobador buyerApproved y sellerApproved.

Seguido de esto, la estructura Landrecientemente creada está incluida en el mapeo de las tierras usando landID como clave. Esto asegura que todos los detalles esenciales de la nueva tierra añadida sean almacenados de forma segura.

Para finalizar el proceso, la función _mint donde el ERC721 se llama para establecer un nuevo token ERC-721 que representa precisamente la tierra. La propiedad del token se atribuye al propietario del contrato (gobernanza), y todos los detalles pertinentes a la tierra son mantenidos de forma segura dentro del mapeo de las tierras. Esto permite que haya referencias futuras fluidas y la transferencia de tokens de tierra.

Finalmente, el evento Add se desencadena, notificando prontamente a los oyentes, que una nueva tierra ha sido exitosamente añadida al contrato. El evento contiene la dirección al propietario del contrato (msg.sender) y el landID de la tierra recientemente añadido.

Déjame explicar cómo la venta y transferencia del token de una tierra, funciona en un contrato inteligente:

  1. Añade la Tierra (Acordando con el Aprobador)

Digamos que un vendedor quiere vender su tierra a un comprador y ambas partes acuerdan en un aprobador antes de comenzar el proceso de la transferencia.

  • El vendedor llama la función agreeOnApprover y provee el landID de la tierra que quiere vender, junto a la dirección del approver acordado.

  • La función agreeOnApprover verifica que el que llama es el propietario de la tierra (el vendedor) y ejecuta el approver para esa tierra en particular.

  1. Iniciar la Transferencia (El Comprador Inicia la Transferencia)

Luego de acordar en el aprobador, el comprador toma la iniciativa para comenzar la transferencia de la tierra:

  • El comprador llama la función initiateTransfer y proporciona el landID de la tierra que quieren comprar, junto a la dirección del approver acordado.

  • La función initiateTransfer revisa si el que llama es el comprador y si la tierra está disponible para vender.

  • La función actualiza la marca buyerApproved para indicar que el comprador ha iniciado la transferencia.

  1. Aprobación desde el Vendedor y Comprador

Ambos el vendedor y comprador necesitan aprobar la transferencia antes que se pueda completar:

  • El vendedor aprueba la transferencia, llamando la función approveTransferAsSeller y proporcionando el landID.

  • El comprador aprueba la transferencia, llamando la función approveTransferAsBuyer y proporcionando el landID.

  1. Completando la Transferencia

Una vez que ambos, el comprador y el vendedor han aprobado la transferencia, la transferencia se completa:

  • La función checkAndCompleteTransfer invoca, revisando si ambos el buyerApproved y sellerApproved están configurados como verdaderos.

  • f aprueba que ambos sean verdaderos, la función transferencia el propietario de la tierra desde el vendedor acuerda al approver.

  • La marca wantSell para la tierra se ponga en 0, indicando que la tierra ya no está disponible a la venta.

  • El acuerdo con el approver toma propiedad del token de la tierra y el costo de la tierra se transfiere al vendedor.

De esta forma, el token de la tierra se vende exitosamente y se transfiere desde el vendedor al comprador, con la involucración del aprobador acordado.

En conclusión, el contrato inteligente presentado demuestra cómo la tecnología blockchain, a través del uso de Solidity y OpenZeppelin, puede ser aprovechada para implementar un sistema de registro de tierra descentralizado. El contrato utiliza el estándar ERC-721 para crear tokens únicos y no fungibles, cada uno representando una parcela distinta de tierra.

El dueño del contrato, típicamente una entidad del gobierno, tiene la autoridad de añadir tierras al contrato, facilitando la creación de un registro de tierra digital. Los compradores y vendedores interactúan con el contrato para iniciar las transferencias de tierras, y el aprobador acordado juega un rol crucial en la completación del proceso de la transferencia.

Mientras el contrato presentado aquí sirve como un ejemplo simplificado para propósitos educativos e ilustrativos, en los despliegues del mundo real, se debe tener mucha atención con la seguridad, auditabilidad y cumplimiento con las regulaciones relevantes, para asegurar la practicalidad y confiabilidad del contrato para manejar transacciones inmobiliarias.

En el futuro cercano, los contratos inteligentes tienen el potencial de revolucionar la industria inmobiliaria, ofreciendo transparencia, inmutabilidad y automatización en la transferencia de la propiedad de la tierra, simplificando y mejorando la eficiencia del proceso.

Si encuentras que esta información es útil, por favor considera apoyar y sígueme para más actualizaciones.

Este artículo es una traducción de Brian, hecha por Gabriella Martínez. 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)