Estás a punto de lanzar una colección de activos digitales en la red más popular para NFTs: Polygon (Mumbai). Para lograr ello se usará un contrato que implementa el estándar ERC721 con una cantidad de 2000 NFTs. Las estrategias para acuñación incluyen airdrop con lista blanca y compra directa.
Ethereum es la red más líquida en términos financieros. Hasta el día de hoy tiene el más alto total valor capturado (total value locked - TVL) en comparación con otros Blockchain. Tus clientes poseen sus dólares cripto (USDC) aquí. Dicha razón te motivó a crear una capa intermedia para poder realizar operaciones cross-chain.
Como parte de este lanzamiento, decidiste crear tu propio token llamado BBites Token - BBTKN. Lograr que este token adquiera un valor con el tiempo será clave para darle sostenibilidad al proyecto. Por eso decidiste que este token jugará un papel crucial al momento de adquirir los NFTs.
Una porción de los NFTs podrán ser comprados directamente en Ethereum (Goerli). Dado que el contrato de compra y venta de NFTs (Public Sale) solo recibe los tokens BBTKN y el usuario posee USDC, es necesario la creación de un pool de liquidez en Uniswap V2. Así, los compradores podrán intercambiar USDC por BBTKN y comprar los NFTs. También existe la modalidad de pagar directamente en USDC y dejar al contrato Public Sale que realice el swap internamente antes de comprar el NFT usando BBTKN.
Existen tres maneras de adquirir los activos digitales y son las siguientes:
- Usando
BBTKNoUSDC: Las compradores pueden dirigirse al contrato de compra y venta de NFTs (Public Sale) en la red Ethereum (Goerli) y usar los tokensBBTKNoUSDCpara adquirir NFTs. Los únicos tokens a la venta en esta modalidad van del id0al699(inclusivo) y tienen diferentes rangos de precio. Los tokensBBTKNse deducen de la billeterá del comprador y se transfieren al contratoPublic Sale. Se dispara un evento para que en Mumbai sea acuñado el NFT con el id que acaba de ser comprado. Si se usaUSDCpara pagar, internamente el contratoPublic Saleprimero convierte elUSDCa una cantidad exacta deBBTKN(usando Uniswap) para pagar por el NFT. - Usando
ether: Los tokens que van del id700al999(inclusivo) pueden ser comprados depositando0.01ether al contrato dePublic Sale. Si el usuario llama al métodopurchaseWithEtherAndId(uint256 _id) publicdel contratoPublic Sale, el usuario puede comprar dicho _id del rango mencionado si está disponible. Sin embargo, el usuario también puede optar por enviaretheraPublic Salesin ejecutar ningún metodo. En dicho caso, de manera aleatoria el contrato escoge un id disponible en el rango700a999(inclusivo). Este id que es adquirido medianteetherse envía en un evento a la red Polygon (Mumbai) para que se acuñe dicho NFT. - Usando una lista blanca: Los usuarios en la lista blanca pueden dirigirse a Polygon (
Mumbai) e interactuar con el contrato de NFTs para acuñar y saltarse el paso del pago en Ethereum (Goerli). Se han seleccionado 1000 billeteras para que cada una pueda acuñar un id en específico. El rango de id para esta modalidad va del1000al1999. Puedes revisar las billeteras que irán en la lista blanca en el archivo./wallets/walletList.js.
Tu proyecto ofrece la oportunidad recomprar los NFTs cuyos ids fueron parte de la lista blanca (no importa si el dueño ya no lo es). Estos usuarios pueden acercarse al contrato de NFTs en Polygon (Mumbai) y quemar su NFT usando el método buyBack(uint256 id) public y recibir una compensación. Al quemarse el NFT, se emite el evento Burn(address account, uint256 id) que finalmente, cross-chain, dispara una acuñación de 10,000 BBTKN en Ethereum (Goerli). De esta manera, tu proyecto propicia la deflación de los activos digitales.
Para asegurar la conveniencia del usuario y éxito de tu proyecto, has creado una arquitectura de contratos y middleware (Open Zeppelin Defender) que consta de las siguientes partes:
- Token ERC20 (llamado
BBites Token - BBTKN) - NFT ERC721 (usar coleccion de 2000 cuyes)
- Contrato de compra y venta (
Public Sale) USDC(stable coin)- Open Zeppelin Defender (Middleware)
Goerli=>MumbaiMumbai=>Goerli
- IPFS
- Pool de liquidez (par:
USDCyBBites Token- UNISWAP V2) - Front-end
Ethereum (Goerli) |
Polygon (Mumbai) |
|---|---|
BBites Token ERC20, USDC, Public Sale |
NFT ERC721 |
| Actualizables | No Actualizables |
|---|---|
BBites Token ERC20, NFT ERC721 y Public Sale |
USDC |
-
Este contrato es un ERC20 que debe ser convertido a actualizable. Posee 18 decimales. Es publicado en Ethereum (
Goerli) -
En el método
initialize(), usando_mint()se acuña 1 millón de tokens al que publica el contrato. Ese millón será utilizado para crear el pool de liquidez junto al USDC. -
Posee un método
mint(address to, uint256 amount) onlyRole(MINTER_ROLE)que solo es llamado por elRelayerde Open Zeppelin. Este método es disparado cuando desde Polygon (Mumbai) se quema un NFT cuyo id está entre1000y1999(inclusivo). Se acuña10,000tokens aladdressque quemó su NFT. -
Su método
mintposee el modifierwhenNotPausedpara pausarse cuando sea necesario. -
Bonus: Implementar la extensión
ERC20Permit. Aquellos compradores que no poseen gas para pagar la transacción crearán una firma digital para poner al contrato dePublic Salecomo el gastador de sus tokens. Esta firma digital podrá ser generada desde el front-end usando Metamask.Una vez generada la firma, se llamará a un autotask desde el front-end pasando los parámetros necesarios (e.g. firma). Este autotask usará un relayer en
Goerliy tendrá la tarea de llamarexecutePermitAndPurchase() public onlyRole(EXECUTER_ROLE)dePublic Sale. Este método hace lo siguiente:- Ejecuta el método
permit()del contrato ERC20PermitBBTokencon todos sus parámetros (owner,spender,value,deadline,v,rys) - Inmediatamente calcula un id aleatorio del tipo
mistico(explicado más abajo) cuyos ids van del700al999. - Emite el evento
PurchaseNftWithId(owner, randomId)
Reutiliza la misma función aleatoria para este tipo de NFT
mistico(ver cuarta modalidad de compra en el contratoPublic Sale). - Ejecuta el método
- Este contrato
Cuy Collection Nftimplementa el estándar ERC721 que debe ser convertido a actualizable. - Posee el método
safeMint(address to, uint256 tokenId) public onlyRole(MINTER_ROLE)que solo puede ser llamado por elRelayerde Open Zeppelin enMumbai. Los ids permitidos van del0al999para este método. Lleva el modifierwhenNotPaused. - Posee el método
safeMintWhiteList(address to, uint256 tokenId, bytes32[] proofs) publicque será llamado por cada una de las 1000 billeteras de la lista blanca. Internamente este método valida quetoytokenIdsean parte de la lista. Así también, se debe habilitar en el front-end una manera de solicitar las pruebas. Dado unaddressy unuint256, el front-end te entregará el array de pruebas a usarse como argumento de este método. LlevawhenNotPaused. Puede ser llamado por cualquiera. - Posee el método
buyBack(uint256 id) publicque permite a los dueños de los ids en el rango de1000y1999(inclusivo) quemar sus NFTs a cambio de un repago deBBTKNen la red de Ethereum (Goerli). Este método emite el eventoBurn(address account, uint256 id)que finalmente, cross-chain, disparamint()en el tokenBBTKNen la cantidad de10,000BBTKNs.
-
Este contrato de
Public Salese publica en Ethereum (Goerli). Sirve como intermediario para poder realizar el pago para adquirir NFTs. -
La comunicación entre el contrato de
Public Saley el contrato de NFTs se dará a través de Open Zeppelin Defender. El contrato dePublic Saleemite eventos que serán escuchados por Open Zeppelin Defender, que a su vez ordenará al contrato de NFT en Polygon (Mumbai) de acuñar un determinado NFT. -
Los ids para la venta usando
BBTKNoUSDCvan del0hasta el699y tienen diferentes rangos de precio. -
Se puede enviar
0.01 etherpara comprar NFTs en el rango de700 - 999. -
Los ids que van del
1000 - 1999solo se acuñan en Polygon (Mumbai) en el mismo contrato de NFTs usando la lista blanca (merkle tree). -
La siguiente tabla resume la información de ids vs tips vs precios.
id (inclusivo) Tipo Precio ( BBTKN)0 - 199Común 1000 BBTKNfijo200 - 499Raro Multiplicar su id por 20500 - 699Legendario Según días pasados***** 700 - 999Místico 0.01 etherfijo1000 - 1999Whitelist Sin precio *****Nota: Su precio cambia según el # de días pasados desde las 00 horas del 30 de septiembre del 2023 GMT (obtener el timestamp en epoch converter). El primer día empieza en
10,000 BBTKN. Por cada día pasado, el precio se incrementa en2,000 BBTKN. El precio máximo es90,000 BBTKN. -
La primera manera de compra es usando los
BBTKNtokens. El método a usar espurchaseWithTokens(uint256 _id)y el usuario escoge el id a comprar y se emite el evento. Estos tokens se transfieren al contratoPublic Sale. Aplica para ids en el rango0 - 699. -
La segunda manera de compra es usando
USDC. El método a usar espurchaseWithUSDC(uint256 _id)y el usuario escoge el id a comprar y se emite el evento. Internamente, en este método se usa el pool de liquidez para intercambiar losUSDCpor una cantidad exacta deBBTKN. Aplica para ids en el rango0 - 699. Dado que no se sabe la cantidad deUSDCa depositar, se sugiere dar elapprovede un monto seguro por parte del usuario. Este método tiene que dar el vuelto delUSDCque no se llegó a usar en la compra.BONUS: Para obtener un estimado de cuántos
USDCse necesitan para comprar una cantidad exacta deBBTKN, revisar getAmountIn de Uniswap. El usuario, antes de comprar bajo este método, puede consultargetAmountIny dar elapproveen dicha cantidad deUSDCestimada. ExponergetAmountInen este contrato. -
La tercera manera de compra es enviando exactamente
0.01 ethery ejecutando, al mismo tiempo, el métodopurchaseWithEtherAndId(uint256 _id). El usuario escoge el id a comprar y se emite el evento. Aplica para ids en el rango700 - 999. Eletheres acumulado en el mismo contratoPublic Sale. Dar vuelto si se envía más de0.01 ether. -
La cuarta manera de compra es enviando exactamente
0.01 etheral contrato sin ejecutar ningún metodo. Aleatoriamente se escoge un id de NFT que esté disponible y se emite el evento. Aplica para ids en el rango700 - 999. Eletheres acumulado en el mismo contratoPublic Sale. -
El evento que se emite luego de realizar cualquier compra tiena la siguiente forma:
event PurchaseNftWithId(address account, uint256 id). -
El método llamado
withdrawEther() public onlyRole(DEFAULT_ADMIN_ROLE)permite a cualquier admin transferirse eletherque fue depositado a este contrato. -
El método llamado
withdrawTokens() public onlyRole(DEFAULT_ADMIN_ROLE)permite a cualquier admin transferirse los tokensBBTKNque fueron depositados a este contrato. -
Construir un método de ayuda que devuelve el precio dado un id. Este método se llamará
getPriceForId(uint256 id) public view returns(uint256). Solo aplica para ids en el rango0y699(inclusivo).
- Encontrarás una réplica del stable coin
USDCen el repositorio. Al desplegarlo, elmsg.senderse hace acreeder de500,000 USDC. Esta cantidad es usada para crear el pool de liquidez junto alBBTKN. - Este contrato no es actualizable y se publica en Ethereum (
Goerli) - Inicialmente este contrato es de 18 decimales. Debes convertirlo a un token de 6 decimales como lo es el original
USDC. - Puedes repartir
USDCa cualquier comprador para que simule la posesión de fondos. Normalmente, este stable coin es adquirido en DEXes como Binance, KuCoin y otros.
De Ethereum (Goerli) a Polygon (Mumbai):
- El sentinel (
Goerli) escucha los eventosPurchaseNftWithIddePublic Sale. El autotask ejecuta el script que acuña el NFT en Polygon (Mumbai) en el contrato de NFT. El relayer (Mumbai) será el único que puede firmar el métodosafeMint()del contrato NFT para acuñar el id a la billetera respectiva. El relayer debe tener el rol deMINTER_ROLEpara poder acuñar.
De Polygon (Mumbai) a Ethereum (Goerli):
- El sentinel (
Mumbai) escucha los eventosBurndel contratoNFT. El autotask ejecuta el script que acuña10,000 BBTKNenGoerlien el contrato del tokenBBTKN. El relayer (Goerli) será el único que puede firmar el métodomint()para acuñarBBTKNa la billetera respectiva. El relayer debe tener el rol deMINTER_ROLEpara poder acuñar.
- Dentro de la carpeta
ipfstenemos dos carpetas:imagesymetadata. Estas dos carpetas representan a los activos digitales y la metadata, respectivamente. - Guardar la carpeta de
imagesde activos digitales en la aplicación de escritorioIPFS. Obtener elCIDluego de guardar la carpetaimages. - Dentro de la carpeta de
metadata, se encontrarán los archivosjsonenumerados de manera secuencial. Cada archivojson, representa la metada de un activo digital en particular. Por ejemplo, el archivo0, representa la metadata del activo digital0.png, guardada en la otra carpetaimages. - Vamos a modificar los archivos de
metadata. Por ejemplo, empecemos con./metadata/0. Buscar la propiedad"image": "ipfs://QmWJ3udcvB2XjvgWjcn8YrC7w8VEL2VWaUMq1x6Ns4t29k/0.png". Reemplazar por el valor delCIDobtenido en el punto 2 para todos los archivos. Usactrl + shift + h. - Así también cambia la propiedad
descriptiony escoge un nombre apropiado para tu colección. Usactrl + shift + h. - (Opcional) Dado que hay cinco grupos diferentes de NFTs, modificar el atributo
namede cada archivojsonpara que represente más apropiadamente al grupo de NFT al que pertenece. - (Opcional) Agregar más atributos en la propiedad
attributes. Seguir la guía/estándar definido en la página de Open Sea que lo puedes encontrar aquí. Estos atributos serán vistos en la galería de Opean Sea. - Luego de terminar de editar los archivos de metadata, guardar la carpeta
metadataenipfspara poder obtener elCID. - Finalmente, este
CIDes el que se guardará en el smart contract de NFT en el método_baseURI(). Gracias a este método, el smart contract puede encontrar la metadata y el activo digital en elIPFS.
- Se creará un pool de liquidez en Uniswap V2 usando los tokens
USDCyBBTKN. Dicho pool estará conformado por 1 Millón de tokensBBTKNy medio millón del tokenUSDC. - Acuñar
100,000 USDCa la siguiente billetera para propósitos de testing:0xF90a9359f2422b6885c900091f2aCc93E0933B7a. - Desde el contrato de
Public Salese establecerá una comunicación con elRouterde Uniswap para intercambioUSDCporBBTKNy realizar la compra del NFT con su precio respectivo
Crear un front-end minimalista para poder interactuar con el contrato de Public Sale (ver video). En este front, se podrán realizar las siguientes operaciones:
- Botón conectar a Metamask
- Ver cuenta conectada
- Observar el Balance
USDCde la billetera conectada - Observar el Balance
BBTokende la billetera conectada
- Dar approve de
BBTKNal contrato dePublic Sale - Dar approve de
USDCal contrato dePublic Sale
- Comprar un NFT usando el método
purchaseWithTokens - Comprar un NFT usando el método
purchaseWithUSDC - Comprar un NFT usando el método
purchaseWithEtherAndId - Comprar un NFT enviando
etheral contratoPublic Salesin ejecutar métodos - Consultar el precio de un NFT dado su id
- Dados un
idybilletera, consultar losproofs� para el whitelist - Usando
billetera,token idyproofs, acuñar NFT de whitelist - Ejecutar Buy Back quemando el NFT usando el
token id
- Public Sale
- PurchaseNftWithId
- Bites Token
- Transfer
- NFT contract
- Transfer
- Burn
- Token ERC20
BBITES Token - BBTKN - Contrato NFT
ERC721con una colección de 2000 cuyes - Contrato de
Public Sale - Stable Coin
USDCficticio - Autotask:
GoerliaMumbai. Incluye código engoerliToMumbai.js. - Autotask:
MumbaiaGoerli. Incluye código enmumbaiToGoerli.js. - Pool de liquidez en Uniswap V2
- Front-end con los métodos implementados del punto
8 - Front-end - Testing con alta cobertura para
Public Sale - Testing con alta cobertura para
ERC721 - Script de deployment para contratos en
Goerli - Script de deployment para contratos en
Mumbai
- Pega aquí la tx de una compra de un NFT
comúnenPublic SaleusandoUDSC: 0xe9b7f9d64f568081683c28f814c219ea232137d7519cd106e25a34018f4a478e - Pega aquí la tx de una compra de un NFT
raroenPublic SaleusandoBBTKN: 0xbc430c83b9d1965393eb422f876e5e149c0dcced8bc867ce56a7c19a27976cf4 - Pega aquí la tx de una compra de un NFT
legendarioenPublic SaleusandoUDSC: 0x124716b2f3e77cd35983f8280d520500b3e5dcdd656e53bb68e4f731f374ab9b - Pega aquí la tx de una compra de un NFT
misticoenPublic Saleusandoethery uniden específico: 0x4b3eb6f3415fe4d2fbd2beae0b48ddaf5d01beb523537df5c10dd3e308aa6723 - Pega aquí la tx de una compra de un NFT
misticoenPublic Saleusandoether(random id): 0x4525030102072da3762892161db48481da6ecb9c9d19e8d46f1de6cf329c5d4e - Pega aquí la tx de una acuñación whitelist de un NFT en el contrato
NFT: 0x00341499b8bc7eb184de789f8d895486399c2ecd8edb2821073eb369bb398213 - Pega aquí la tx de un buy back de NFT en el contrato
NFT: 0xfe8dfd1d665e82194700752e4f917ca90ec8e2236d1c67bc7885654e504daf85
