Los contratos inteligentes son inmutables una vez implementados en la cadena de bloques, lo que significa que no se pueden modificar. Por lo tanto, cualquier error o vulnerabilidad de seguridad puede tener consecuencias graves, lo que hace que las pruebas sean un paso indispensable en el proceso de desarrollo.
En esta lección, analizaremos el contrato Fa1_2TestFull
, que incluye una serie de pruebas diseñadas para verificar la funcionalidad de nuestro contrato de token.
Fa1_2TestFull
El contrato Fa1_2TestFull
es una clase que hereda todas las funcionalidades de los diferentes contratos como Admin, Pause, Fa1_2, Mint, Burn y ChangeMetadata. Se utiliza para agregar todas estas funcionalidades y realizar una prueba exhaustiva para garantizar que el contrato funcione como se esperaba.
Python
clase Fa1_2TestFull(Admin, Pause, Fa1_2, Mint, Burn, ChangeMetadata):
def __init__(auto, administrador, metadatos, libro mayor, token_metadata):
ChangeMetadata.__init__(yo)
Quemar.__init__(yo)
Menta.__init__(yo)
Fa1_2.__init__(yo, metadatos, libro mayor, token_metadata)
Pausa.__init__(yo)
Administración.__init__(yo, administrador)
El constructor de la clase Fa1_2TestFull
inicializa todas las funcionalidades.
Para nuestro contrato, comenzamos configurando el escenario de prueba con cuentas de prueba y la inicialización del contrato. Esto se hace dentro de una función de prueba decorada con @sp.add_test
.
Python
@sp.add_test(name="FA12")def test():
# Inicializa el escenario de prueba y las cuentas
sc = sp.test_scenario(m)
admin = sp.test_account("Administrador")
alicia = sp.test_account("Alicia")
bob = sp.test_account("Roberto")
# Inicializar contrato con algunos valores iniciales
token_metadata = {
"decimals": sp.utils.bytes_of_string("18"), # Mandatory by the spec"name": sp.utils.bytes_of_string("My Great Token"), # Recommended"symbol": sp.utils.bytes_of_string("MGT"), # Recommended# Extra fields"icon": sp.utils.bytes_of_string("https://smartpy.io/static/img/logo-only.svg"),
}
contract_metadata = sp.utils.metadata_of_url("ipfs://QmaiAUj1FFNGYTu8rLBjc3eeN9cSKwaF8EGMBNDmhzPNFd")
c1 = m.Fa1_2TestFull(administrador=admin.address,metadata=contrato_metadata,token_metadata=token_metadata,ledger={},)
sc += c1
Definimos las cuentas de prueba: Admin, Alice y Bob. Luego inicializamos nuestro contrato, Fa1_2TestFull
, con algunos valores iniciales. El operador +=
agrega el contrato al escenario.
De ahora en adelante, para ayudarlo a comprender mejor el código, el código estará a la izquierda y una visualización de la línea de código resaltada estará a la derecha. Ejemplo aquí:
El siguiente paso es ejecutar pruebas, lo que implica activar diferentes funciones del contrato y verificar los resultados.
Por ejemplo, para probar la funcionalidad de acuñación, ejecutamos:
Python
sc.h2("El administrador acuña algunas monedas")
c1.mint(dirección=alice.address, valor=12).run(remitente=admin)
Esta línea ejecuta una prueba en la que el administrador acuña 12 tokens para Alice. Si la función acuña correctamente los tokens y actualiza correctamente el saldo de Alice, entonces esta prueba pasa.
SmartPy proporciona el método verify
para garantizar que una condición sea verdadera. Si no se cumple la condición, la prueba fallará. Por ejemplo:
Python
c1.update_metadata(key="", valor=sp.bytes("0x00")).run(sender=admin)
sc.verify(c1.data.metadata[""] == sp.bytes("0x00"))
Esas líneas verifican que los metadatos del contrato se actualizaron correctamente a "0x00"
. Si no se actualizó correctamente, la prueba falla.
Las pruebas de sus contratos inteligentes deben cubrir todos los casos de uso posibles, incluidos los casos extremos y las posibles fallas. Estos pueden incluir transferencias que excedan el saldo de un usuario, quema de tokens cuando el contrato está en pausa, etc.
Por ejemplo, una prueba de transferencia fallida podría verse así:
Python
sc.h2("Bob intenta transferirse de Alice pero no tiene su aprobación")
c1.transfer(from_=alice.address, to_=bob.dirección, valor=4).run(remitente=bob, válido = falso)
Aquí, Bob intenta transferir 4 tokens de la cuenta de Alice sin tener aprobación. Dado que esta operación debería fallar, configuramos valid=False
en la función run
. Si el contrato impide correctamente la transferencia, se supera la prueba.
Las pruebas son cruciales en el desarrollo de contratos inteligentes. Dada la naturaleza inmutable de blockchain, cualquier error en un contrato puede tener consecuencias permanentes y potencialmente costosas. La redacción de pruebas integrales garantiza que todas las funciones se comporten como se espera, lo que genera contratos sólidos y seguros.
Recuerde escribir pruebas tanto para casos positivos como negativos. Los casos positivos validan que una función funciona correctamente cuando se usa según lo previsto. Los casos negativos garantizan que el contrato se comporte correctamente al manejar entradas incorrectas o inesperadas.
Los contratos inteligentes son inmutables una vez implementados en la cadena de bloques, lo que significa que no se pueden modificar. Por lo tanto, cualquier error o vulnerabilidad de seguridad puede tener consecuencias graves, lo que hace que las pruebas sean un paso indispensable en el proceso de desarrollo.
En esta lección, analizaremos el contrato Fa1_2TestFull
, que incluye una serie de pruebas diseñadas para verificar la funcionalidad de nuestro contrato de token.
Fa1_2TestFull
El contrato Fa1_2TestFull
es una clase que hereda todas las funcionalidades de los diferentes contratos como Admin, Pause, Fa1_2, Mint, Burn y ChangeMetadata. Se utiliza para agregar todas estas funcionalidades y realizar una prueba exhaustiva para garantizar que el contrato funcione como se esperaba.
Python
clase Fa1_2TestFull(Admin, Pause, Fa1_2, Mint, Burn, ChangeMetadata):
def __init__(auto, administrador, metadatos, libro mayor, token_metadata):
ChangeMetadata.__init__(yo)
Quemar.__init__(yo)
Menta.__init__(yo)
Fa1_2.__init__(yo, metadatos, libro mayor, token_metadata)
Pausa.__init__(yo)
Administración.__init__(yo, administrador)
El constructor de la clase Fa1_2TestFull
inicializa todas las funcionalidades.
Para nuestro contrato, comenzamos configurando el escenario de prueba con cuentas de prueba y la inicialización del contrato. Esto se hace dentro de una función de prueba decorada con @sp.add_test
.
Python
@sp.add_test(name="FA12")def test():
# Inicializa el escenario de prueba y las cuentas
sc = sp.test_scenario(m)
admin = sp.test_account("Administrador")
alicia = sp.test_account("Alicia")
bob = sp.test_account("Roberto")
# Inicializar contrato con algunos valores iniciales
token_metadata = {
"decimals": sp.utils.bytes_of_string("18"), # Mandatory by the spec"name": sp.utils.bytes_of_string("My Great Token"), # Recommended"symbol": sp.utils.bytes_of_string("MGT"), # Recommended# Extra fields"icon": sp.utils.bytes_of_string("https://smartpy.io/static/img/logo-only.svg"),
}
contract_metadata = sp.utils.metadata_of_url("ipfs://QmaiAUj1FFNGYTu8rLBjc3eeN9cSKwaF8EGMBNDmhzPNFd")
c1 = m.Fa1_2TestFull(administrador=admin.address,metadata=contrato_metadata,token_metadata=token_metadata,ledger={},)
sc += c1
Definimos las cuentas de prueba: Admin, Alice y Bob. Luego inicializamos nuestro contrato, Fa1_2TestFull
, con algunos valores iniciales. El operador +=
agrega el contrato al escenario.
De ahora en adelante, para ayudarlo a comprender mejor el código, el código estará a la izquierda y una visualización de la línea de código resaltada estará a la derecha. Ejemplo aquí:
El siguiente paso es ejecutar pruebas, lo que implica activar diferentes funciones del contrato y verificar los resultados.
Por ejemplo, para probar la funcionalidad de acuñación, ejecutamos:
Python
sc.h2("El administrador acuña algunas monedas")
c1.mint(dirección=alice.address, valor=12).run(remitente=admin)
Esta línea ejecuta una prueba en la que el administrador acuña 12 tokens para Alice. Si la función acuña correctamente los tokens y actualiza correctamente el saldo de Alice, entonces esta prueba pasa.
SmartPy proporciona el método verify
para garantizar que una condición sea verdadera. Si no se cumple la condición, la prueba fallará. Por ejemplo:
Python
c1.update_metadata(key="", valor=sp.bytes("0x00")).run(sender=admin)
sc.verify(c1.data.metadata[""] == sp.bytes("0x00"))
Esas líneas verifican que los metadatos del contrato se actualizaron correctamente a "0x00"
. Si no se actualizó correctamente, la prueba falla.
Las pruebas de sus contratos inteligentes deben cubrir todos los casos de uso posibles, incluidos los casos extremos y las posibles fallas. Estos pueden incluir transferencias que excedan el saldo de un usuario, quema de tokens cuando el contrato está en pausa, etc.
Por ejemplo, una prueba de transferencia fallida podría verse así:
Python
sc.h2("Bob intenta transferirse de Alice pero no tiene su aprobación")
c1.transfer(from_=alice.address, to_=bob.dirección, valor=4).run(remitente=bob, válido = falso)
Aquí, Bob intenta transferir 4 tokens de la cuenta de Alice sin tener aprobación. Dado que esta operación debería fallar, configuramos valid=False
en la función run
. Si el contrato impide correctamente la transferencia, se supera la prueba.
Las pruebas son cruciales en el desarrollo de contratos inteligentes. Dada la naturaleza inmutable de blockchain, cualquier error en un contrato puede tener consecuencias permanentes y potencialmente costosas. La redacción de pruebas integrales garantiza que todas las funciones se comporten como se espera, lo que genera contratos sólidos y seguros.
Recuerde escribir pruebas tanto para casos positivos como negativos. Los casos positivos validan que una función funciona correctamente cuando se usa según lo previsto. Los casos negativos garantizan que el contrato se comporte correctamente al manejar entradas incorrectas o inesperadas.