Está en la página 1de 17

CURSO DE SOLIDITY

La importancia de la web3 y Solidity


https://github.com/anfepar/SmartContractsPlatzi
https://github.com/platzi/curso-solidity/tree/main/Contratos
https://solidity-es.readthedocs.io/es/latest/types.html
https://solidity-es.readthedocs.io/es/latest/types.html#mappings

https://solidity-by-example.org/call/
platzi.com/celo construyendo en Web3
https://docs.opensea.io/docs/metadata-standards
https://docs.soliditylang.org/en/v0.8.14/

https://www.tutorialspoint.com//solidity/index.htm
https://ethernaut.openzeppelin.com/
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/
token/ERC20/ERC20.sol
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/
token/ERC721/ERC721.sol

https://web3js.readthedocs.io/en/v1.2.11/web3-eth-abi.html#eth-abi
https://docs.ethers.io/v5/api/utils/abi/

sebastian
https://www.blockchainacademy.cl/enrol/index.php?id=10
https://twitter.com/sebaleoperez
}

CURSO
https://platzi.com/cursos/intro-dapps/

Más importante incluso que Solidity es la EVM (Ethereum Virtual Machine), por su
impacto cultural y tecnológico al implementarse en distintos blockchains.

Solidity es un lenguaje que compila hacia la EVM, por lo que es compatible con
redes como BSC, Polygon, RSK, TRON, etc.

// Version puede representar un rango. Ej >=0.7.0 <9.0.0


pragma solidity <version>;

// Declaración de un contrato, similar a una clase


contract <name> { // Name puede ser cualquier cosa

// Función de inicialización de un contrato


constructor() {
// Código de inicialización
}
}

Tipos de datos

int | uint <8-256>: Son números enteros, que pueden ser sin signo o con signo,
y que pueden tener una capacidad de 8 a 256 bits.
bool: Verdadero o flaso
address: Guarda direcciones de ETH de 160 bits (20 bytes), y puede tener
métodos extra como .transfer o .balance
string: Cadena de texto
bytes<8-256>: Cadena de bytes

Tipos de variables

Variables locales: Son aquellas que ocurren durante la ejecución. En la EVM es


la parte correspondiente a memoria volátil
Variables de estado: Son variables que se almacenan en la parte de la ROM de la
EVM. Es memoria persistente

Variables globales

msg: Toda transacción es un mensaje firmado. En este objeto vienen los datos de
dicho mensaje (sender, value, etc.)
tx: Represena la transacción, es distitna respecto a msg porque cosas como el
sender van variando conforme se concatenan llamadas entre contratos
block: Información respecto al bloque

Poner especial atención a la primer propiedad de block, ya que esa información irá
cambiando a lo largo del tiempo y no siempre seremos capaces de recuperarla (por lo
que no deberíamos depender de este dato en particular para alguna operación).

blockhash(uint blockNumber) returns (bytes32): hash of the given block when


blocknumber is one of the 256 most recent blocks; otherwise returns zero
block.basefee (uint): current block’s base fee (EIP-3198 and EIP-1559)
block.chainid (uint): current chain id
block.coinbase (address payable): current block miner’s address
block.difficulty (uint): current block difficulty
block.gaslimit (uint): current block gaslimit
block.number (uint): current block number
block.timestamp (uint): current block timestamp as seconds since unix epoch
gasleft() returns (uint256): remaining gas
msg.data (bytes calldata): complete calldata
msg.sender (address): sender of the message (current call)
msg.sig (bytes4): first four bytes of the calldata (i.e. function identifier)
msg.value (uint): number of wei sent with the message
tx.gasprice (uint): gas price of the transaction
tx.origin (address): sender of the transaction (full call chain)

//SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Estructura {

int cantidad;
uint cantidadSinSigno;
address direccion;
bool firmado;

constructor (bool estaFirmado) {


direccion = msg.sender;
firmado =estaFirmado;
}
Aqui la versión actualizada de la guia de estilos de solidity.
La recomiendo, asi se van familiarizando más con la terminología en inglés que
gobierna el mundo de la programación. Éxitos!!.
https://docs.soliditylang.org/en/v0.8.12/style-guide.html

Structs

Son estructuras de datos complejas, que agrupan una serie de datos.


struct <name> {
<type> <name>;
...
<type> <name>;
}

arreglos
override(Arreglos)

// Arreglos estáticos (n = cantidad de elementos)


<type>[n] <visibility> <name>;

// Arreglos dinámicos
<type>[] <visibility> <name>;

Funciones Array Dinámico

push: Se usa para adicionar elementos al final de un array


pop: Se usa para remover el último elemento de un array

uint[] data;
data.push(10);
data.push(20);
data.push(30);
// [10, 20, 30]

data.pop();
// [10, 20]

pragma solidity >=0.7.0 <0.9.0;

contract Clase {

struct Alumno {
string nombre;
uint documento;
}
Alumno [] public alumnos;

constructor() {
alumnos.push(Alumno({ nombre: "Kinam", documento: 12345 }));
}

MAPPINGS Y ENUMS

Mapas
Los mapas son estructuras de datos de tipo llave-valor, que permiten apuntar un
tipo de dato a otro en forma de diccionario.

El tipo de la llave puede ser cualquier tipo de dato elemental, (por ejemplo,
uint), y el tipo de dato del valor puede ser cualquier dato elemental o complejo,
(se pueden inclusive hacer estructuras multidimensionales)

mapping(<key type> => <value type>) <visibility> <name>;

Enum

Representa una lista de valores posibles creados por el usuario, una variable del
tipo de enum declarado sólo puede tomar los valores enumerados.

enum { <value1>, ..., <valueN> }

mapping: Es un tipo especial de arreglo llamados arreglos asociativos.

enum: Coleccion ordenada de valores, el primer elemento corresponde con el elemento


0 (cero).

Enum types

Las enumeraciones son la forma de crear tipos de datos definidos por el usuario,
generalmente se usa para proporcionar nombres para constantes integrales, lo que
hace que el contrato sea mejor para el mantenimiento y la lectura. Las
enumeraciones restringen la variable con uno de los pocos valores predefinidos

enum <enumerator_name> {
element 1, elemenent 2,....,element n
}

pragma solidity >=0.7.0 <0.9.0;

contract Saldo {

mapping(address => uint) public balance;

enum Estado { Iniciado, Finalizado }

Estado public estadoDelContrato;

constructor() {
estadoDelContrato = Estado.Iniciado;

balance[msg.sender] = 1000;

estadoDelContrato = Estado.Finalizado;
}

Estructuras de control
if/else: Estructura condicional. Ejecuta un bloque u otro dependiendo de una
evaluación booleana
for: Estructura cíclica que ejecuta un bloque de instrucciones un número
determinado de veces
while: Estructura cíclica que repite un bloque mientras se cumpla una condición
do while: Estructura cíclica que se asmilia al while, con la diferencia que
siempre se ejecuta almenos una vez

contract EstructuraDeControl {

uint[] public numeros;


string public resultado;

constructor(bool condicion) {
if (condicion) {
resultado = "Condicion True";
}
else {
resultado = "Condicion False";
}

for (uint iterador = 0; iterador < 10; iterador++) {


numeros.push(iterador);
}
}

EVENTOS

Los eventos son un tipo de dato que sirve para emitir avisos de que ocurrió alguna
acción en particular.

Puede ser utilizado por clientes para escuchar cambios importantes, y también
pueden utilizarse para indexar información.

Protocolos como TheGraph utilizan indexación de eventos para agregación de


información

contract Eventos {

uint[] public numeros;


string public resultado;

event NotificacionDeCondicion(bool condicion);

constructor(bool condicion) {
if (condicion) {
resultado = "Condicion True";
}
else {
resultado = "Condicion False";
}

emit NotificacionDeCondicion(condicion);

for (uint iterador = 0; iterador < 10; iterador++) {


numeros.push(iterador);
}
}

Permite conectar lo que pasa dentro de la Blockchain con el exterior porque a


tráves de un protocolo otras aplicaciones se pueden suscribir a ellos y escuchar
todo lo que está pasando en el Smart Contract.

Se usan para:

Registrar cambios que se hicieron


Feedback (Retroalimentación)

FUNCIONES

Funciones

Son piezas de código definidas por un nombre, parámetros y modificadores.

function <name>(<type> <parameter>..., [..., ]>)


<access modifiers>
<mutability modifiers>
<user defined modifiers>
<returns>(<type>) {
<content>
}

name: Nombre de la función


type: Tipo de dato
parameter: Nombre del parámetro
access modifier: public, private, internal, external
mutability modifier: view, pure. Ambas hacen que la función no cobre gas, y si
se omite, se asume que es una función que escribe en el storage de la EVM
user defined modifiers: Son modificadores definidos por el usuario, son
opcionales y se presentan en la siguiente clase
returns: Indica que la función retornará uno o más datos

Algunos puntos a pulir:

Las funciones pure. No leen ni modifican variables de estado y tampoco usan


ninguna variable global.
Existen funciones payable. Estas se usan cuando la función envía ether a alguna
dirección en la blockchain. Solo las funciones con tipo de retorno “payable” están
habilitadas para enviar ether.

Convenciones no obligatorias

En el desarrollo Solidity existe una convención no obligatoria y es que todos


los parámetros de una función empiecen con guión bajo.

function Suma( uint _numero1, uint _numero2 ) public pure returns (uint) {
return sumaInterna(_numero2, _numero2);
}

Tipos de función
public: son accesibles desde todo ámbito posible.
private: solo son accesibles desde el mismo contrato.
internal: solo son accesibles desde el mismo contrato y sus contratos
derivados.
external: solo accesibles desde fuera del contrato.

/ palabra clave o declaración - function


// nombre - Suma
// parámetros - ( uint numero1, uint numero2 )
// Modificador de acceso - public
// Tipo de función - pure
// Tipo de retorno - returns (uint)
function Suma( uint numero1, uint numero2 ) public pure returns (uint) {
return numero1 + numero2;
}

Un método no es lo mismo que un procedimiento…

Método es un término de la programación orientada a objetos, hace referencia a


una función que pertenece a una clase.

Una función devuelve un valor.

Un procedimiento ejecuta una serie de acciones (típicamente hace mutar las


variablesque definen el estado) y no devuelve nada.

¿Qué son las funciones en Solidity?

Las funciones son secciones de un programa que se encargar de ejecutar


instrucciones de forma independiente. Estas pueden recibir parametros para usarlos
dentro del código y pueden retornar una o más varibales. (Conocido como input y
output)

Tienen visibilidad al igual que las variables de estado, pueden ser.

Public: Totalmente accesible, sea cual sea el origen.


Private: Accesible únicamente a través de una función incluida en el mismo
contrato.
Internal: Accesible únicamente a través de otra función incluida en el mismo
contrato, o desde una función de un contrato que deriva del mismo. NO es accesible
desde un mensaje de un contrato externo o una transacción externa.
External: Accesible desde una cuenta de propiedad externa y a través de un
mensaje (llamada desde otro contrato). No es accesible desde una función del mismo
contrato o uno derivado del mismo.

MODIFICADORES

Los modificadores son funciones especiales por el usuario y que se añaden a otra
función para envolver su funcionamiento

modifier <name>(<type> <parameter>..., [,...]) {


<content>
}

La función revert() se utiliza para arrojar una excepción en nuestro smart contract
y revertir la función que la llama. Se puede agregar un mensaje como parámetro
describiendo el error.
modifier EsOwner() {
if (msg.sender != owner) revert("Solo el dueño del contrato puede
modificarlo.");
_;
}

Dentro de un modificador de función se puede añadir toda la lógica que necesitemos,


no se limita a una sola validación, se pueden usar estructuras require dentro de
las mismas:

require( msg.sender == owner, "Solo el propietario puede cambiar el nombre del


proyecto." );

EJEMPLO DE MODIFICADORES

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Modificadores {
//qureremos restrir que solo el que hizo el deploy del contrato

address private owner;

constructor() {
owner = msg.sender;
}

function Suma(uint numero1, uint numero2) public view EsOwner() returns(uint)


{
return numero1 + numero2;
}

modifier EsOwner() {
if (msg.sender!= owner) revert();
_;
}
}

Manejo de errores

assert: Se utiliza para pruebas, compara dos valores


revert: Es un error que regresa todas las modificaciones de estado realizadas
durante la ejecución de la función. Recibe por parámetro un mensaje de error
require: Es una variación del revert que recibe por parámetro una expresión
booleana y revierte si esta expresión es falsa.

Cabe destacar que cualquier consumo de gas ejecutado hasta el momento de un revert
se debe pagar, porque el cómputo fué utilizado

En este blog explica con ejemplos y descripciones el uso para cada uno de estos
tipos de manejo de errores. Aqui una pequena parte traducida:

Utilice require ():


Validar las entradas del usuario, es decir. require (entrada <20);
Validar la respuesta de un contrato externo, es decir. require (external.send
(cantidad));
Validar las condiciones estatales antes de la ejecución, es decir. require
(block.number> SOME_BLOCK_NUMBER) o require (balance [msg.sender]> = amount)
Generalmente, debe usar require con mayor frecuencia
Generalmente, se utilizará hacia** el comienzo** de una función.

Utilice revert ()

Maneja el mismo tipo de situaciones que require (), pero con una lógica más
compleja.
Si tiene algún flujo lógico anidado complejo if / else, puede encontrar que
tiene sentido usar revert () en lugar de require ().

Utilice assert ()

Compruebe si hay desbordamiento / subdesbordamiento, es decir.c = a + b;


assert(c> b)
Compruebe invariantes, es decir. assert (este.balance> = totalSupply);
Validar el estado después de realizar cambios
Prevenir condiciones que nunca deberían ser posibles.
Por lo general, probablemente usaráassert con menos frecuencia.
Generalmente, se utilizará hacia el final de una función.

Tipos de almacenamiento

Storage: Memoria persistente. Es el más costoso. Similar a la memoria ROM


Memory: Variables temporales durante ejecución. Se asimila a la RAM
Calldata: Son constantes definidas en el entorno de ejecución de una variable.
No son modificables.

Memoria dinámica

La razón por la que un string necesita un sufijo que indique el uso de memoria, es
debido a que es memoria dinámica, por lo que calldata no puede alocar una cantidad
definida de memoria, por lo que tenemos que indicarle que esa variable la pase por
la memoria volátil (RAM/memory), para que la función la pueda manejar
correctamente.

Este efecto ocurre con cualquier cosa que sea de tamaño no definido, por ejemplo:

Un arreglo
Un string

Storage:

Hace referencia a todos los datos guardados permanentemente en la blockchain. ¿Pero


cuáles son estos datos? Las variables de nuestro contrato que hayan sido declaradas
en el scope global fuera de cualquier método (función del contrato), a esto se le
denomina el ESTADO de nuestro Smart Contract. Puedes entenderlo como los datos del
disco duro de tu ordenador, solo que están en la blockchain, esto es,
descentralizados en millones de discos duros u otros dispositivos de almacenamiento
persistente (nodos).

Data Location
Storage: Queda guardada dentro de la blockchain, siempre vamos a poder obtener
el valor almacenado, pues este nunca se va borrar. Memoria Persistente.

Memory (Modificable): Solo existe mientras se llama una función y no podemos


acceder de nuevo a el dato. Temporales. Costo menor al STORAGE

Calldata: Solo existe mientras se llama la función.

Por defecto las variables de estado se almacenan en el storage y los parámetros en


memory.

Gas y comisiones

El gas es una unidad de medida para el procesamiento de la EVM. Se mide en unidades


de gas, y es constante para las mismas operaciones.

gasPrice: Es la cantidad de ETH que pagamos por unidad de gas. Es decir, aunque
el gas sea constante, la demanda por ese gas puede subir el precio.
gasCost: Es la cantidad de unidades de gas que generó la ejecución
gasFee: Gas cost * Gas Price

Priority fee

A partir del EIP1559 , se realizaron cambios importantes al mercado de gas, y se


contempla el priority fee, que es el extra que menciona Sebastián, y es una propina
para el minero con la cuál se obtiene prioridad en la ejecución

Me queda la duda con el concepto de gas fee, en la clase se explica que la formula
para el gas total es: GasTotal = Gas x GasPrice + GasFee. Entiendo ademas que el
gas fee es la comisión que se le paga al minero y esto puede variar según el uso de
la red. Si esto es correcto el gasFee NO es GasCost * GasPrice. En la siguiente
página se ve como cambia el gas fee https://crypto.com/defi/dashboard/gas-fees

Gas y comisiones

El gas es una unidad de medida para el procesamiento de la EVM. Se mide en unidades


de gas, y es constante para las mismas operaciones.

gasPrice: Es la cantidad de ETH que pagamos por unidad de gas. Es decir, aunque
el gas sea constante, la demanda por ese gas puede subir el precio.
gasCost: Es la cantidad de unidades de gas que generó la ejecución
gasFee: Gas cost * Gas Price

Priority fee

A partir del EIP1559 , se realizaron cambios importantes al mercado de gas, y se


contempla el priority fee, que es el extra que menciona Sebastián, y es una propina
para el minero con la cuál se obtiene prioridad en la ejecución

La fórmula que utiliza el profesor es una simplificación. Creo que los términos
utilizados igual no son los más correctos y eso generalmente es lo que causa
confusión.

Cuando hablamos de gasFee lo puedes interpretar de diferentes maneras

La cantidad de unidades de gas que costó. Este no es necesariamente ETH


La cantidad que le llega al minero. Este es REALMENTE el priority fee
La cantidad que el usuario paga en ETH. De este, una parte va al minero y el
otro se quema.

gasFee no es un término preciso porque tiene interpretaciones, de hecho no existe


en la EVM, lo correcto es:

En ETHEREUM con el EIP1559

BASE_FEE: Es el gasPrice del bloque. El EIP1559 sí establece un precio base


para el gas por bloque, que varía en base a la demanda. Este se quema
PRIORITY_FEE: Es el extra que se paga al minero por preferir tu transacción.
Este sí va al minero.

En cualquier otra EVM compatible blockchain sin EIP1559

GAS_PRICE: Cantidad de ether por unidad de gas.

Realmente utilizamos “fee” como una conveniencia para muchas cosas, como el
dashboard que compartiste. Pero formalmente no existe el término

Transferencia de ether desde un contrato

send: Envía un monto a una dirección y retorna false si la transferencia no se


realiza
transfer: Envía un monto y revierte si no se puede realizar
call: Esta es más complicada, pero básicamente realiza una llamada hacia una
dirección. Incluso se pueden llamar funciones de otro contrato si se le pasa un
address válido y la llamada dentro del parámetro data. No obstante, al ser un
mensaje, puede llevar ether, y por eso se usa para envíos. Retorna el resultado de
la función llamada (si es que fué el caso

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Transferencia {
constructor() payable {

function transferenciaPorSend(address destino,uint monto) public returns(bool)


{
bool salida = payable(destino).send(monto);
return salida;
}

function transferenciaPorTransfer(address destino, uint monto) public {


payable(destino).transfer(monto);
}

function transferenciaPorCall(address destino,uint monto) public returns(bool)


{
(bool salida, bytes memory respuesta) = destino.call{value:monto}("");
return salida;
}
}
Recibir ether desde un contrato

send Ether
|
msg.data esta vacia?
/ \
yes no
/ \
receive() existe? fallback()
/ \
yes no
/ \
receive() fallback()

Recibir Ether desde un contrato

Receive: Recibe el saldo de trasferencias sin parámetros.


FallBack: Recibe información adjunta a la trasferencia por medio de los
parámetros.
Función Payable: Se especifica el tipo payable a una función que puede recibir
trasferencias.

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Recepcion {

//trasferencia limpia sin parametros, puede recibir saldos


//y poder ejecutar codigo cuando se recibe saldo de transferencia limpia
mapping(address => uint) balances;
uint public saldoEnviado;

receive() external payable {


balances[msg.sender] += msg.value;
}

//funcion para recibir parametros que no corresponden a ninguna funcion en


particular
fallback() external payable {

//Funcion que es capaz de recibir saldo, no quiere decir que siempre reciba
// saldo

function recibirSaldo(uint numero) public payable {


saldoEnviado = msg.value;
uint monto =numero;

}
importaciones

LIBRERIAS
Manejo de dependencias y librerías

Importar una dependencia

Con la sentencia “import” podemos hacer referencia a un contrato que esté


definido en el mismo ámbito en el que estemos trabajando.
También podemos importar contratos que se encuentren en un repositorio o en un
paquete como npm.
Además de contratos podemos importar librerías que son similares a los
contratos, pero no contienen estado y solo brindan utilidad.

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract Importacion {

function sumarNumeros(uint numero1, uint numero2) public pure returns (uint) {


return SafeMath.add(numero1,numero2);
}

En el el caso de estar desarrollado tendríamos que tener instalado openzeppelin por


medio de npm.

En el caso de estar desarrollando en remix ya tenemos acceso a openzeppelin y


podemos importarlo directamente sin mayor problema.

En remix, cuidado al momento de hacer deploy y las referencias, el deploy siempre


buscara lo primero que encuentre en las referencias, para hacer deploy de nuestro
contrato debemos seleccionarlo

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract Importacion {

function sumarNumeros(uint numero1, uint numero2) public pure returns (uint) {


return SafeMath.add(numero1,numero2);
}

HERENCIA
Hola, para aclarar que Solidity sí es un lenguaje orientado a objetos, en la
documentación oficial lo definen así:

Solidity is an object-oriented, high-level language for implementing smart


contracts. Smart contracts are programs which govern the behaviour of accounts
within the Ethereum state.

“No hay que reinvetar la rueda”

Utilizamos la Herencia para reutilizar codigo en nuevos contratos. Solidity no es


POO, pero se comporta similar. Solidity es orientado a contratos. Identificaremos
con la sentencia is. Si un contrato tiene un constructor con parametros, debemos
indicar que valores debe tomar ese constructor para poder derivarse.

Entonces, se busca generar una relacion entre contratos para reutilizar el codigo
mediante la Herencia. Por lo que la capacidad de agregar/modificar una funcion ya
escrita en el contrato anterior nos sera de mucha utilidad.

Las funciones virtuales son funciones definidas para que se puedan reescrbir por
las funciones override. Para esto debemos establecer una relacion de Herencia. Si
una funcion virtual no define implementacion, el contrato se convierte en un
contrato abstracto. Tambien hay contratos abstractos que usamos como moldes vacios
para usar en futuros contratos.

Las interfaces no van a tener codigo. su funcion es indicarnos un comportamiento


que queremos que tenga un contrato. Solo tiene declaraciones (definiciones de
funciones) sin codigo.

super (sentencia) nos sirve para hacer referencia a una funcion de clase
superior.

Ejemplo practico: Buscamos 2 funciones virtuales en Modificadores📗 e Interface📘


para colocar en nuestro archivo/contrato de Herencia 📕📘📗.

Vamos a tener que importar el directorio de los demas contratos, en este caso se
encuentran en la misma carpeta los contratos. Coloco los emojis de libros para
hacer referencia a un contrato, si hay varios libros es porque es una Herencia que
contiene otros contratos.

/ SPDX-Licence-Identifier: UNLICENSED

pragma solidity >=0.7.0 < 0.9.0;

import "./Interface.sol";
import "./Modificadores.sol";

contract Herencia is Suma, Modificadores {

constructor(string memory nombreNuevo) Modificadores(nombreNuevo) {

function sumar(uint numero1, uint numero2) public override EsOwner() view


returns(uint) {
return numero1 + numero2;
}
}
Polimorfismo

Capacidad de poder utilizar contratos derivados en estructuras superiores.

Polimorfismo es una propiedad de la POO que permite (a nivel general digamos)


enviar mensajes iguales a objetos de diferentes tipos.

En limpio: tus objetos deben de “saber” responder al mensaje que les estás
enviando, esta es la propiedad polimórfica.

No tiene nada qué ver con contratos ni nada por el estilo, es puramente un tema de
objetos.

Qué es un token

‍n token es un objeto físico o digital que tiene valor en cierto contexto o para
U
determinada comunidad, aunque su propia materialidad no contenga ese valor en sí.

Las fichas de casino, por ejemplo, son solo pedazos de plástico de distintos
colores, pero representan cantidades de dinero. Algunas, hasta millones de dólares,
aunque fabricar una de ellas cueste apenas centavos.

Eso hacen los tokens: representan otra cosa, están en su lugar. ¿Por qué? Hay
muchos motivos: la comodidad, la seguridad, la facilidad de transportarlos o
transferirlos.

En el mundo cripto, los tokens se generan a partir de piezas de código de


programación, en formato de contratos inteligentes que corren sobre la blockchain.
El smart contract describe cómo funciona cada token. La base de datos lleva el
registro de cuántos tiene cada quien. Y los usuarios pueden enviárselos entre sí
como forma de transferirse valor.

ERC-20

Representa a los tokens fungibles


Solo define su Interface
Existen mas estándares pero mantienen compatibilidad con el ERC-20

ERC-20 OpenZeppelin

ERC-721

Representa a los tokens no fungibles. NFT


Solo define su Interface
Tienen un identificador único conocido como tokenId.

ERC-721 OpenZeppelin

TokenFungible.sol

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract TokenFungible is ERC20("TokenFungible", "TF") {

//Funcion mint es la que emite los tokens y pide una direccion y una cantidad
constructor() {
_mint(msg.sender, 1000);
}

OTRO EJEMPLO

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

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

contract TokenNoFungible is ERC721("TokenNoFungible","TNF") {

//Funcion mint es la que emite los tokens y pide una direccion y un


identificador
constructor() {

//tener la precaucion de siempre tener un ID que no se repita, unico


_mint(msg.sender, 1);
}

Application Binary Interface (ABI)

ABI

Application Binary Interface


Es una interface que nos detalla que definiciones tiene el contrato y sus
funciones, sin conocer su implementacion.
Nos permite saber la forma que tiene un contrato para poder interactuar con las
funciones.
ABI se presenta en formato JSON

Herramientas que gestionan el ABI

HardHat
Truffle

También podría gustarte