Pular para o conteúdo principal
Change page

Anatomia dos contratos inteligentes

Última atualização da página: 23 de fevereiro de 2026

Um contrato inteligente (smart contract) é um programa executado em um endereço na Ethereum. Eles são compostos por dados e funções que podem ser executadas ao receber uma transação. Veja aqui uma visão geral do que compõe um contrato inteligente.

Pré-requisitos

Certifique-se de que leu sobre contratos inteligentes primeiro. Este documento presume que você já está familiarizado com linguagens de programação como JavaScript ou Python.

Dados

Quaisquer dados de contrato devem ser atribuídos a um local: storage ou memory. É caro modificar o armazenamento em um contrato inteligente, então você precisa considerar onde seus dados devem estar no ar.

Armazenamento

Dados persistentes são referidos como armazenamento e são representados por variáveis de estado. Esses valores são armazenados permanentemente na blockchain. É necessário declarar o tipo para que o contrato possa manter um registro de quanto espaço na blockchain será necessário quando ele compilar.

1// Exemplo de Solidity
2contract SimpleStorage {
3 uint storedData; // Variável de estado
4 // ...
5}
1# Exemplo Vyper
2storedData: int128

Se você já programou linguagens orientadas a objetos, provavelmente você estará familiarizado com a maioria dos tipos. No entanto, address (endereço) deve ser novidade para você se você é novo no desenvolvimento para Ethereum.

Um tipo address pode conter um endereço Ethereum que equivale a 20 bytes ou 160 bits. Ele retorna em hexadecimal com um 0 à frente.

Outros tipos incluem:

  • booleano
  • inteiro
  • números de ponto fixo
  • arrays de bytes de tamanho fixo
  • arrays de bytes de tamanho dinâmico
  • literais racionais e inteiros
  • literais de string
  • literais hexadecimais
  • enums

Para mais explicação, dê uma olhada na documentação:

Memória

Valores que são armazenados apenas para a duração da execução da função de contratos são chamadas de variáveis de memória. Como estes não são armazenados permanentemente na blockchain, são muito mais baratos de usar.

Saiba mais sobre como a EVM armazena dados (Storage, Memory e a Pilha) nos documentos do Solidity (opens in a new tab).

Variáveis de ambiente

Além das variáveis definidas no seu contrato, existem algumas variáveis globais especiais. Elas são usadas principalmente para fornecer informações sobre a blockchain (cadeia de blocos) ou transação atual.

Exemplos:

PropriedadeVariável de estadoDescrição
block.timestampuint256Data/hora de início do bloco atual
msg.senderendereçoRemetente da mensagem (chamada atual)

Funções

Da forma mais simplista, funções podem obter informação ou um conjunto de informações em resposta a entrada de transações.

Existem dois tipos de chamadas de função:

  • internal – estas não criam uma chamada de EVM
    • As funções e variáveis de estado internas só podem ser acessadas internamente (ou seja, de dentro do contrato atual ou dos contratos que derivam dele)
  • external – estas criam uma chamada de EVM
    • Funções externas fazem parte da interface do contrato, o que significa que elas podem ser chamadas a partir de outros contratos e através de transações. Uma função externa f não pode ser chamada internamente (ou seja, f() não funciona, mas this.f() funciona).

Elas também podem ser public ou private

  • As funções public podem ser chamadas internamente de dentro do contrato ou externamente por meio de mensagens
  • As funções private são visíveis apenas para o contrato em que são definidas e não em contratos derivados

Tanto funções quanto variáveis de estado podem ser tornadas públicas ou privadas

Aqui está uma função para atualizar uma variável de estado em um contrato:

1// Exemplo de Solidity
2function update_name(string value) public {
3 dapp_name = value;
4}
  • O parâmetro value do tipo string é passado para a função: update_name
  • Ela é declarada como public, o que significa que qualquer pessoa pode acessá-la
  • Ela não é declarada como view, portanto, pode modificar o estado do contrato

Funções de visualização

Essas funções prometem não modificar o estado dos dados do contrato. Exemplos comuns são funções "obter" – você pode usar isso para receber o saldo de um usuário, por exemplo.

1// Exemplo
2function balanceOf(address _owner) public view return (uint256 _balance) {
3 return ownerPizzaCount[_owner];
4}
1dappName: public(string)
2
3@view
4@public
5def readName() -> string:
6 return dappName

O que é considerado como modificar estado:

  1. Escrevendo variáveis de estado.
  2. Emitindo eventos (opens in a new tab).
  3. Criando outros contratos (opens in a new tab).
  4. Usando selfdestruct.
  5. Enviando ether por chamadas.
  6. Chamando qualquer função não marcada como view ou pure.
  7. Usando chamadas de baixo nível.
  8. Usando montagem em linha que contém certos códigos.

Funções de construtor

As funções constructor são executadas apenas uma vez quando o contrato é implantado pela primeira vez. Assim como o constructor em muitas linguagens de programação baseadas em classes, essas funções geralmente inicializam variáveis de estado para seus valores especificados.

1// Exemplo de Solidity
2// Inicializa os dados do contrato, definindo o `owner`
3// para o endereço do criador do contrato.
4constructor() public {
5 // Todos os contratos inteligentes dependem de transações externas para acionar suas funções.
6 // `msg` é uma variável global que inclui dados relevantes sobre a transação em questão,
7 // como o endereço do remetente e o valor de ETH incluído na transação.
8 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
9 owner = msg.sender;
10}
Exibir tudo
1# Exemplo Vyper
2
3@external
4def __init__(_beneficiary: endereço, _bidding_time: uint256):
5 mesmo. eneficiário = _beneficiário
6 self.auctionStart = block.timestamp
7 self.auctionEnd = self.auctionStart + _bidding_time

Funções incorporadas

Além das variáveis definidas no seu contrato, existem algumas variáveis globais especiais. O exemplo mais óbvio é:

  • address.send() – Solidity
  • send(address) – Vyper

Estes permitem contratos para enviar ETH para outras contas.

Escrevendo funções

Sua função precisa:

  • variável e tipo de parâmetro (se aceitar parâmetros)
  • declaração de interno/externo
  • declaração de puro/visualização/pagável
  • tipo de retorno (se ele retornar um valor)
1pragma solidity >=0.4.0 <=0.6.0;
2
3contract ExampleDapp {
4 string dapp_name; // variável de estado
5
6 // Chamado quando o contrato é implantado e inicializa o valor
7 constructor() public {
8 dapp_name = "Meu dapp de Exemplo";
9 }
10
11 // Função Get
12 function read_name() public view returns(string) {
13 return dapp_name;
14 }
15
16 // Função Set
17 function update_name(string value) public {
18 dapp_name = value;
19 }
20}
Exibir tudo

Um contrato completo pode parecer algo assim. Aqui, a função constructor fornece um valor inicial para a variável dapp_name.

Eventos e logs

Os eventos permitem que seu contrato inteligente se comunique com seu front-end ou outros aplicativos que se inscrevem para recebê-los. Uma vez que uma transação é validada e adicionada a um bloco, os contratos inteligentes podem emitir eventos e registrar informações, que o front-end pode processar e utilizar.

Exemplos anotados

Estes são alguns exemplos escritos em Solidity. Se você quiser brincar com o código, pode interagir com eles no Remix (opens in a new tab).

Olá, mundo

1// Especifica a versão do Solidity, usando versionamento semântico.
2// Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
3pragma solidity ^0.5.10;
4
5// Define um contrato chamado `HelloWorld`.
6// Um contrato é um conjunto de funções e dados (seu estado).
7// Uma vez implantado, um contrato reside em um endereço específico na blockchain Ethereum.
8// Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
9contract HelloWorld {
10
11 // Declara uma variável de estado `message` do tipo `string`.
12 // Variáveis de estado são variáveis cujos valores são armazenados permanentemente no armazenamento do contrato.
13 // A palavra-chave `public` torna as variáveis acessíveis de fora de um contrato
14 // e cria uma função que outros contratos ou clientes podem chamar para acessar o valor.
15 string public message;
16
17 // Semelhante a muitas linguagens de programação orientadas a objetos baseadas em classes, um construtor é
18 // uma função especial que é executada apenas na criação do contrato.
19 // Construtores são usados para inicializar os dados do contrato.
20 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
21 constructor(string memory initMessage) public {
22 // Aceita um argumento de string `initMessage` e define o valor
23 // na variável de armazenamento `message` do contrato).
24 message = initMessage;
25 }
26
27 // Uma função pública que aceita um argumento de string
28 // e atualiza a variável de armazenamento `message`.
29 function update(string memory newMessage) public {
30 message = newMessage;
31 }
32}
Exibir tudo

Token

1pragma solidity ^0.5.10;
2
3contract Token {
4 // Um `address` é comparável a um endereço de e-mail - ele é usado para identificar uma conta na Ethereum.
5 // Endereços podem representar um contrato inteligente ou contas externas (de usuário).
6 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/types.html#address
7 address public owner;
8
9 // Um `mapping` é essencialmente uma estrutura de dados de tabela de hash.
10 // Este `mapping` atribui um inteiro sem sinal (o saldo do token) a um endereço (o detentor do token).
11 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types
12 mapping (address => uint) public balances;
13
14 // Eventos permitem o registro de atividades na blockchain.
15 // Clientes Ethereum podem ouvir eventos para reagir a mudanças de estado do contrato.
16 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events
17 event Transfer(address from, address to, uint amount);
18
19 // Inicializa os dados do contrato, definindo o `owner`
20 // para o endereço do criador do contrato.
21 constructor() public {
22 // Todos os contratos inteligentes dependem de transações externas para acionar suas funções.
23 // `msg` é uma variável global que inclui dados relevantes sobre a transação em questão,
24 // como o endereço do remetente e o valor de ETH incluído na transação.
25 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
26 owner = msg.sender;
27 }
28
29 // Cria uma quantidade de novos tokens e os envia para um endereço.
30 function mint(address receiver, uint amount) public {
31 // `require` é uma estrutura de controle usada para impor certas condições.
32 // Se uma instrução `require` for avaliada como `false`, uma exceção é acionada,
33 // que reverte todas as alterações feitas no estado durante a chamada atual.
34 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
35
36 // Somente o proprietário do contrato pode chamar esta função
37 require(msg.sender == owner, "Você não é o proprietário.");
38
39 // Impõe uma quantidade máxima de tokens
40 require(amount < 1e60, "Emissão máxima excedida");
41
42 // Aumenta o saldo de `receiver` em `amount`
43 balances[receiver] += amount;
44 }
45
46 // Envia uma quantidade de tokens existentes de qualquer chamador para um endereço.
47 function transfer(address receiver, uint amount) public {
48 // O remetente deve ter tokens suficientes para enviar
49 require(amount <= balances[msg.sender], "Saldo insuficiente.");
50
51 // Ajusta os saldos de token dos dois endereços
52 balances[msg.sender] -= amount;
53 balances[receiver] += amount;
54
55 // Emite o evento definido anteriormente
56 emit Transfer(msg.sender, receiver, amount);
57 }
58}
Exibir tudo

Ativo digital exclusivo

1pragma solidity ^0.5.10;
2
3// Importa símbolos de outros arquivos para o contrato atual.
4// Neste caso, uma série de contratos de ajuda da OpenZeppelin.
5// Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files
6
7import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol";
8import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
9import "../node_modules/@openzeppelin/contracts/introspection/ERC165.sol";
10import "../node_modules/@openzeppelin/contracts/math/SafeMath.sol";
11
12// A palavra-chave `is` é usada para herdar funções e palavras-chave de contratos externos.
13// Neste caso, `CryptoPizza` herda dos contratos `IERC721` e `ERC165`.
14// Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance
15contract CryptoPizza is IERC721, ERC165 {
16 // Usa a biblioteca SafeMath do OpenZeppelin para realizar operações aritméticas com segurança.
17 // Saiba mais: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath
18 using SafeMath for uint256;
19
20 // Variáveis de estado constantes em Solidity são semelhantes a outras linguagens
21 // mas você deve atribuir a partir de uma expressão que é constante em tempo de compilação.
22 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables
23 uint256 constant dnaDigits = 10;
24 uint256 constant dnaModulus = 10 ** dnaDigits;
25 bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
26
27 // Tipos de estrutura permitem que você defina seu próprio tipo
28 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs
29 struct Pizza {
30 string name;
31 uint256 dna;
32 }
33
34 // Cria uma matriz vazia de estruturas Pizza
35 Pizza[] public pizzas;
36
37 // Mapeamento do ID da pizza para o endereço do seu proprietário
38 mapping(uint256 => address) public pizzaToOwner;
39
40 // Mapeamento do endereço do proprietário para o número de tokens possuídos
41 mapping(address => uint256) public ownerPizzaCount;
42
43 // Mapeamento do ID do token para o endereço aprovado
44 mapping(uint256 => address) pizzaApprovals;
45
46 // Você pode aninhar mapeamentos, este exemplo mapeia o proprietário para as aprovações do operador
47 mapping(address => mapping(address => bool)) private operatorApprovals;
48
49 // Função interna para criar uma Pizza aleatória a partir de uma string (nome) e DNA
50 function _createPizza(string memory _name, uint256 _dna)
51 // A palavra-chave `internal` significa que esta função só é visível
52 // dentro deste contrato e dos contratos que derivam deste contrato
53 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters
54 internal
55 // `isUnique` é um modificador de função que verifica se a pizza já existe
56 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers
57 isUnique(_name, _dna)
58 {
59 // Adiciona a Pizza à matriz de Pizzas e obtém o id
60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);
61
62 // Verifica se o proprietário da Pizza é o mesmo que o usuário atual
63 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
64
65 // note que address(0) é o endereço zero,
66 // indicando que pizza[id] ainda não foi alocada para um usuário em particular.
67
68 assert(pizzaToOwner[id] == address(0));
69
70 // Mapeia a Pizza para o proprietário
71 pizzaToOwner[id] = msg.sender;
72 ownerPizzaCount[msg.sender] = SafeMath.add(
73 ownerPizzaCount[msg.sender],
74 1
75 );
76 }
77
78 // Cria uma Pizza aleatória a partir de uma string (nome)
79 function createRandomPizza(string memory _name) public {
80 uint256 randDna = generateRandomDna(_name, msg.sender);
81 _createPizza(_name, randDna);
82 }
83
84 // Gera DNA aleatório a partir de uma string (nome) e do endereço do proprietário (criador)
85 function generateRandomDna(string memory _str, address _owner)
86 public
87 // As funções marcadas como `pure` prometem não ler ou modificar o estado
88 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions
89 pure
90 returns (uint256)
91 {
92 // Gera um uint aleatório a partir de uma string (nome) + endereço (proprietário)
93 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +
94 uint256(_owner);
95 rand = rand % dnaModulus;
96 return rand;
97 }
98
99 // Retorna uma matriz de Pizzas encontradas pelo proprietário
100 function getPizzasByOwner(address _owner)
101 public
102 // Funções marcadas como `view` prometem não modificar o estado
103 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions
104 view
105 returns (uint256[] memory)
106 {
107 // Usa o local de armazenamento `memory` para armazenar valores apenas para o
108 // ciclo de vida desta chamada de função.
109 // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack
110 uint256[] memory result = new uint256[](ownerPizzaCount[_owner]);
111 uint256 counter = 0;
112 for (uint256 i = 0; i < pizzas.length; i++) {
113 if (pizzaToOwner[i] == _owner) {
114 result[counter] = i;
115 counter++;
116 }
117 }
118 return result;
119 }
120
121 // Transfere a Pizza e a propriedade para outro endereço
122 function transferFrom(address _from, address _to, uint256 _pizzaId) public {
123 require(_from != address(0) && _to != address(0), "Endereço inválido.");
124 require(_exists(_pizzaId), "A pizza não existe.");
125 require(_from != _to, "Não é possível transferir para o mesmo endereço.");
126 require(_isApprovedOrOwner(msg.sender, _pizzaId), "O endereço não está aprovado.");
127
128 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);
129 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);
130 pizzaToOwner[_pizzaId] = _to;
131
132 // Emite evento definido no contrato IERC721 importado
133 emit Transfer(_from, _to, _pizzaId);
134 _clearApproval(_to, _pizzaId);
135 }
136
137 /**
138 * Transfere com segurança a propriedade de um determinado ID de token para outro endereço
139 * Se o endereço de destino for um contrato, ele deverá implementar `onERC721Received`,
140 * que é chamado após uma transferência segura e retorna o valor mágico
141 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
142 * caso contrário, a transferência será revertida.
143 */
144 function safeTransferFrom(address from, address to, uint256 pizzaId)
145 public
146 {
147 // solium-disable-next-line arg-overflow
148 this.safeTransferFrom(from, to, pizzaId, "");
149 }
150
151 /**
152 * Transfere com segurança a propriedade de um determinado ID de token para outro endereço
153 * Se o endereço de destino for um contrato, ele deverá implementar `onERC721Received`,
154 * que é chamado após uma transferência segura e retorna o valor mágico
155 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
156 * caso contrário, a transferência será revertida.
157 */
158 function safeTransferFrom(
159 address from,
160 address to,
161 uint256 pizzaId,
162 bytes memory _data
163 ) public {
164 this.transferFrom(from, to, pizzaId);
165 require(_checkOnERC721Received(from, to, pizzaId, _data), "Deve implementar onERC721Received.");
166 }
167
168 /**
169 * Função interna para invocar `onERC721Received` em um endereço de destino
170 * A chamada não é executada se o endereço de destino não for um contrato
171 */
172 function _checkOnERC721Received(
173 address from,
174 address to,
175 uint256 pizzaId,
176 bytes memory _data
177 ) internal returns (bool) {
178 if (!isContract(to)) {
179 return true;
180 }
181
182 bytes4 retval = IERC721Receiver(to).onERC721Received(
183 msg.sender,
184 from,
185 pizzaId,
186 _data
187 );
188 return (retval == _ERC721_RECEIVED);
189 }
190
191 // Queima uma Pizza - destrói o Token completamente
192 // O modificador de função `external` significa que esta função é
193 // parte da interface do contrato e outros contratos podem chamá-la
194 function burn(uint256 _pizzaId) external {
195 require(msg.sender != address(0), "Endereço inválido.");
196 require(_exists(_pizzaId), "A pizza não existe.");
197 require(_isApprovedOrOwner(msg.sender, _pizzaId), "O endereço não está aprovado.");
198
199 ownerPizzaCount[msg.sender] = SafeMath.sub(
200 ownerPizzaCount[msg.sender],
201 1
202 );
203 pizzaToOwner[_pizzaId] = address(0);
204 }
205
206 // Retorna a contagem de Pizzas por endereço
207 function balanceOf(address _owner) public view returns (uint256 _balance) {
208 return ownerPizzaCount[_owner];
209 }
210
211 // Retorna o proprietário da Pizza encontrado por id
212 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {
213 address owner = pizzaToOwner[_pizzaId];
214 require(owner != address(0), "ID de pizza inválido.");
215 return owner;
216 }
217
218 // Aprova outro endereço para transferir a propriedade da Pizza
219 function approve(address _to, uint256 _pizzaId) public {
220 require(msg.sender == pizzaToOwner[_pizzaId], "Deve ser o proprietário da Pizza.");
221 pizzaApprovals[_pizzaId] = _to;
222 emit Approval(msg.sender, _to, _pizzaId);
223 }
224
225 // Retorna o endereço aprovado para uma Pizza específica
226 function getApproved(uint256 _pizzaId)
227 public
228 view
229 returns (address operator)
230 {
231 require(_exists(_pizzaId), "A pizza não existe.");
232 return pizzaApprovals[_pizzaId];
233 }
234
235 /**
236 * Função privada para limpar a aprovação atual de um determinado ID de token
237 * Reverte se o endereço fornecido não for de fato o proprietário do token
238 */
239 function _clearApproval(address owner, uint256 _pizzaId) private {
240 require(pizzaToOwner[_pizzaId] == owner, "Deve ser o proprietário da pizza.");
241 require(_exists(_pizzaId), "A pizza não existe.");
242 if (pizzaApprovals[_pizzaId] != address(0)) {
243 pizzaApprovals[_pizzaId] = address(0);
244 }
245 }
246
247 /*
248 * Define ou cancela a aprovação de um determinado operador
249 * Um operador tem permissão para transferir todos os tokens do remetente em seu nome
250 */
251 function setApprovalForAll(address to, bool approved) public {
252 require(to != msg.sender, "Não é possível aprovar o próprio endereço");
253 operatorApprovals[msg.sender][to] = approved;
254 emit ApprovalForAll(msg.sender, to, approved);
255 }
256
257 // Informa se um operador é aprovado por um determinado proprietário
258 function isApprovedForAll(address owner, address operator)
259 public
260 view
261 returns (bool)
262 {
263 return operatorApprovals[owner][operator];
264 }
265
266 // Assume a propriedade da Pizza - apenas para usuários aprovados
267 function takeOwnership(uint256 _pizzaId) public {
268 require(_isApprovedOrOwner(msg.sender, _pizzaId), "O endereço não está aprovado.");
269 address owner = this.ownerOf(_pizzaId);
270 this.transferFrom(owner, msg.sender, _pizzaId);
271 }
272
273 // Verifica se a Pizza existe
274 function _exists(uint256 pizzaId) internal view returns (bool) {
275 address owner = pizzaToOwner[pizzaId];
276 return owner != address(0);
277 }
278
279 // Verifica se o endereço é o proprietário ou se está aprovado para transferir a Pizza
280 function _isApprovedOrOwner(address spender, uint256 pizzaId)
281 internal
282 view
283 returns (bool)
284 {
285 address owner = pizzaToOwner[pizzaId];
286 // Disable solium check because of
287 // https://github.com/duaraghav8/Solium/issues/175
288 // solium-disable-next-line operator-whitespace
289 return (spender == owner ||
290 this.getApproved(pizzaId) == spender ||
291 this.isApprovedForAll(owner, spender));
292 }
293
294 // Verifica se a Pizza é única e ainda não existe
295 modifier isUnique(string memory _name, uint256 _dna) {
296 bool result = true;
297 for (uint256 i = 0; i < pizzas.length; i++) {
298 if (
299 keccak256(abi.encodePacked(pizzas[i].name)) ==
300 keccak256(abi.encodePacked(_name)) &&
301 pizzas[i].dna == _dna
302 ) {
303 result = false;
304 }
305 }
306 require(result, "Uma pizza com esse nome já existe.");
307 _;
308 }
309
310 // Retorna se o endereço de destino é um contrato
311 function isContract(address account) internal view returns (bool) {
312 uint256 size;
313 // Atualmente não há uma maneira melhor de verificar se há um contrato em um endereço
314 // do que verificar o tamanho do código nesse endereço.
315 // Veja https://ethereum.stackexchange.com/a/14016/36603
316 // para mais detalhes sobre como isso funciona.
317 // TODO Verificar isso novamente antes do lançamento do Serenity, porque todos os endereços serão
318 // contratos então.
319 // solium-disable-next-line security/no-inline-assembly
320 assembly {
321 size := extcodesize(account)
322 }
323 return size > 0;
324 }
325}
Exibir tudo

Leitura adicional

Confira a documentação sobre Solidity e Vyper para ter uma visão geral mais completa dos contratos inteligentes:

Este artigo foi útil?