FlowCards: Um Framework Declarativo para Desenvolvimento de dApps Ergo
29 de abril de 2020

Agradecimentos a Robert Kornacki pela revisão do rascunho.
Introdução
ErgoScript é a linguagem de contrato inteligente utilizada
pela blockchain Ergo. Embora tenha uma sintaxe concisa adotada do Scala/Kotlin, ainda pode
parecer confusa à primeira vista, pois conceitualmente o ErgoScript é bastante diferente em comparação
com as linguagens convencionais que todos conhecemos e amamos. Isso ocorre porque o Ergo é uma blockchain baseada em UTXO,
enquanto os contratos inteligentes são tradicionalmente associados a sistemas baseados em contas
como o Ethereum. No entanto, o modelo de transação do Ergo tem muitas vantagens sobre o modelo
baseado em contas e, com a abordagem certa, pode ser significativamente mais fácil desenvolver contratos Ergo
do que escrever e depurar código Solidity.
Abaixo, abordaremos os principais aspectos do modelo de contrato Ergo que o tornam diferente:
Paradigma
O modelo de conta do Ethereum é imperativo. Isso significa que a tarefa típica de enviar moedas de
Alice para Bob requer a alteração dos saldos no armazenamento como uma série de operações. O modelo de programação baseado em UTXO do Ergo,\npor outro lado, é declarativo. Os contratos ErgoScript especificam condições para que uma
transação seja aceita pela blockchain (não mudanças a serem feitas no estado de armazenamento
como resultado da execução do contrato).
Escalabilidade
No modelo de conta do Ethereum, tanto as mudanças de armazenamento quanto as verificações de validade são realizadas
on-chain durante a execução do código. Em contraste, as transações Ergo são criadas
off-chain e apenas as verificações de validação são realizadas on-chain, reduzindo assim a quantidade de
operações realizadas por cada nó na rede. Além disso, devido à imutabilidade do
grafo de transações, várias estratégias de otimização são possíveis para melhorar a taxa de
transações por segundo na rede. Nós leves de verificação também são possíveis, facilitando ainda mais a escalabilidade e acessibilidade da rede.
Estado compartilhado
O modelo baseado em contas depende de um estado mutável compartilhado, que é conhecido por levar
a semânticas complexas (e sutis bugs de milhões de dólares) no contexto de computação concorrente/
distribuída. O modelo do Ergo é baseado em um grafo imutável de transações. Essa
abordagem, herdada do Bitcoin, se adapta bem à natureza concorrente e distribuída das
blockchains e facilita clientes leves sem confiança.
Poder expressivo
O Ethereum defendeu a execução de uma linguagem Turing-completa na blockchain. Teoricamente,
prometeu potencial ilimitado, no entanto, na prática, severas limitações vieram à tona devido ao excesso de
inchaço da blockchain, sutis bugs de milhões de dólares, custos de gás que
limitam a complexidade do contrato e outros problemas semelhantes. O Ergo, por outro lado, estende o UTXO para permitir
a completude de Turing enquanto limita a complexidade da própria linguagem ErgoScript. O mesmo
poder expressivo é alcançado de uma maneira diferente e mais semanticamente sólida.
Com todos os pontos acima, deve estar claro que há muitos benefícios no modelo que o Ergo está utilizando.
No restante deste artigo, vou apresentar o conceito de FlowCards - um componente para desenvolvedores de dApp
que permite projetar contratos Ergo complexos de maneira declarativa e visual.
De Imperativo a Declarativo
No modelo de programação imperativa do Ethereum, uma transação é uma sequência de operações
executadas pela VM do Ethereum. A seguinte função Solidity
implementa uma transferência de tokens de sender para receiver. A transação começa quando
sender chama essa função em uma instância de um contrato e termina quando a função
retorna.
// Envia uma quantidade de moedas existentes de qualquer chamador para um endereço
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Saldo insuficiente.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
A função primeiro verifica as pré-condições, depois atualiza o armazenamento (ou seja, saldos) e
finalmente publica a pós-condição como o evento Sent. O gás consumido pela
transação é enviado ao minerador como recompensa por executar essa transação.
Ao contrário do Ethereum, uma transação no Ergo é uma estrutura de dados que contém uma lista de moedas de entrada
que gasta e uma lista de moedas de saída que cria, preservando os saldos totais de
ERGs e tokens (em que o Ergo é semelhante ao Bitcoin).
Voltando ao exemplo acima, uma vez que o Ergo suporta nativamente tokens, portanto, para este
exemplo específico de envio de tokens, não precisamos escrever nenhum código em ErgoScript. Em vez disso,
precisamos criar a transação 'send' mostrada na figura a seguir, que descreve
transferência de token da mesma forma, mas de maneira declarativa.

A imagem descreve visualmente os seguintes passos que o usuário da rede precisa realizar:
- Selecionar caixas não gastas do remetente, contendo no total
tB >= amountde tokens eB >= txFee + minErgERGs. - Criar uma caixa de saída
targetque é protegida pela chave pública doreceivercomminErg
ERGs eamountde tokensT. - Criar uma saída de taxa protegida pelo contrato
minerFeecomtxFeeERGs. - Criar uma saída de troco protegida pela chave pública do
sender, contendo
B - minErg - txFeeERGs etB - amountde tokensT. - Criar uma nova transação, assiná-la usando a chave secreta do remetente e enviá-la para a rede
Ergo.
O que é importante entender aqui é que todos esses passos são realizados off-chain (por
exemplo, usando a API de Transação do Appkit) pela
aplicação do usuário. Os nós da rede Ergo não precisam repetir esse processo de criação de transação,
eles apenas precisam validar a transação já formada. Os contratos ErgoScript são armazenados nas
entradas da transação e verificam as condições de gasto. O nó executa os
contratos on-chain quando a transação é validada. A transação é válida se todas
as condições forem satisfeitas.
Assim, no Ethereum, quando dizemos "enviar quantia de remetente para destinatário", estamos literalmente
editando saldos e atualizando o armazenamento com um conjunto concreto de comandos. Isso acontece
on-chain e, portanto, uma nova transação também é criada on-chain como resultado desse processo.
No Ergo (como no Bitcoin), as transações são criadas off-chain e os nós da rede apenas
as verificam. Os efeitos da transação no estado da blockchain são que as moedas de entrada
(ou Caixas na terminologia do Ergo) são removidas e as caixas de saída são adicionadas ao
UTXO conjunto.
No exemplo acima, não usamos um contrato ErgoScript, mas assumimos que uma verificação de assinatura é
usada como a pré-condição de gasto. No entanto, em cenários de aplicação mais complexos, precisamos
usar o ErgoScript, que é o que vamos discutir a seguir.
De Mudança de Estado para Verificação de Contexto
No exemplo da função send, primeiro verificamos a pré-condição (require(amount <= balances[msg.sender],...)) e depois mudamos o estado (ou seja, atualizamos os saldos
balances[msg.sender] -= amount). Isso é típico nas transações do Ethereum. Antes
que possamos mudar qualquer coisa, precisamos verificar se é válido fazê-lo.
No Ergo, como discutimos anteriormente, o estado (ou seja, conjunto UTXO de caixas) é alterado implicitamente quando uma
transação válida é incluída em um bloco. Assim, só precisamos verificar as pré-condições antes
que a transação possa ser adicionada ao bloco. É isso que os contratos ErgoScript fazem.
Não é possível "mudar o estado" no ErgoScript porque é uma linguagem para verificar
pré-condições para gastar moedas. O ErgoScript é uma linguagem puramente funcional sem efeitos colaterais que opera em valores de dados imutáveis. Isso significa que todas as entradas, saídas e
outros parâmetros de transação disponíveis em um script são imutáveis. Isso, entre outras
coisas, torna o ErgoScript uma linguagem muito simples que é fácil de aprender e segura de usar. Semelhante ao
Bitcoin, cada caixa de entrada contém um script, que deve retornar o valor true para
- permitir o gasto da caixa (ou seja, removendo do conjunto UTXO) e 2) adicionar a
transação ao bloco.
Se formos pedantes, portanto, é incorreto (estritamente falando) pensar no ErgoScript como a linguagem dos
contratos Ergo, porque é a linguagem de proposições (predicados lógicos, fórmulas,
etc.) que protegem as caixas de gastos "ilegais". Ao contrário do Bitcoin, no Ergo, toda a
transação e uma parte do contexto atual da blockchain estão disponíveis para cada script. Portanto,
cada script pode verificar quais saídas são criadas pela transação, suas quantidades de ERG e token
(usar essa capacidade em nossos contratos DEX), número do bloco atual
etc.
No ErgoScript, você define as condições de se as mudanças (ou seja, gasto de moedas) são permitidas
acontecer em um determinado contexto. Isso contrasta com programar as mudanças
imperativamente no código de um contrato.
Enquanto o modelo de transação do Ergo desbloqueia uma gama inteira de aplicações como (DEX, DeFi
Apps, LETS, etc), projetar contratos como pré-condições para gasto de moedas (ou scripts de proteção)
diretamente não é intuitivo. Nas próximas seções, consideraremos uma notação gráfica útil
para projetar contratos de forma declarativa usando Diagramas FlowCard, que é uma representação visual
de componentes executáveis (FlowCards).
FlowCards visam simplificar radicalmente o desenvolvimento de dApp na plataforma Ergo, fornecendo uma linguagem declarativa de alto nível, tempo de execução, formato de armazenamento e
a notação gráfica.
Começaremos com um nível alto de diagramas e desceremos para a especificação do FlowCard.
Diagramas FlowCard
A ideia por trás dos diagramas FlowCard é baseada nas seguintes observações: 1) Uma caixa Ergo
é imutável e só pode ser gasta na transação que a utiliza como entrada. 2) Portanto,
podemos desenhar um fluxo de caixas através de transações, de modo que as caixas fluindo para dentro
da transação sejam gastas e aquelas fluindo para fora sejam criadas e adicionadas ao UTXO. 3) Uma
transação, dessa perspectiva, é simplesmente um transformador de caixas antigas para novas,
preservando os saldos de ERGs e tokens envolvidos.
A figura a seguir mostra os principais elementos da transação Ergo que já vimos
anteriormente (agora sob o nome de Diagrama FlowCard).

Há um significado (semântica) estritamente definido por trás de cada elemento do diagrama,
para que o diagrama seja uma representação visual (ou uma visão) do componente executável subjacente
(chamado FlowCard).
O FlowCard pode ser usado como um componente reutilizável de um dApp Ergo para criar e iniciar a
transação na blockchain Ergo. Discutiremos isso nas seções seguintes.
Agora vamos olhar para as peças individuais do diagrama FlowCard uma a uma.
1. Nome e Parâmetros
Cada flow card recebe um nome e uma lista de parâmetros tipados. Isso é semelhante a um
template com parâmetros. Na figura acima, podemos ver o flow card Send, que tem cinco parâmetros.
Os parâmetros são usados na especificação.
2. Carteira do Contrato
Este é um elemento chave do flow card. Cada caixa tem um script de proteção. Muitas vezes, é o
script que verifica uma assinatura contra uma chave pública. Este script é trivial no ErgoScript
e é definido como o template def pk(pubkey: Address) = { pubkey }, onde pubkey é
um parâmetro do tipo Address. Na figura, o template do script é aplicado ao
parâmetro pk(sender) e, assim, um contrato de carteira concreto é obtido. Portanto,
pk(sender) e pk(receiver) geram scripts diferentes e representam carteiras diferentes
no diagrama, mesmo que usem o mesmo template.
A Carteira do Contrato contém um conjunto de todas as caixas UTXO que têm um dado script derivado do
template de script dado usando os parâmetros do flow card. Por exemplo, na figura, o
template é pk e o parâmetro pubkey é substituído pelo parâmetro do flow card sender.
3. Contrato
Embora um contrato seja uma propriedade de uma caixa, no diagrama agrupamos as caixas por seus
contratos, portanto, parece que as caixas pertencem aos contratos, em vez de os
contratos pertencerem às caixas. No exemplo, temos três contratos instanciados
pk(sender), pk(receiver) e minerFee. Note que pk(sender) é a instanciação do
template pk com o parâmetro concreto sender e minerFee é a instanciação do
contrato pré-definido que protege as caixas de recompensa do minerador.
4. Nome da Caixa
No diagrama, podemos dar a cada caixa um nome. Além da legibilidade do diagrama, também usamos o
nome como um sinônimo de um acesso indexado mais complexo à caixa no contrato. Por
exemplo, change é o nome da caixa, que também pode ser usado nas condições do ErgoScript
em vez de OUTPUTS(2). Também usamos nomes de caixas para associar condições de gasto
com as caixas.
5. Caixas na carteira
No diagrama, mostramos caixas (retângulos mais escuros) como pertencentes às carteiras de contrato
(retângulos mais claros). Cada retângulo de caixa é conectado a um retângulo de transação
cinza por setas laranja ou verdes ou ambas. Uma caixa de saída (com uma seta verde
entrante) pode incluir muitas linhas de texto, onde cada linha especifica uma condição que deve ser verificada como parte da transação. A primeira
linha especifica a condição sobre a quantidade de ERG que deve ser colocada na caixa. Outras
linhas podem assumir uma das seguintes formas:
amount: TOKEN- a caixa deve conter a dadaamountdo dadoTOKENR == value- a caixa deve conter o dadovaluedo dado registroRboxName ? condition- a caixa chamadaboxNamedeve verificarconditionem seu script.
Discutiremos essas condições nas seções abaixo.
6. Quantidade de ERGs na caixa
Cada caixa deve armazenar uma quantidade mínima de ERGs. Isso é verificado quando a transação de criação é
validada. No diagrama, a quantidade de ERGs é sempre mostrada como a primeira linha (por exemplo, B: ERG ou B - minErg - txFee). A atribuição de tipo de valor B: ERG é opcional e pode
ser usada para legibilidade. Quando o valor é dado como uma fórmula, então essa fórmula deve ser
respeitada pela transação que cria a caixa.
É importante entender que variáveis como amount e txFee não são propriedades nomeadas
das caixas. Elas são parâmetros de todo o diagrama e representam algumas
quantidades. Ou, colocando de outra forma, são parâmetros compartilhados entre transações (por exemplo, a Ordem de Venda e as transações de Troca do exemplo DEX abaixo compartilham o parâmetro tAmt). Assim,
o mesmo nome está vinculado ao mesmo valor em todo o diagrama (é aqui que a
ferramenta ajudaria muito). No entanto, quando se trata de validação on-chain desses valores,
apenas condições explícitas que estão marcadas com ? são transformadas em ErgoScript. Ao
mesmo tempo, todas as outras condições são garantidas off-chain durante a construção da transação (por exemplo, em uma
aplicação usando a API do Appkit) e validação da transação quando é adicionada à
blockchain.
7. Quantidade de token T
Uma caixa pode armazenar valores de muitos tokens. Os tokens no diagrama são nomeados e uma variável value
pode ser associada ao token T usando a expressão value: T. O value pode
ser dado por fórmula. Se a fórmula for prefixada com um nome de caixa como boxName ? formula,
então também deve ser verificada no script de proteção da caixa boxName. Essa
especificação adicional é muito conveniente porque 1) permite validar o design visual
automaticamente, e 2) as condições especificadas nas caixas de um diagrama são suficientes
para sintetizar os scripts de proteção necessários. (mais sobre isso
abaixo em "De Diagramas a Contratos ErgoScript")
8. Entradas Tx
As entradas estão conectadas à transação correspondente por setas laranja. Uma seta de entrada pode ter um rótulo das seguintes formas:
name@index- nome opcional com um índice, ou seja,fee@0ou@2. Esta é uma propriedade do
ponto de destino da seta. O nome é usado nas condições das caixas relacionadas
e oindexé a posição da caixa correspondente na coleção INPUTS da
transação.!action- é uma propriedade da origem da seta e dá um nome para um caminho de gasto alternativo da caixa (veremos isso no exemplo DEX)
Devido a caminhos de gasto alternativos, uma caixa pode ter muitas setas laranja saindo, caso em que elas devem ser rotuladas com ações diferentes.
9. Transação
Uma transação gasta caixas de entrada e cria caixas de saída. As caixas de entrada são dadas pelas
setas laranja e espera-se que os rótulos coloquem as entradas nos
índices corretos na coleção INPUTS. As caixas de saída são dadas pelas setas verdes. Cada transação deve preservar um equilíbrio estrito dos valores de ERG
(soma das entradas == soma das saídas) e para cada token a soma das entradas >= a soma
das saídas. O diagrama de design requer uma especificação explícita dos valores de ERG e token
para todas as caixas de saída para evitar erros implícitos e garantir melhor legibilidade.
10. Saídas Tx
As saídas estão conectadas à transação correspondente por setas verdes. Uma seta de saída pode ter um rótulo da seguinte forma name@index, onde um
nome opcional é acompanhado por um índice, ou seja, fee@0 ou @2. Esta é uma propriedade do
ponto de origem da seta. O nome é usado nas condições das caixas relacionadas e o
index é a posição da caixa correspondente na coleção OUTPUTS da transação.
Exemplo: Troca Descentralizada (DEX)
Agora vamos usar a notação descrita acima para projetar um FlowCard para um dApp DEX. É simples
demais, mas também ilustra todos os principais recursos dos diagramas FlowCard
que introduzimos na seção anterior.
O cenário do dApp é mostrado na figura abaixo:
Há três participantes (comprador,
vendedor e DEX) do dApp DEX e cinco tipos diferentes de transações, que são criadas pelos
participantes. O comprador deseja trocar ergAmt de ERGs por tAmt de tokens TID (ou vice
versa, o vendedor deseja vender tokens TID por ERGs, quem envia a ordem primeiro não
importa). Tanto o comprador quanto o vendedor podem cancelar seus pedidos a qualquer momento. O serviço de correspondência off-chain do DEX
pode encontrar pedidos correspondentes e criar a transação Swap para
completar a troca.
O diagrama a seguir especifica totalmente (e formalmente) todas as cinco transações que devem
ser criadas off-chain pelo dApp DEX. Ele também especifica todas as condições de gasto que
devem ser verificadas on-chain.

Vamos discutir o diagrama FlowCard e a lógica de cada transação em detalhes:
Transação de Ordem de Compra
Um comprador cria uma transação de Ordem de Compra. A transação gasta E quantidade de ERGs
(que escreveremos E: ERG) de uma ou mais caixas na carteira pk(buyer). A
transação cria uma caixa bid com ergAmt: ERG protegida pelo script buyOrder. O
script buyOrder é sintetizado a partir da especificação (veja
abaixo em "De Diagramas a Contratos ErgoScript") manualmente ou automaticamente por uma
ferramenta. Embora não precisemos definir o script buyOrder explicitamente durante
o design, em tempo de execução a caixa bid deve conter o script buyOrder como a
proposição de proteção (que verifica as condições de gasto da caixa), caso contrário, as condições
especificadas no diagrama não serão verificadas.
A caixa change é criada para equilibrar as somas de entrada e saída da transação.
A caixa de taxa da transação é omitida porque pode ser adicionada automaticamente pelas ferramentas. Na
prática, no entanto, o designer pode adicionar a caixa de taxa explicitamente ao diagrama. Isso cobre
os casos de transações mais complexas (como Troca) onde há muitas maneiras de pagar
a taxa da transação.
Cancelar Compras, Cancelar Vendas
A qualquer momento, o comprador pode cancelar o pedido enviando a transação CancelBuy. A
transação deve satisfazer o contrato de proteção buyOrder que protege a caixa bid.
Como você pode ver no diagrama, tanto as transações Cancel quanto Swap podem gastar a
caixa bid. Quando uma caixa tem alternativas de gasto (ou caminhos de gasto), cada
alternativa é identificada por um nome único prefixado com ! (!cancel e !swap
para a caixa bid). Cada caminho alternativo tem condições de gasto específicas. No nosso exemplo,
quando a transação Cancel Buy gasta a caixa bid, a condição ?buyer deve ser
satisfeita, que lemos como "a assinatura para o endereço buyer deve ser apresentada na
transação". Portanto, apenas o comprador pode cancelar a ordem de compra. Essa condição de "assinatura"
é exigida apenas para o caminho de gasto alternativo !cancel e não é exigida para !swap.
Transação de Ordem de Venda
A transação de Ordem de Venda é semelhante à Ordem de Compra na medida em que lida com tokens além de ERGs. A transação gasta E: ERG e T: TID tokens da carteira do vendedor
(especificada como contrato pk(seller)). As duas saídas são ask e change. O troco
é uma caixa padrão para equilibrar a transação. A caixa ask mantém tAmt: TID tokens para a troca
e minErg: ERG - a quantidade mínima de ERGs exigida em cada caixa.
Transação de Troca
Esta é uma transação chave no cenário do dApp DEX. A transação tem várias condições de gasto nas caixas de entrada e essas condições estão incluídas nos scripts buyOrder e
sellOrder (que são verificados quando a transação é adicionada à
blockchain). No entanto, no diagrama, essas condições não estão especificadas nas caixas bid e
ask, elas são definidas nas caixas de saída da transação.
Esta é uma convenção para melhorar a usabilidade, pois a maioria das condições se relaciona às propriedades das
caixas de saída. Poderíamos especificar essas propriedades na caixa bid, mas então teríamos
que usar expressões mais complexas.
Vamos considerar a saída criada pela seta rotulada com buyerOut@0. Este rótulo nos diz
que a saída está no índice 0 na coleção OUTPUTS da transação e
que no diagrama podemos nos referir a esta caixa pelo nome buyerOut. Assim, podemos rotular
tanto a caixa em si quanto a seta para dar um nome à caixa.
As condições mostradas na caixa buyerOut têm a forma bid ? condition, o que significa
que devem ser verificadas on-chain para gastar a caixa bid.
As condições têm o seguinte significado:
tAmt: TIDexige que a caixa tenhatAmtquantidade de tokenTIDR4 == bid.idexige que o registro R4 na caixa seja igual ao id da caixabid.script == buyerexige que a caixabuyerOuttenha o script da carteira onde está
localizada no diagrama, ou seja,pk(buyer)
Propriedades semelhantes são adicionadas à caixa sellerOut, que é especificada para estar no índice 1
e o nome é dado a ela usando o rótulo na própria caixa, em vez de na seta.
A transação Swap gasta duas caixas bid e ask usando o caminho de gasto !swap em ambas,
no entanto, ao contrário de !cancel, as condições no caminho não são especificadas. É aqui que os
prefixos bid ? e ask ? entram em cena. Eles são usados para que as condições listadas nas caixas buyerOut e
sellerOut sejam movidas para o caminho de gasto !swap das caixas bid e ask, respectivamente.
Se você olhar para as condições das caixas de saída, verá que elas especificam exatamente
a troca de valores entre as carteiras do vendedor e do comprador. O comprador recebe a quantidade necessária
de token TID e o vendedor recebe a quantidade correspondente de ERGs. A transação Swap
é criada quando há duas caixas correspondentes com contratos buyOrder e sellOrder.
De Diagramas a Contratos ErgoScript
O que é interessante sobre as especificações FlowCard é que podemos usá-las para gerar automaticamente
os scripts necessários ErgoTree.
Com o suporte de ferramentas apropriadas, isso pode ser feito automaticamente, mas na falta de
suporte, pode ser feito manualmente. Assim, o FlowCard nos permite capturar e representar visualmente
todas as escolhas de design e detalhes semânticos de um dApp Ergo.
O que vamos fazer a seguir é criar mecanicamente o contrato buyOrder a partir das
informações dadas no flow card DEX.
Lembre-se de que cada script é uma proposição (expressão de valor booleano) que deve avaliar
para true para permitir o gasto da caixa. Quando temos muitas condições a serem atendidas ao mesmo
tempo, podemos combiná-las em uma fórmula lógica usando a operação binária AND, e se tivermos
alternativas (não necessariamente exclusivas), podemos colocá-las na operação OR.
A caixa buyOrder tem os caminhos de gasto alternativos !cancel e !swap. Assim, o
código ErgoScript deve ter a operação OR com dois argumentos - um para cada caminho de gasto.
/** contrato buyOrder */
{
val cancelCondition = {}
val swapCondition = {}
cancelCondition || swapCondition
}
A fórmula para a expressão cancelCondition é dada no caminho de gasto !cancel
da caixa buyOrder. Podemos incluí-la diretamente no script.
/** contrato buyOrder */
{
val cancelCondition = { buyer }
val swapCondition = {}
cancelCondition || swapCondition
}
Para o caminho de gasto !swap da caixa buyOrder, as condições são especificadas na
caixa de saída buyerOut da transação Swap. Se simplesmente as incluirmos na
swapCondition, obteremos um script sintaticamente incorreto.
/** contrato buyOrder */
{
val cancelCondition = { buyer }
val swapCondition = {
tAmt: TID &&
R4 == bid.id &&
@contract
}
cancelCondition || swapCondition
}
Podemos, no entanto, traduzir as condições da sintaxe do diagrama para expressões ErgoScript
usando as seguintes regras simples:
buyerOut@0==>val buyerOut = OUTPUTS(0)tAmt: TID==>tid._2 == tAmtondetid = buyerOut.tokens(TID)R4 == bid.id==>R4 == SELF.idondeR4 = buyerOut.R4[Coll[Byte]].getscript == buyer==>buyerOut.propositionBytes == buyer.propBytes
Note que, no diagrama, TID representa um id de token, mas o ErgoScript não tem acesso aos
tokens pelos ids, então não podemos escrever tokens.getByKey(TID). Por essa razão, quando o
diagrama é traduzido para ErgoScript, TID se torna uma constante nomeada do índice na
coleção tokens da caixa. O valor concreto da constante é atribuído quando a
transação BuyOrder com a caixa buyOrder é criada. A correspondência e
consistência entre o tokenId real, a constante TID e os tokens reais da
caixa buyerOut são garantidas pelo código da aplicação off-chain, que é completamente
possível, uma vez que todas as transações são criadas pela aplicação usando o FlowCard como uma
especificação orientadora. Isso pode parecer muito complicado, mas isso faz parte da tradução
da especificação do diagrama para o código de aplicação executável real, a maior parte da qual pode ser
automatizada.
Após a transformação, podemos obter um script correto que verifica todas as pré-condições
exigidas para gastar a caixa buyOrder.
/** contrato buyOrder */
def DEX(buyer: Addrss, seller: Address, TID: Int, ergAmt: Long, tAmt: Long)
{
val cancelCondition: SigmaProp = { buyer } // verifica a assinatura do comprador (ProveDlog)
val swapCondition = OUTPUTS.size > 0 && { // garantindo acesso a OUTPUTS
val buyerOut = OUTPUTS(0) // de buyerOut@0
buyerOut.tokens.size > TID && { // garantindo acesso a tokens
val tid = buyerOut.tokens(TID)
val regR4 = buyerOut.R4[Coll[Byte]]
regR4.isDefined && { // garantindo acesso a R4
val R4 = regR4.get
tid._2 == tAmt && // de tAmt: TID
R4 == SELF.id && // de R4 == bid.id
buyerOut.propositionBytes == buyer.propBytes // de script == buyer
}
}
}
cancelCondition || swapCondition
}
Um script semelhante para a caixa sellOrder pode ser obtido usando as mesmas regras de tradução.
Com a ajuda das ferramentas, o código dos contratos pode ser gerado mecanicamente a partir da
especificação do diagrama.
Conclusões
Modelos de programação declarativa já venceram a batalha contra a programação imperativa
em muitos domínios de aplicação como Big Data, Processamento de Fluxo, Aprendizado Profundo, Bancos de Dados,
etc. O Ergo está pioneirando o modelo declarativo de desenvolvimento de dApp como uma alternativa melhor e mais segura
ao agora popular modelo imperativo de contratos inteligentes.
O conceito de FlowCard muda o foco de escrever contratos ErgoScript para o
geral fluxo de valores (daí o nome), de tal forma que o ErgoScript pode sempre
ser gerado a partir deles. Você nunca precisará olhar para o código ErgoScript uma vez que as ferramentas
estejam em funcionamento.
Aqui estão os possíveis próximos passos para trabalhos futuros:
-
Formato de armazenamento para a Especificação FlowCard e o correspondente formato de arquivo padronizado EIP
(Json/XML/Protobuf). Isso permitirá que várias ferramentas (Editor de Diagrama, Tempo de Execução, dApps etc)
criem e usem arquivos*.flowcard. -
Visualizador FlowCard, que pode gerar os diagramas a partir de arquivos
*.flowcard. -
Tempo de Execução FlowCard, que pode executar arquivos
*.flowcard, criar e enviar transações para a rede Ergo. -
Ferramenta de Designer FlowCard, que pode simplificar o desenvolvimento de diagramas complexos. Isso fará
com que o design e a validação de contratos Ergo sejam uma experiência agradável, mais parecida com desenhar
do que codificar. Além disso, a correção de todo o cenário do dApp pode ser
verificada e controlada pelas ferramentas.
Referências
Share post
13 de agosto de 2025
12 de agosto de 2025
9 de julho de 2025
12 de maio de 2025

7 de abril de 2022

8 de março de 2022


















