Nesse artigo iremos abordar sobre como interagir com interfaces, funções pagáveis e níveis de visibilidade em funções do seu contrato inteligente.
Falaremos sobre visibility
, interface
e payable
.
Visibility (Visibilidade)
Funções e variáveis de estado devem declarar se são acessíveis por outros contratos.
As funções podem ser declaradas como:
public
- pode ser chamada por qualquer contrato, endereços e contasprivate
- pode ser chamada apenas dentro do contrato que a definiuinternal
- pode ser chamada apenas dentro do contrato que herda uma funçãointernal
external
- pode ser chamada apenas fora do contrato, por outros contratos, endereços e contas
As variáveis de estado podem ser declaradas como public
, private
ou internal
mas não external
.
// SPDX-License-Identifier: MITpragma solidity ^0.8.13;contract Base {// A função privada só pode ser chamada// de dentro deste contrato// Os contratos que herdam esse contrato não podem chamar essa função.function privateFunc() private pure returns (string memory) {return "função privada chamada";}function testPrivateFunc() public pure returns (string memory) {return privateFunc();}// A função interna pode ser chamada// - dentro deste contrato// - dentro de contratos que herdam este contratofunction internalFunc() internal pure returns (string memory) {return "função interna chamada";}function testInternalFunc() public pure virtual returns (string memory) {return internalFunc();}// Funções públicas podem ser chamadas// - dentro deste contrato// - dentro de contratos que herdam este contrato// - por outros contratos, endereços e contasfunction publicFunc() public pure returns (string memory) {return "função pública chamada";}// Funções externas só podem ser chamadas// - por outros contratos, endereços e contasfunction externalFunc() external pure returns (string memory) {return "função externa chamada";}// Esta função não irá compilar pois estamos tentando chamar// uma função externa aqui.// function testExternalFunc() public pure returns (string memory) {// return externalFunc();// }// Variáveis de estadostring private privateVar = "variável privada";string internal internalVar = "variável interna";string public publicVar = "variável pública";// As variáveis de estado não podem ser externas,// portanto, esse código não será compilado.// string external externalVar = "my external variable";}contract Child is Base {// Os contratos herdados não têm acesso// a funções privadas e variáveis de estado.// function testPrivateFunc() public pure returns (string memory) {// return privateFunc();// }// Chamada de função interna podem ser// realizadas dentro de contratos filho.function testInternalFunc() public pure override returns (string memory) {return internalFunc();}}
Interface
Você pode interagir com outros contratos através da declaração de uma Interface
.
Interface
- não pode ter nenhuma função implementada
- pode herdar de outras interfaces
- todas as funções declaradas devem ser externas
- não pode declarar um construtor
- não pode declarar variáveis de estado
// SPDX-License-Identifier: MITpragma solidity ^0.8.13;contract Counter {uint public count;function increment() external {count += 1;}}// Declaramos a Interface ICounter// Através dela podemos acessar as funções count e incrementinterface ICounter {function count() external view returns (uint);function increment() external;}contract MyContract {function incrementCounter(address _counter) external {ICounter(_counter).increment();}function getCount(address _counter) external view returns (uint) {return ICounter(_counter).count();}}// Exemplo utilizando o Uniswap// Declaração da Interface UniswapV2Factory// Através dela podemos acessar a função getPairinterface UniswapV2Factory {function getPair(address tokenA, address tokenB)externalviewreturns (address pair);}// Declaração da Interface UniswapV2Pair// Através dela podemos acessar a função getReservesinterface UniswapV2Pair {function getReserves()externalviewreturns (uint112 reserve0,uint112 reserve1,uint32 blockTimestampLast);}// Declaração do Contrato UniswapExample// No contrato abaixo podemos ver a interação// do contrato com as duas Interfaces acimacontract UniswapExample {address private factory = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;address private dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;address private weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;function getTokenReserves() external view returns (uint, uint) {// Aqui utilizamos a Interface UniswapV2Factory para obter// o endereço do contrato do par dai e weth através da função getPairaddress pair = UniswapV2Factory(factory).getPair(dai, weth);// Aqui utilizamos a Interface UniswapV2Pair para obter os dois// valores uint, reserve0 e reserve1 através da função getReserves(uint reserve0, uint reserve1, ) = UniswapV2Pair(pair).getReserves();return (reserve0, reserve1);}}
Payable (Pagável)
Funções e endereços declarados como payable
podem receber ether
.
// SPDX-License-Identifier: MITpragma solidity ^0.8.13;contract Payable {// Endereço definido com payable poderá receber Etheraddress payable public owner;// Construtor definido com payable poderá receber Etherconstructor() payable {owner = payable(msg.sender);}// Função para depositar Ether neste contrato.// Chame esta função junto com algum Ether.// O saldo deste contrato será atualizado automaticamente.function deposit() public payable {}// Chame esta função junto com algum Ether.// A função lançará um erro, pois esta função não é pagável.function notPayable() public {}// Função para retirar todo o Ether deste contrato.function withdraw() public {// obtém a quantidade de Ether armazenada neste contratouint amount = address(this).balance;// enviar todo o Ether para o proprietário// O dono do contrato pode receber Ether desde que o// endereço esteja definido com payable(bool success, ) = owner.call{value: amount}("");require(success, "Falha ao enviar Ether");}// Função para transferir Ether deste contrato para o endereço de entradafunction transfer(address payable _to, uint _amount) public {// Observe que "to" é declarado como pagável 'payable'(bool success, ) = _to.call{value: _amount}("");require(success, "Falha ao enviar Ether");}}