Desde la introducción de la tecnología de contratos inteligentes, Solidity ha sido el lenguaje de codificación elegido por los desarrolladores de contratos inteligentes.
Sin embargo, si eres un desarrollador de Solidity, ya sabes que tiene inconvenientes. Entre otras fallas, pueden surgir importantes problemas de seguridad por el simple manejo indebido de ciertos tipos de datos, y no hay controles de acceso integrados.
Un nuevo lenguaje de contrato inteligente desarrollado para la cadena de bloques Flow, Cadence , aprende de los descuidos de Solidity y resuelve de forma nativa muchos de sus problemas inherentes. Y si ya conoce Solidity, ¡es fácil de aprender!
Este artículo presenta el lenguaje de contrato inteligente Cadence, detalla cómo mejora con respecto a Solidity y luego realiza una comparación lado a lado de ambos lenguajes en algunos ejemplos comunes de contrato inteligente. Al final, debería sentirse cómodo con Cadence y estar listo para comenzar con Flow.
Cadence es el lenguaje de programación que impulsa la cadena de bloques Flow, que fue creado originalmente por
Todo esto significa que Cadence está altamente optimizado para la creación y gestión de activos digitales .
La innovación más importante que introduce Cadence es su
Cadence mejora sobre Solidity de muchas maneras. Veamos tres ejemplos: pequeños errores de codificación, seguridad y control de acceso e implementación de contratos.
Algunos de los mayores problemas con Solidity generalmente surgen de los errores más pequeños. Por ejemplo, inicializar una variable con solo un valor predeterminado, aunque a veces es conveniente, puede generar resultados inesperados si esa variable no se cambia. Y los tipos de datos de rango fijo pueden conducir a situaciones potenciales de subdesbordamiento o desbordamiento, lo que sería desastroso si ese tipo de datos representa un valor monetario.
En Cadence, los valores de las variables deben establecerse en la inicialización, eliminando cualquier resultado no deseado de los valores predeterminados. Además, los números enteros en Cadence se verifican automáticamente en busca de condiciones de desbordamiento o subdesbordamiento, mientras que necesitaría heredar la biblioteca matemática segura de OpenZeppelin o usar una versión superior a 0.8 con Solidity.
Cuando se trata de seguridad y control de acceso, Solidity requiere que cree modificadores personalizados o herede otros contratos inteligentes basados en seguridad, pero también tiene muchas funciones que son públicas de forma predeterminada.
Con el modelo de seguridad basado en la capacidad de Cadence, las cuentas solo pueden realizar funciones a las que tienen acceso. Esto significa que Cadence tiene un control de acceso integrado fundamentalmente en el propio lenguaje. Además, los métodos definidos en objetos de recursos en Cadence no pueden ser susceptibles a ataques de reingreso, algo que los desarrolladores de Solidity deben tener muy en cuenta al crear el flujo de su lógica.
Cuando se encuentran problemas en los contratos inteligentes de Solidity, los desarrolladores no pueden solucionarlos sin implementar un contrato completamente nuevo. E incluso entonces, el contrato vulnerable todavía existe. Los desarrolladores deben asegurarse de que su base de usuarios cambie al nuevo contrato.
En Cadence, la capacidad de actualización de contratos inteligentes está integrada y es transparente. Cuando el código se declara seguro y definitivo, el contrato puede volverse inmutable quitando las claves al propietario del contrato inteligente.
En general, Cadence es un lenguaje de contrato inteligente más seguro que deja menos margen de error.
Ahora veamos en detalle las diferencias entre los contratos inteligentes escritos en Solidity y Cadence. Veremos un contrato Hello World simple y luego una implementación NFT más complicada.
Comencemos con un clásico de todos los tiempos. Todos hemos escrito "Hello World" en varios idiomas, por lo que es una introducción fácil a Cadence.
Vamos a repasarlo paso a paso.
Primero, tenemos la definición del contrato. La diferencia obvia es que el contrato Cadence tiene un modificador de control de acceso: en este caso, pub. Este modificador garantiza que todos en la red de Flow puedan acceder al contrato, el comportamiento predeterminado para los contratos de Solidity.
Sin embargo, en Cadence, también podríamos establecer el control de acceso en access(account)
. Esto limita el acceso al contrato a la cuenta que implementó ese contrato . Aquí ya vemos una gran diferencia entre Flow y Ethereum. No implementamos simplemente contratos en la cadena de bloques Flow; los desplegamos en el almacenamiento de nuestra cuenta. En la cadena de bloques Flow, cada cuenta se inicializa con almacenamiento, donde se pueden almacenar recursos y estructuras. Este almacenamiento tiene sus propios permisos, lo que nos permite un control detallado sobre quién puede ejecutar los métodos de nuestro contrato.
La siguiente línea define una variable de cadena en el ámbito de nuestro contrato. Los puntos y comas son opcionales en Cadence y se usa una palabra clave let
para definir la variable.
La cadencia tiene dos tipos de variables: mutables e inmutables. Las variables creadas con let
son inmutables, o conocidas como constantes; solo podemos configurarlos una vez y no se pueden cambiar durante la vigencia del contrato. Definimos variables mutables (aquellas que se pueden cambiar) con la palabra clave var
.
En este caso, establecemos el valor de la variable en el método init, porque Cadence garantiza que este método solo se llame una vez para cada implementación de contrato.
El equivalente de Cadence al constructor
de Solidity es el método init
. Este método se llama exactamente una vez, en el momento en que se implementa un contrato.
Dentro del método init, establecemos el valor de nuestra variable de saludo. Mientras que Solidity escribe en las variables del contrato de forma predeterminada, Cadence escribe en las variables locales y requiere que use el objeto propio para acceder a las variables del contrato. Esta decisión lo protege contra la escritura accidental en una variable de contrato al cometer un error tipográfico.
El segundo método de nuestro contrato devuelve la variable saludo. Tanto en Cadence como en Solidity, tenemos que declarar el acceso para que el método sea público, y ambos lenguajes requieren que definamos el tipo de retorno. En este caso, es una cadena.
Pero Solidity requiere que tengamos un nivel más bajo aquí. Requiere que le digamos explícitamente dónde se encuentra la cadena. También hace que marquemos las funciones como vistas, para que no modifiquemos accidentalmente el estado de la cadena de bloques.
La cadencia, por otro lado, no necesita ese control de bajo nivel, ya que tiene un tipo fuerte y estático. Los errores potenciales se detectan antes de que el programa se ejecute en la cadena, lo que hace que la declaración del método completo sea más legible al eliminar las palabras clave redundantes.
A continuación, veamos un contrato NFT básico de ambos idiomas:
Dado que ambos lenguajes tienen diferentes enfoques para este ejemplo, veámoslos por separado: primero analicemos el ejemplo de Solidity, luego Cadence.
En Solidity, una NFT es básicamente una lista de ID. Debe realizar un seguimiento de estos ID dentro del contrato inteligente e incrementarlos manualmente para garantizar la exclusividad. Solidity no sabe nada sobre los NFT o su singularidad. Es solo una lista de identificaciones asignadas a sus propietarios, todas administradas manualmente dentro del contrato. Esto deja margen para el error si el incremento de ID se maneja de forma incorrecta, lo que puede dar lugar a que varios NFT tengan ID idénticos.
En el ejemplo, el NFT no tiene datos adicionales adjuntos, pero podría agregar otro ID de mapeo a un URI. El contrato garantiza que cada NFT recién acuñado se asigne a la dirección de un propietario.
Este es un ejemplo simple, por supuesto. Por lo general, necesitará ampliar varias interfaces para obtener un contrato NFT seguro de forma remota y características como los metadatos utilizados para adjuntar los JPG conocidos a su NFT, pero los mecanismos básicos son los mismos.
Ahora, veamos la versión de Cadence y cómo mejora este ejemplo de Solidity.
El ejemplo de Cadence comienza con un tipo de recurso llamado NFT
. ¿Observe el símbolo @ delante de NFT
? Este símbolo es obligatorio, ya que garantiza que el uso y el comportamiento de los tipos de recursos seguirán siendo explícitos.
Podemos crear instancias a partir de un recurso y puede tener atributos como una estructura. La diferencia con una estructura regular es que un recurso es un tipo especial que maneja la propiedad además de los datos que almacena.
Dentro del tipo de recurso NFT
, hay un campo de identificación. El campo de id
es un número entero, UInt64
, y es una identificación única otorgada a cada recurso NFT. Esta id
será diferente para cada recurso NFT, lo que significa que el recurso no se puede duplicar ni combinar. A continuación, el campo id
se inicializa mediante la función init
.
De manera similar a cómo el verificador de préstamos de Rust garantiza que solo una función pueda modificar una variable, Cadence garantiza lo mismo para sus recursos.
Cuando creamos un nuevo recurso, tenemos que moverlo por las ubicaciones de almacenamiento. Nuestro contrato inteligente no funcionará correctamente si dejamos el recurso como está, por lo que esto nos obliga a ser cuidadosos con los recursos y sus ubicaciones de almacenamiento. Esta forma de control también asegura que los recursos nunca se pierdan o se eliminen accidentalmente; solo pueden estar en un lugar a la vez.
Cuando llamamos a la función mint, creará una nueva instancia de nuestro recurso NFT
. Esta función devuelve un recurso con un tipo de NFT
y toma el campo id
del recurso que se definió anteriormente. La palabra clave create
es un poco como el operador new en la programación orientada a objetos, creando un nuevo recurso. El <-
, u operador de movimiento, hace explícito que este recurso no está disponible en la fuente después de que lo llamamos.
La variable self.account
apuntará a la cuenta que usamos como destino de implementación para nuestro contrato. Como aprendimos antes: los contratos inteligentes no se implementan en un espacio de nombres global en la red Flow, sino en un almacenamiento especial en cadena que pertenece a su cuenta. Entonces, el contrato inteligente sabe en qué cuenta se implementó y puede usar esa información en sus métodos.
En este ejemplo, usamos el método de guardado de la cuenta. En la función de init
final, movemos el recurso al primer argumento de métodos de save
y le indicamos qué ruta dentro de la cuenta debe almacenar nuestro NFT.
Dado que nuestro NFT es un recurso, ninguna entidad en la red Flow puede copiarlo; no tenemos que hacer un seguimiento de su singularidad explícitamente.
Cadence es una nueva versión de los lenguajes de programación de contratos inteligentes, optimizada para la creación y gestión de activos. Es una alternativa moderna que mitiga las deficiencias de Solidity a través de medios como la gestión forzada de variables y recursos, seguridad y controles de acceso a un nivel básico y la capacidad de actualizar los contratos inteligentes antes de hacerlos inmutables. Cadence te abre a las posibilidades del ecosistema Flow e incorpora muchas funciones de lenguajes como Rust.
Entonces, si usted es un desarrollador que busca escribir contratos inteligentes en un lenguaje fundamentalmente más seguro, Cadence es una excelente opción. Para obtener más información, consulte la documentación de cadencia y el portal para desarrolladores de flujo .
¡Que tengas un gran día!