Skip to content

Latest commit

 

History

History
223 lines (166 loc) · 8.18 KB

10-savinggasview.md

File metadata and controls

223 lines (166 loc) · 8.18 KB
title actions requireLogin material
Economizando Gas com Funções 'View'
verificarResposta
dicas
true
editor
language startingCode answer
sol
zombiehelper.sol zombiefeeding.sol zombiefactory.sol ownable.sol
pragma solidity ^0.4.19; import "./zombiefeeding.sol"; contract ZombieHelper is ZombieFeeding { modifier aboveLevel(uint _level, uint _zombieId) { require(zombies[_zombieId].level >= _level); _; } function changeName(uint _zombieId, string _newName) external aboveLevel(2, _zombieId) { require(msg.sender == zombieToOwner[_zombieId]); zombies[_zombieId].name = _newName; } function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) { require(msg.sender == zombieToOwner[_zombieId]); zombies[_zombieId].dna = _newDna; } // Crie sua função aqui }
pragma solidity ^0.4.19; import "./zombiefactory.sol"; contract KittyInterface { function getKitty(uint256 _id) external view returns ( bool isGestating, bool isReady, uint256 cooldownIndex, uint256 nextActionAt, uint256 siringWithId, uint256 birthTime, uint256 matronId, uint256 sireId, uint256 generation, uint256 genes ); } contract ZombieFeeding is ZombieFactory { KittyInterface kittyContract; function setKittyContractAddress(address _address) external onlyOwner { kittyContract = KittyInterface(_address); } function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) public { require(msg.sender == zombieToOwner[_zombieId]); Zombie storage myZombie = zombies[_zombieId]; _targetDna = _targetDna % dnaModulus; uint newDna = (myZombie.dna + _targetDna) / 2; if (keccak256(_species) == keccak256("kitty")) { newDna = newDna - newDna % 100 + 99; } _createZombie("NoName", newDna); } function feedOnKitty(uint _zombieId, uint _kittyId) public { uint kittyDna; (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId); feedAndMultiply(_zombieId, kittyDna, "kitty"); } }
pragma solidity ^0.4.19; import "./ownable.sol"; contract ZombieFactory is Ownable { event NewZombie(uint zombieId, string name, uint dna); uint dnaDigits = 16; uint dnaModulus = 10 ** dnaDigits; uint cooldownTime = 1 days; struct Zombie { string name; uint dna; uint32 level; uint32 readyTime; } Zombie[] public zombies; mapping (uint => address) public zombieToOwner; mapping (address => uint) ownerZombieCount; function _createZombie(string _name, uint _dna) internal { uint id = zombies.push(Zombie(_name, _dna, 1, uint32(now + cooldownTime))) - 1; zombieToOwner[id] = msg.sender; ownerZombieCount[msg.sender]++; NewZombie(id, _name, _dna); } function _generateRandomDna(string _str) private view returns (uint) { uint rand = uint(keccak256(_str)); return rand % dnaModulus; } function createRandomZombie(string _name) public { require(ownerZombieCount[msg.sender] == 0); uint randDna = _generateRandomDna(_name); randDna = randDna - randDna % 100; _createZombie(_name, randDna); } }
/** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function Ownable() public { owner = msg.sender; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner); _; } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { require(newOwner != address(0)); OwnershipTransferred(owner, newOwner); owner = newOwner; } }
pragma solidity ^0.4.19; import "./zombiefeeding.sol"; contract ZombieHelper is ZombieFeeding { modifier aboveLevel(uint _level, uint _zombieId) { require(zombies[_zombieId].level >= _level); _; } function changeName(uint _zombieId, string _newName) external aboveLevel(2, _zombieId) { require(msg.sender == zombieToOwner[_zombieId]); zombies[_zombieId].name = _newName; } function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) { require(msg.sender == zombieToOwner[_zombieId]); zombies[_zombieId].dna = _newDna; } function getZombiesByOwner(address _owner) external view returns(uint[]) { } }

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.

Vamos testar

Vamos implementar a função que irá retornar todo o exército zumbi do usuário. Mais tarde podemos chamar esta função do web3.js se quisermos mostrar uma página de perfil do usuário e todo o seu exército.

A lógica desta função é um pouco mais complicada então irá tomar alguns capítulos para implementar.

  1. Crie uma nova função chamada getZombiesByOwner. Esta receberá um argumento, um address chamada _owner.

  2. Vamos fazê-la uma função external view, então podemos chamá-la da web3.js sem gastar qualquer gas.

  3. A função deve retornar um uint[] (um array de uint).

Deixe o corpo da função vazio por enquanto, iremos completá-lo no próximo capítulo.