Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Integración y Desarrollo11 min de lectura

Estándar de Token ERC-721: Implementación, Verificación y Flujo de Trabajo Operativo

Una guía práctica para implementar, desplegar y verificar tokens ERC-721, incluyendo la mecánica de la interfaz, metadatos, seguridad en transferencias y procedimientos de diagnóstico.

TL;DR

ERC-721 es el estándar de Ethereum para tokens no fungibles, donde cada ID de token dentro de un contrato representa un activo único e individualmente rastreado. Este artículo explica la mecánica de la interfaz, recorre una implementación ejecutable y un flujo de trabajo de despliegue, y muestra cómo verificar la propiedad, las aprobaciones y las transferencias contra un endpoint RPC en vivo. También cubre el manejo de metadatos, la semántica de transferencia segura, fallos comunes de integración y las ventajas y desventajas entre ERC-721 y modelos alternativos de tokens.

Qué Representa un Token ERC-721

Un token ERC-721 es una entrada única en un contrato inteligente, identificada por un ID de token uint256. A diferencia de los tokens fungibles donde cada unidad es intercambiable, cada token ERC-721 tiene un propietario distinto y puede llevar metadatos distintos. El par de dirección de contrato e ID de token es globalmente único, lo que permite que billeteras, mercados y aplicaciones hagan referencia a un activo específico sin ambigüedad.

El estándar, finalizado como EIP-721 en enero de 2018, define una interfaz mínima para el seguimiento de propiedad, transferencias, aprobaciones y eventos. Se basa en ERC-165 para la detección de interfaz, de modo que los integradores pueden consultar si un contrato soporta ERC-721 antes de interactuar con él. El estándar no prescribe cómo se almacenan los metadatos ni qué significa un token; solo estandariza cómo se poseen y mueven los tokens.

  • balanceOf(address) devuelve cuántos tokens posee una cuenta.
  • ownerOf(uint256) devuelve el propietario actual de un token específico.
  • transferFrom y safeTransferFrom mueven la propiedad entre cuentas.
  • approve y setApprovalForAll delegan derechos de transferencia a operadores.
  • Los eventos Transfer, Approval y ApprovalForAll proporcionan un registro auditable.

Requisitos Previos y Suposiciones

Esta guía asume que tienes un entorno de desarrollo de Solidity con Foundry o Hardhat, acceso a un endpoint RPC compatible con Ethereum y una cuenta con fondos para el despliegue en una testnet. Debes estar cómodo con la sintaxis de Solidity, las llamadas JSON-RPC y las herramientas básicas de línea de comandos. Los ejemplos usan marcadores como RPC_URL y PRIVATE_KEY; nunca confirmes credenciales reales en el control de versiones.

Para la selección de endpoints, la descripción general de la API RPC de Ethereum explica cómo los servicios RPC gestionados difieren de ejecutar tu propio nodo. Si necesitas un entorno dedicado para despliegues repetidos o indexación, revisa las opciones de nodo dedicado y los precios de RPC antes de comprometerte con un proveedor.

Mecánica de la Interfaz y el Modelo de Propiedad

El modelo de propiedad ERC-721 es un mapeo de ID de token a dirección, más un mapeo de dirección a recuento de tokens. Las transferencias actualizan ambos mapeos y emiten un evento Transfer. Las aprobaciones se almacenan por token o por par propietario-operador. El estándar requiere que ownerOf revierta para tokens inexistentes, y que balanceOf revierta para la dirección cero.

Las transferencias seguras añaden una verificación: si el destinatario es un contrato, debe implementar onERC721Received y devolver el selector correcto; de lo contrario, la transferencia revierte. Esto evita que los tokens queden bloqueados permanentemente en contratos que no pueden manejarlos. La función no segura transferFrom omite esta verificación, por lo que debe usarse solo cuando estés seguro de que el destinatario puede gestionar el token.

Los metadatos son opcionales en el estándar base pero ampliamente esperados. La función tokenURI devuelve un URI que apunta a un documento JSON con campos de nombre, descripción e imagen. El URI puede estar en cadena, en IPFS o en un servidor HTTP. Los mercados suelen obtener este URI y renderizar el activo, por lo que la disponibilidad de metadatos afecta directamente cómo aparece un token a los usuarios.

Contrato ERC-721 Ejecutable con OpenZeppelin

El siguiente contrato utiliza OpenZeppelin Contracts, que proporciona implementaciones auditadas de la interfaz ERC-721 y extensiones comunes. Añade una función de acuñación solo para el propietario, un URI base y un contador de suministro. La llamada _safeMint asegura que si el destinatario es un contrato, pueda recibir el token.

Instala las dependencias con npm install @openzeppelin/contracts o el comando equivalente de Foundry, luego compila y despliega. El contrato es intencionalmente mínimo; los despliegues en producción deben añadir control de acceso, un suministro máximo y una estrategia de metadatos.

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

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

contract LearnNFT is ERC721, Ownable {
    uint256 private _nextTokenId;
    string private _baseTokenURI;

    constructor(string memory baseURI)
        ERC721("LearnNFT", "LNFT")
        Ownable(msg.sender)
    {
        _baseTokenURI = baseURI;
    }

    function mint(address to) external onlyOwner returns (uint256) {
        uint256 tokenId = _nextTokenId++;
        _safeMint(to, tokenId);
        return tokenId;
    }

    function _baseURI() internal view override returns (string memory) {
        return _baseTokenURI;
    }

    function setBaseURI(string calldata baseURI) external onlyOwner {
        _baseTokenURI = baseURI;
    }
}

Despliegue y Verificación con un Endpoint RPC en Vivo

Después del despliegue, verifica el contrato contra el explorador de bloques y confirma que el bytecode está presente en la dirección desplegada. Los siguientes comandos curl usan JSON-RPC para verificar el código y leer el nombre del token. Reemplaza RPC_URL y CONTRACT_ADDRESS con tus valores. El resultado de eth_getCode debe ser una cadena hexadecimal más larga que 0x, lo que indica bytecode desplegado.

Para leer el nombre del token, codifica el selector de función name() 0x06fdde03 y llama a eth_call. La respuesta está codificada en ABI; decodifícala con una biblioteca o un explorador de bloques. Si la llamada devuelve datos vacíos, el contrato puede no implementar la interfaz esperada o la dirección puede ser incorrecta.

curl -s -X POST "$RPC_URL" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":["CONTRACT_ADDRESS","latest"]}'

curl -s -X POST "$RPC_URL" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"eth_call","params":[{"to":"CONTRACT_ADDRESS","data":"0x06fdde03"},"latest"]}'

Procedimiento de Verificación y Resultados Esperados

Utiliza el siguiente procedimiento para confirmar que un contrato ERC-721 desplegado se comporta como se espera. Registra cada resultado en una tabla para que puedas comparar ejecuciones entre entornos. No asumas valores; mídalos contra tu propio despliegue.

VerificaciónMétodoResultado esperado
El código del contrato existeeth_getCodeCadena hexadecimal no vacía
Nombre y símboloeth_call a name() y symbol()Cadenas codificadas en ABI que coinciden con el despliegue
Propietario del token 0eth_call a ownerOf(0)Dirección del destinatario de la acuñación
Saldo del destinatarioeth_call a balanceOf(address)Número de tokens acuñados a esa dirección
Evento de transferenciaeth_getLogs filtrado por contrato y temaUn registro Transfer por transferencia
Soporte de interfazeth_call a supportsInterface(0x80ac58cd)true para ERC-721

Si alguna verificación falla, inspecciona el recibo de la transacción y el código fuente del contrato. Una causa común es desplegar en una red donde el contrato no fue realmente minado, o consultar un ID de cadena diferente al previsto. Confirma el ID de cadena con eth_chainId y compáralo con la red que esperas.

Transferencia Segura de Tokens desde JavaScript

El siguiente script de Node.js usa ethers.js para leer la propiedad y realizar una transferencia segura. Asume que el firmante posee el token y ha aprobado la transferencia si es necesario. El script espera el recibo de la transacción y luego vuelve a leer el propietario para confirmar el cambio de estado.

Siempre simula o estima el gas antes de enviar una transacción, y maneja las reversiones explícitamente. Una reversión en safeTransferFrom a menudo significa que el contrato destinatario no implementa onERC721Received, o que el llamador no está autorizado.

const { ethers } = require("ethers");

async function main() {
  const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
  const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
  const abi = [
    "function ownerOf(uint256) view returns (address)",
    "function safeTransferFrom(address,address,uint256)"
  ];
  const contract = new ethers.Contract(process.env.CONTRACT_ADDRESS, abi, signer);

  const tokenId = 0n;
  const before = await contract.ownerOf(tokenId);
  console.log("Owner before:", before);

  const tx = await contract.safeTransferFrom(before, process.env.RECIPIENT, tokenId);
  const receipt = await tx.wait();
  console.log("Mined in block:", receipt.blockNumber);

  const after = await contract.ownerOf(tokenId);
  console.log("Owner after:", after);
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});

Solución de Problemas Comunes de Integración ERC-721

La mayoría de los problemas con ERC-721 caen en unas pocas categorías: red incorrecta, aprobación faltante, receptor no compatible o fallo en la resolución de metadatos. Comienza confirmando el ID de cadena y la dirección del contrato, luego revisa el recibo de la transacción para ver el motivo de la reversión. Si el motivo de la reversión no se muestra, repite la llamada con eth_call en el bloque fallido para obtener un error más detallado.

Para problemas de metadatos, obtén el tokenURI directamente e inspecciona la respuesta. Si el URI apunta a IPFS, confirma que la puerta de enlace es accesible y que el CID es correcto. Si el URI está en cadena, decodifica la carga útil base64. Los mercados pueden almacenar en caché los metadatos, por lo que una actualización reciente podría no aparecer de inmediato.

Si ownerOf devuelve una dirección inesperada, verifica si el token fue transferido o quemado. Un token quemado debería hacer que ownerOf revierta. Si balanceOf es inconsistente con el número de tokens que esperas, verifica que los eventos de acuñación y quema coincidan con tus registros.

  • Reversión en transferencia: verifica aprobación, propiedad e interfaz del receptor.
  • Metadatos vacíos: verifica tokenURI y disponibilidad de la puerta de enlace.
  • Propietario incorrecto: confirma el ID de cadena y la dirección del contrato.
  • Eventos faltantes: consulta los registros con el rango de bloques y temas correctos.

Limitaciones y Compensaciones

ERC-721 está optimizado para la unicidad, no para la eficiencia por lotes. Cada token requiere almacenamiento y llamadas de transferencia separadas, lo que puede ser costoso a escala. ERC-1155 aborda esto al soportar múltiples tipos de tokens en un solo contrato, pero cambia el modelo de propiedad y eventos. Elige ERC-721 cuando cada activo deba identificarse y rastrearse individualmente; elige ERC-1155 cuando necesites operaciones semifungibles o por lotes.

El almacenamiento de metadatos es otra compensación. Los metadatos en cadena son permanentes pero costosos. IPFS está direccionado por contenido pero depende del anclaje y la disponibilidad de la puerta de enlace. Los metadatos HTTP son flexibles pero mutables y pueden desaparecer. No hay una única respuesta correcta; la elección depende de los requisitos de permanencia y el presupuesto.

Finalmente, el estándar no impone regalías ni el comportamiento del mercado. La aplicación de regalías es una convención del mercado, no una garantía del protocolo. Los integradores no deben asumir que un token generará regalías en cada venta.

Próximos Pasos para la Preparación en Producción

Antes del despliegue en la red principal, ejecuta el procedimiento de verificación en una testnet, añade pruebas exhaustivas para acuñación, transferencias, aprobaciones y metadatos, y considera una auditoría de terceros. Monitorea la confiabilidad y la latencia de tu proveedor de RPC, especialmente si planeas indexar eventos o servir metadatos a escala. La guía de endpoints RPC multicadena cubre patrones para trabajar en múltiples redes, y el directorio de redes lista las cadenas soportadas.

Si estás decidiendo entre RPC gestionado e infraestructura autoalojada, revisa la guía de alojamiento de nodos blockchain para consideraciones operativas. Para recomendaciones concretas de endpoints, el Asistente de RPC puede ayudarte a elegir un proveedor según tus requisitos de latencia y rendimiento.

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar