Os contratos inteligentes são imutáveis uma vez implantados no blockchain, o que significa que não podem ser modificados. Portanto, quaisquer bugs ou vulnerabilidades de segurança podem ter consequências graves, tornando o teste uma etapa indispensável no processo de desenvolvimento.
Nesta lição, discutiremos o contrato Fa1_2TestFull
, que inclui uma série de testes projetados para verificar a funcionalidade do nosso contrato de token.
Fa1_2TestFull
O contrato Fa1_2TestFull
é uma classe que herda todas as funcionalidades dos diferentes contratos como Admin, Pause, Fa1_2, Mint, Burn e ChangeMetadata. É utilizado para agregar todas essas funcionalidades e realizar um teste minucioso para garantir que o contrato está funcionando conforme o esperado.
Python
classe Fa1_2TestFull (Admin, Pause, Fa1_2, Mint, Burn, ChangeMetadata):
def __init__(self, administrador, metadados, ledger, token_metadata):
ChangeMetadata.__init__(próprio)
Queimar.__init__(próprio)
Hortelã.__init__(próprio)
Fa1_2.__init__(próprio, metadados, razão, token_metadata)
Pausa.__init__(próprio)
Administrador.__init__(próprio, administrador)
O construtor da classe Fa1_2TestFull
inicializa todas as funcionalidades.
Para o nosso contrato, começamos configurando o cenário de teste com contas de teste e a inicialização do contrato. Isso é feito em uma função de teste decorada com @sp.add_test
.
Python
@sp.add_test(name="FA12")def test():
# Inicializa cenário de teste e contas
sc = sp.test_scenario(m)
admin = sp.test_account("Administrador")
alice = sp.test_account("Alice")
bob = sp.test_account("Robert")
# Inicialize o contrato com alguns valores iniciais
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=contract_metadata,token_metadata=token_metadata,ledger={},)
sc + = c1
Definimos as contas de teste: Admin, Alice e Bob. Depois inicializamos nosso contrato, Fa1_2TestFull
, com alguns valores iniciais. O operador +=
adiciona o contrato ao cenário.
A partir de agora, para ajudar você a entender melhor o código, o código ficará à esquerda e uma visualização da linha do código destacada à direita. Exemplo aqui:
A próxima etapa é executar testes, e isso envolve o acionamento de diferentes funções de contrato e a verificação dos resultados.
Por exemplo, para testar a funcionalidade de cunhagem, executamos:
Python
sc.h2("Admin cunha algumas moedas")
c1.mint(address=alice.address, value=12).run(sender=admin)
Esta linha executa um teste onde o administrador emite 12 tokens para Alice. Se a função cunhar os tokens com sucesso e atualizar corretamente o saldo de Alice, esse teste será aprovado.
SmartPy fornece o método verify
para garantir que uma condição seja verdadeira. Se a condição não for atendida, o teste falhará. Por exemplo:
Python
c1.update_metadata(key="", valor=sp.bytes("0x00")).run(sender=admin)
sc.verify(c1.data.metadata[""] == sp.bytes("0x00"))
Essas linhas verificam se os metadados do contrato foram atualizados corretamente para "0x00"
. Se não foi atualizado corretamente, o teste falhará.
Seus testes de contrato inteligente devem cobrir todos os casos de uso possíveis, incluindo casos extremos e falhas potenciais. Isso pode incluir transferências que excedam o saldo do usuário, queima de tokens quando o contrato é pausado, etc.
Por exemplo, um teste de transferência com falha poderia ser assim:
Python
sc.h2("Bob tenta transferir de Alice, mas não tem a aprovação dela")
c1.transfer(from_=alice.address, to_=bob.endereço, valor=4).run(remetente=bob, válido=Falso)
Aqui, Bob tenta transferir 4 tokens da conta de Alice sem aprovação. Como esta operação deve falhar, definimos valid=False
na função run
. Se o contrato impedir corretamente a transferência, o teste será aprovado.
O teste é crucial no desenvolvimento de contratos inteligentes. Dada a natureza imutável da blockchain, qualquer erro num contrato pode ter consequências permanentes e potencialmente dispendiosas. Escrever testes abrangentes garante que todas as funções se comportem conforme esperado, levando a contratos robustos e seguros.
Lembre-se de escrever testes para casos positivos e negativos. Casos positivos validam que uma função funciona corretamente quando usada conforme pretendido. Os casos negativos garantem que o contrato se comporte corretamente ao lidar com entradas incorretas ou inesperadas.
Os contratos inteligentes são imutáveis uma vez implantados no blockchain, o que significa que não podem ser modificados. Portanto, quaisquer bugs ou vulnerabilidades de segurança podem ter consequências graves, tornando o teste uma etapa indispensável no processo de desenvolvimento.
Nesta lição, discutiremos o contrato Fa1_2TestFull
, que inclui uma série de testes projetados para verificar a funcionalidade do nosso contrato de token.
Fa1_2TestFull
O contrato Fa1_2TestFull
é uma classe que herda todas as funcionalidades dos diferentes contratos como Admin, Pause, Fa1_2, Mint, Burn e ChangeMetadata. É utilizado para agregar todas essas funcionalidades e realizar um teste minucioso para garantir que o contrato está funcionando conforme o esperado.
Python
classe Fa1_2TestFull (Admin, Pause, Fa1_2, Mint, Burn, ChangeMetadata):
def __init__(self, administrador, metadados, ledger, token_metadata):
ChangeMetadata.__init__(próprio)
Queimar.__init__(próprio)
Hortelã.__init__(próprio)
Fa1_2.__init__(próprio, metadados, razão, token_metadata)
Pausa.__init__(próprio)
Administrador.__init__(próprio, administrador)
O construtor da classe Fa1_2TestFull
inicializa todas as funcionalidades.
Para o nosso contrato, começamos configurando o cenário de teste com contas de teste e a inicialização do contrato. Isso é feito em uma função de teste decorada com @sp.add_test
.
Python
@sp.add_test(name="FA12")def test():
# Inicializa cenário de teste e contas
sc = sp.test_scenario(m)
admin = sp.test_account("Administrador")
alice = sp.test_account("Alice")
bob = sp.test_account("Robert")
# Inicialize o contrato com alguns valores iniciais
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=contract_metadata,token_metadata=token_metadata,ledger={},)
sc + = c1
Definimos as contas de teste: Admin, Alice e Bob. Depois inicializamos nosso contrato, Fa1_2TestFull
, com alguns valores iniciais. O operador +=
adiciona o contrato ao cenário.
A partir de agora, para ajudar você a entender melhor o código, o código ficará à esquerda e uma visualização da linha do código destacada à direita. Exemplo aqui:
A próxima etapa é executar testes, e isso envolve o acionamento de diferentes funções de contrato e a verificação dos resultados.
Por exemplo, para testar a funcionalidade de cunhagem, executamos:
Python
sc.h2("Admin cunha algumas moedas")
c1.mint(address=alice.address, value=12).run(sender=admin)
Esta linha executa um teste onde o administrador emite 12 tokens para Alice. Se a função cunhar os tokens com sucesso e atualizar corretamente o saldo de Alice, esse teste será aprovado.
SmartPy fornece o método verify
para garantir que uma condição seja verdadeira. Se a condição não for atendida, o teste falhará. Por exemplo:
Python
c1.update_metadata(key="", valor=sp.bytes("0x00")).run(sender=admin)
sc.verify(c1.data.metadata[""] == sp.bytes("0x00"))
Essas linhas verificam se os metadados do contrato foram atualizados corretamente para "0x00"
. Se não foi atualizado corretamente, o teste falhará.
Seus testes de contrato inteligente devem cobrir todos os casos de uso possíveis, incluindo casos extremos e falhas potenciais. Isso pode incluir transferências que excedam o saldo do usuário, queima de tokens quando o contrato é pausado, etc.
Por exemplo, um teste de transferência com falha poderia ser assim:
Python
sc.h2("Bob tenta transferir de Alice, mas não tem a aprovação dela")
c1.transfer(from_=alice.address, to_=bob.endereço, valor=4).run(remetente=bob, válido=Falso)
Aqui, Bob tenta transferir 4 tokens da conta de Alice sem aprovação. Como esta operação deve falhar, definimos valid=False
na função run
. Se o contrato impedir corretamente a transferência, o teste será aprovado.
O teste é crucial no desenvolvimento de contratos inteligentes. Dada a natureza imutável da blockchain, qualquer erro num contrato pode ter consequências permanentes e potencialmente dispendiosas. Escrever testes abrangentes garante que todas as funções se comportem conforme esperado, levando a contratos robustos e seguros.
Lembre-se de escrever testes para casos positivos e negativos. Casos positivos validam que uma função funciona corretamente quando usada conforme pretendido. Os casos negativos garantem que o contrato se comporte corretamente ao lidar com entradas incorretas ou inesperadas.