/** Gas Ótimo! Agora sabemos como atualizar porções importantes da DApp enquanto prevenimos que outros usuários estraguem com nossos contratos. Vamos ver outra maneira que Solidity é um tanto diferente de outras linguagens de programação: Gas — o combustível utilizado por DApps Ethereum Em Solidity, seus usuários tem que pagar toda vez que executam uma função em sua DApp usando uma moeda chamada gas. Usuários compram gas com Ether (a moeda no Ethereum), então os seus usuários precisam gastar ETH para executar funções em sua DApp. Quanto gas é preciso para executar uma função depende o quão complexo é a lógica desta função. Cada operação individual tem um custo em gas baseado mais ou menos em quanto recursos computacionais serão necessários para realizar essa operação (exemplo: escrever em storage é muito mais caro do que adicionar dois inteiros). O total de custo em gas da sua função é soma de todos os custo de todas as operações de forma individuais. E porque executar funções custam dinheiro real para os seus usuários, otimização do código é muito mais importante em Ethereum do que em qualquer outra linguagem de programação. Se o seu código é desleixado, seus usuários terão que pagar muito mais para executar suas funções - e isto pode adicionar milhões de dólares em custos desnecessários através de milhares de usuários. Por que o gas é necessário? Ethereum é como um grande, lento, mas extremamente seguro computador. Quando você executa uma função, cada um dos nós na rede precisa rodar esta mesma função e verificar suas saídas - milhares de nos verificando cada execução de cada função é o que faz do Ethereum decentralizado, e seus dados imutáveis e resistentes a censura. Os criadores do Ethereum queriam ter certeza que ninguém poderia entupir a rede com laços infinitos, ou estragar todos os recursos da rede com computações realmente intensivas. Então eles fizeram com que as transações não fossem grátis, e os usuários tem que pagar pelo tempo de computação como também pela guarda dos dados Nota: Isto não é necessariamente verdade em sidechains, como a que os autores do CryptoZombies estão construindo na Loom Network. E provavelmente nunca irá fazer sentido rodar um jogo como World of Warcraft diretamente na rede mainnet do Ethereum - o custo em gas seria proibitivamente caro. Mas este pode rodar em uma sidechain com um algorítimo de consenso diferente. Iremos falar mais sobre os tipos de DApps que você poderia implantar em sidechains vs a mainnet do Ethereum em futuras lições. Empacotamento da estrutura para economizar gas Na Lição 1, nós mencionamos que existem outros tipos de uints: uint8, uint16, uint32, etc. Normalmente não há benefício algum em usar estes subtipos porque Solidity reserva 256 bits de espaço independente do tamanho do uint. Por exemplo, usar uint8 ao invés de uint (uint256) não irá economizar gas algum. Mas há uma exceção para isto: dentro das structs. Se você tiver múltiplas uints dentro de uma struct, usando um tamanho menor de uint quando possível irá permitir o Solidity de empacotar essas variáveis juntas para usar menos espaço. Por exemplo: */ struct NormalStruct { uint a; uint b; uint c; } struct MiniMe { uint32 a; uint32 b; uint c; } // `mini` irá custar menos gas que `normal` porque usar o empacotamento NormalStruct normal = NormalStruct(10, 20, 30); MiniMe mini = MiniMe(10, 20, 30); /** Por essa razão, dentro de uma estrutura você irá querer usar o menor subtipo de integer que você puder. Você também quer juntar tipos de dados idênticos (exemplo: colando um perto do outro dentro da estrutura) então Solidity pode minimizar o espaço requerido para guardar a estrutura. Por exemplo, a estrutura com campos : */ uint c; uint32 a; uint32 b; /** irá custar menos gas que a estrutura com os campos: */ uint32 a; uint c; uint32 b; /** porque o os campos */ uint32 /** estão agrupados. */ /** Economizando Gas com Funções 'View' Maravilha! Agora temos habilidades especiais para zumbis de alto nível, dando aos seus donos um incentivo para subir os níveis. Podemos adicionar mais destas funções depois se quisermos. Vamos adicionar mais uma função: nossa DApp precisa de um método para ver todo o exército de zumbis do usuário - vamos chamá-la de getZombiesByOwner. Esta função só irá precisar ler os dados do blockchain, então nós podemos fazer uma função com a palavra reservada view. Que nós leva a um importante tópico ao falar sobre otimização de gas: Funções observação (View) não custam gas Funções view não custam gas algum quando são chamadas por um usuário externo. Isto porque funções view não mudam absolutamente nada no blockchain - elas somente leem os dados. Então marcar uma função com a palavra reservada view diz a web.js que esta função só precisa consultar o nó local do Ethereum para rodar a função, e isso atualmente não cria transação alguma na blockchain (que teria que rodar em cada nó, e custar gas). Iremos cobrir a configuração da web3.js com um próprio nó mais tarde. Mas agora a grande sacada é que você pode otimizar o gas utilizado na DApp pelos seus usuários usando funções de somente leitura external view sempre que possível. Nota: Se uma função view é chamada internamente de uma outra função no mesmo contrato essa não é uma função view, ela continuara custando gas. Isto porque uma outra função já criou uma transação no Ethereum, e ainda terá que validar em cada nó na rede. Então funções view são de graça somente quando chamadas externamente. */