Criar contrato inteligente

O que é um Contrato Inteligente?

Contrato inteligente 📝 são programas simples armazenados em uma rede blockchain.

Você pode dizer que é como um acordo entre duas pessoas na forma de código de computador. As transações em um contrato inteligente são processadas pelo blockchain e armazenadas como um endereço hexadecimal de 42 caracteres com o prefixo "0x"). Tudo isso significa que eles podem ser enviados automaticamente sem a necessidade de terceiros.

🤔 Ainda ficou com duvidas? Pode ver este artigo mais detalhado: O que são contratos inteligentes?

Lembre-se: Eles ficam armazenados em um banco de dados público. E uma vez que um contrato inteligente é implantado, ele não pode ser alterado.

O que é a Solidity?

Solidity é uma das linguagens mais populares usadas para construir contratos inteligentes no Ethereum. É também uma linguagem de programação orientada a objetos.

Veja também: O que é a Solidity e como começar a programar?

Crie seu primeiro contrato inteligente

  1. Abra o RemixIDE a partir daqui .
  2. Clique em Sure depois Done.
  3. Em default_workshop, clique em create new file.
  4. Dê um nome ao seu ficheiro.

Atenção: Neste exmplo o nome do ficheiro é “Hostel.sol”, pois iremos criar um contrato inteligente para simular um contrato entre um cliente e uma estadia no hostel.

Agora você está pronto para escrever seu primeiro contrato inteligente . 🤩

Código do contrato

  1. Você têm que fornecer a versão do solidity no contrato inteligente:
pragma solidity ^0.5.16;
  1. Agora crie o contrato principal:
contract Hostel{
    ...
}
  1. Agora, dentro do contract Hostel{...}siga os passos abaixo.
  2. Crie algumas variáveis ​​onde o contrato inteligente armazenará o valor a pagar address (cadeia hexadecimal de 42 caracteres com prefixo : "0x"​​) do Landlord & the Tenant.
    address payable tenant;
    address payable landlord;
  1. Crie algumas variáveis ​​públicas onde o contrato inteligente armazenará alguns valores inteiros. Para isso, existe um tipo de dados chamado uint(inteiro não assinado de 256 bits)
    uint public no_of_rooms = 0;
    uint public no_of_agreement = 0;
    uint public no_of_rent = 0;
  1. Agora, crie um structure para armazenar detalhes de cada quarto do Hostel como Hostel no.Hostel nameHostel addressNo of total agreementsMonthly rentOne-time security depositLast agreement sign timeVacancyLandlord address, e Current Tenant Address.
    struct Room{
        uint roomid;
        uint agreementid;
        string roomname;
        string roomaddress;
        uint rent_per_month;
        uint securityDeposit;
        uint timestamp;
        bool vacant;
        address payable landlord;
        address payable currentTenant;
    }
  1. map a estrutura anterior com um uint(chamado : room).
mapping(uint => Room) public Room_by_No;
  1. Semelhante ao acima, crie um structure para cada Rental Agreemente mapeie isso com um uint(chamado: agreementid). Isso armazenará detalhes como: Hostel no.Agreement NoHostel nameHostel addressMonthly rentOne-time security depositLockin PeriodAgreement sign timeLandlord address, e Tenant Address.
    struct RoomAgreement{
        uint roomid;
        uint agreementid;
        string Roomname;
        string RoomAddresss;
        uint rent_per_month;
        uint securityDeposit;
        uint lockInPeriod;
        uint timestamp;
        address payable tenantAddress;
        address payable landlordAddress;
    }
mapping(uint => RoomAgreement) public RoomAgreement_by_No;
  1. Agora, crie um structure para cada Rent pagamento e mapeie isso com um uint. Isso armazenará detalhes como: Rent No.Hostel no.Agreement NoHostel nameHostel addressMonthly rentRent payment timeLandlord addressTenant Address.
    struct Rent{
        uint rentno;
        uint roomid;
        uint agreementid;
        string Roomname;
        string RoomAddresss;
        uint rent_per_month;
        uint timestamp;
        address payable tenantAddress;
        address payable landlordAddress;
    }
   mapping(uint => Rent) public Rent_by_No;
  1. Crie alguns modificadores que o ajudarão a verificar algumas coisas antes de executar uma função. require(...);significa que se a condição dada não for satisfeita, a função não será executada e a string dada aparecerá como um código de erro.

O seguinte verificará se o remetente da mensagem é o proprietário.

    modifier onlyLandlord(uint _index) {
        require(msg.sender == Room_by_No[_index].landlord, "Only landlord can access this");
        _;
    }

O seguinte verificará se o remetente da mensagem é alguém, exceto o proprietário.

    modifier notLandLord(uint _index) {
        require(msg.sender != Room_by_No[_index].landlord, "Only Tenant can access this");
        _;
    }

O seguinte irá verificar se o quarto está vago ou não.

    modifier OnlyWhileVacant(uint _index){
        
        require(Room_by_No[_index].vacant == true, "Room is currently Occupied.");
        _;
    }

A seguir, verificará se o inquilino tem o suficiente Etherem sua carteira para pagar o aluguel.

    modifier enoughRent(uint _index) {
        require(msg.value >= uint(Room_by_No[_index].rent_per_month), "Not enough Ether in your wallet");
        _;
    }

A seguir, verificará se o inquilino tem o suficiente Etherem sua carteira para pagar um depósito de segurança único e um mês de aluguel adiantado.

    modifier enoughAgreementfee(uint _index) {
        require(msg.value >= uint(uint(Room_by_No[_index].rent_per_month) + uint(Room_by_No[_index].securityDeposit)), "Not enough Ether in your wallet");
        _;
    }

A seguir, verificará se o endereço do inquilino é o mesmo que assinou o contrato de locação anterior.

    modifier sameTenant(uint _index) {
        require(msg.sender == Room_by_No[_index].currentTenant, "No previous agreement found with you & landlord");
        _;
    }

A seguir, verificará se há tempo restante para o término do contrato.

    modifier AgreementTimesLeft(uint _index) {
        uint _AgreementNo = Room_by_No[_index].agreementid;
        uint time = RoomAgreement_by_No[_AgreementNo].timestamp + RoomAgreement_by_No[_AgreementNo].lockInPeriod;
        require(now < time, "Agreement already Ended");
        _;
    }

A seguir, verificará se 365 dias se passaram após a criação do último contrato.

    modifier AgreementTimesUp(uint _index) {
        uint _AgreementNo = Room_by_No[_index].agreementid;
        uint time = RoomAgreement_by_No[_AgreementNo].timestamp + RoomAgreement_by_No[_AgreementNo].lockInPeriod;
        require(now > time, "Time is left for contract to end");
        _;
    }

O seguinte irá verificar se 30 dias se passaram após o último pagamento.

    modifier RentTimesUp(uint _index) {
        uint time = Room_by_No[_index].timestamp + 30 days;
        require(now >= time, "Time left to pay Rent");
        _;
    }
  1. Agora, crie algumas funções

A função a seguir será usada para adicionar quartos.

    function addRoom(string memory _roomname, string memory _roomaddress, uint _rentcost, uint  _securitydeposit) public {
        require(msg.sender != address(0));
        no_of_rooms ++;
        bool _vacancy = true;
        Room_by_No[no_of_rooms] = Room(no_of_rooms,0,_roomname,_roomaddress, _rentcost,_securitydeposit,0,_vacancy, msg.sender, address(0)); 
        
    }

Agora, crie uma função para assinar o contrato de aluguel de um quarto de hostel entre o proprietário e o inquilino.

Antes de criar a signAgreementfunção, lembre-se do seguinte:

  • A função só será executada se o usuário for Tenant, o que significa que o endereço do usuário e o endereço do proprietário não coincidem.
  • A função só será executada se o usuário tiver ether suficiente (‘ether’ pagável) em sua carteira Ethereum. (Ether suficiente significa = depósito de segurança único + aluguel do 1º mês)

Vamos usar esses modificadores aqui, para que:

  • A função signAgreementsó será executada se o referido quarto estiver vago e o inquilino tiver ether suficiente em sua carteira.

Lembre-se daqueles modificadores no ponto no.10? Use esses modificadores aqui para executar a função a seguir.

    function signAgreement(uint _index) public payable notLandLord(_index) enoughAgreementfee(_index) OnlyWhileVacant(_index) {
        require(msg.sender != address(0));
        address payable _landlord = Room_by_No[_index].landlord;
        uint totalfee = Room_by_No[_index].rent_per_month + Room_by_No[_index].securityDeposit;
        _landlord.transfer(totalfee);
        no_of_agreement++;
        Room_by_No[_index].currentTenant = msg.sender;
        Room_by_No[_index].vacant = false;
        Room_by_No[_index].timestamp = block.timestamp;
        Room_by_No[_index].agreementid = no_of_agreement;
        RoomAgreement_by_No[no_of_agreement]=RoomAgreement(_index,no_of_agreement,Room_by_No[_index].roomname,Room_by_No[_index].roomaddress,Room_by_No[_index].rent_per_month,Room_by_No[_index].securityDeposit,365 days,block.timestamp,msg.sender,_landlord);
        no_of_rent++;
        Rent_by_No[no_of_rent] = Rent(no_of_rent,_index,no_of_agreement,Room_by_No[_index].roomname,Room_by_No[_index].roomaddress,Room_by_No[_index].rent_per_month,now,msg.sender,_landlord);
    }

Agora, crie uma função que o inquilino usará para pagar o aluguel mensal ao proprietário.

Antes de criar a payRentfunção, lembre-se do seguinte:

  • A função só será executada se a morada do utilizador e a morada do inquilino anterior forem iguais, o que significa que o utilizador só pode pagar a renda se tiver assinado um acordo com o senhorio nos últimos 365 dias.
  • A função só será executada se o inquilino tiver pago a renda anterior há mais de um mês.
  • A função só será executada se o usuário tiver ether suficiente (‘ether’ pagável) em sua carteira Ethereum. (éter suficiente = aluguel de quarto suficiente).
    function payRent(uint _index) public payable sameTenant(_index) RentTimesUp(_index) enoughRent(_index){
        require(msg.sender != address(0));
        address payable _landlord = Room_by_No[_index].landlord;
        uint _rent = Room_by_No[_index].rent_per_month;
        _landlord.transfer(_rent);
        Room_by_No[_index].currentTenant = msg.sender;
        Room_by_No[_index].vacant = false;
        no_of_rent++;
        Rent_by_No[no_of_rent] = Rent(no_of_rent,_index,Room_by_No[_index].agreementid,Room_by_No[_index].roomname,Room_by_No[_index].roomaddress,_rent,now,msg.sender,Room_by_No[_index].landlord);
    }

Vamos criar uma função que o proprietário usará para marcar um contrato como concluído.

Antes de criar agreementCompleteda função, lembre-se do seguinte:

  • A função só será executada se o endereço do usuário e o endereço do proprietário forem os mesmos.
  • A função só será executada se o inquilino tiver assinado esse contrato há mais de um ano.function agreementCompleted(uint _index) public payable onlyLandlord(_index) AgreementTimesUp(_index){ require(msg.sender != address(0)); require(Room_by_No[_index].vacant == false, "Room is currently Occupied."); Room_by_No[_index].vacant = true; address payable _Tenant = Room_by_No[_index].currentTenant; uint _securitydeposit = Room_by_No[_index].securityDeposit; _Tenant.transfer(_securitydeposit); }

Vamos criar uma função que o proprietário usará para rescindir um contrato.

Antes de criar agreementTerminateda função, lembre-se do seguinte:

  • A função só será executada se o endereço do usuário e o endereço do proprietário forem os mesmos.
  • A função só será executada se o inquilino tiver assinado esse contrato há menos de um ano.
    function agreementTerminated(uint _index) public onlyLandlord(_index) AgreementTimesLeft(_index){
        require(msg.sender != address(0));
        Room_by_No[_index].vacant = true;
    }

Compilar

Agora, clique na Solidity Compileopção na barra lateral esquerda.

  1. Selecione a versão do compilador0.5.16+
  2. Em seguida, clique emCompile Hostel.sol

Semelhante ao seguinte:

Implantar

Clique na Deploy & Run Transactionsopção na barra lateral esquerda.

  1. Escolha Environment>JavaScript VM (London)
  2. Agora clique emDeploy

🎉 Parabéns, seu contrato inteligente foi implantado. 🎉

Transações de amostra

Lembre-se que sempre que uma transação está sendo executada, ela armazena todos os detalhes em uma hashchave única.

Agora, sob Deployed Contractclique em> HOSTEL AT ..... (MEMORY)

  1. Clique no icone V (menu suspenso) da addRoomfunção.
  2. Preencha os detalhes.

Semelhante ao seguinte:

Nota: Você está inserindo seus dados em weinot in ether(1 ether = 1000000000000000000 wei)

  1. Em seguida, clique emtransact🎉 Parabéns, você adicionou com sucesso seu 1º quarto no contrato. 🎉(Você pode encontrar o mesmo no terminal também.)Agora, o proprietário do quarto é o seu 1º endereço de éter. (Aquele com éter de teste 99,99 na carteira.)
  2. Altere o Account Addressno menu suspenso. (Escolha qualquer um, exceto aquele com 99,99 éter)

  1. Adicione o valor total que você escolheu anteriormente como (custo do aluguel + depósito de segurança)
  2. E então, no menu suspenso wei, escolhaether

  1. Role para baixo e clique em signAgreement, digite 1e pressionesignAgreementVocê pode verificar o mesmo digitando RoomAgreementNo:1

🎉 Parabéns, você assinou com sucesso seu 1º contrato. 🎉

Todas as suas transações são mostradas no arquivo terminal.

Agora, você pode verificar isso verificando o etherendereço da sua conta.

🤔 Ficaste com duvidas? abaixo está um video a explicar como criar um contrato inteligente com o solidity.

Vantagens dos contratos inteligentes

Agora você pode perguntar: “qual é o uso de contratos inteligentes quando existem vários métodos centralizados?”

Deixe-me explicar algumas vantagens dos contratos inteligentes sobre sistemas centralizados:

  1. Aqui os dados não podem ser alterados ou adulterados. Portanto, é quase impossível que atores mal-intencionados manipulem dados.
  2. É completamente descentralizado.
  3. Ao contrário de qualquer carteira de pagamento centralizada, você não precisa pagar nenhuma porcentagem de comissão a um intermediário para realizar transações.

Armazenamento e outros

Você também pode perguntar “como todas as transações são registradas?”

É preciso lembrar que os contratos inteligentes armazenam dados em um bloco do blockchain e todas as transações são armazenadas com uma hashchave exclusiva.

No Remix IDE, você pode baixar o histórico completo de transações como um arquivo JSON. Para isso, siga estes passos:

  1. Clique Deploy & Run Transaction
  2. Em seguida, expanda o Transactions Recorded (..) Vmenu suspenso.
  3. Em seguida, clique no Save.
  4. Pressione ok.

Taxa de gás

Você deve ter notado que sempre que uma transação é executada, algumas wei são deduzidas de sua carteira ether.

Chama-se taxa de gás , que é o pagamento feito pelos usuários para compensar a energia de computação necessária para processar e validar as transações.

À medida que mais mineradores de Ethereum surgirem no futuro próximo, o gas feevalor diminuirá em uma relação inversa.

bitcoin
Bitcoin (BTC) 19.709,68 0,09%
ethereum
Ethereum (ETH) 1.369,60 0,33%
tether
Tether (USDT) 1,03 0,04%
usd-coin
USD Coin (USDC) 1,03 0,13%
bnb
BNB (BNB) 287,09 1,05%
xrp
XRP (XRP) 0,506091 0,82%
binance-usd
Binance USD (BUSD) 1,03 0,26%
cardano
Cardano (ADA) 0,473900 1,01%
solana
Solana (SOL) 34,73 3,06%
dogecoin
Dogecoin (DOGE) 0,064914 5,20%
polkadot
Polkadot (DOT) 6,54 1,65%
shiba-inu
Shiba Inu (SHIB) 0,000012 0,28%
dai
Dai (DAI) 1,03 0,09%
staked-ether
Lido Staked Ether (STETH) 1.362,22 0,29%
matic-network
Polygon (MATIC) 0,785605 1,75%
tron
TRON (TRX) 0,062035 0,60%
avalanche-2
Avalanche (AVAX) 18,30 1,98%
wrapped-bitcoin
Wrapped Bitcoin (WBTC) 19.709,07 0,06%
uniswap
Uniswap (UNI) 6,10 1,78%
cosmos
Cosmos Hub (ATOM) 14,40 1,03%
leo-token
LEO Token (LEO) 4,47 0,48%
ethereum-classic
Ethereum Classic (ETC) 30,11 1,44%
chainlink
Chainlink (LINK) 8,27 4,47%
litecoin
Litecoin (LTC) 55,89 1,69%
okb
OKB (OKB) 15,74 0,44%
ftx-token
FTX (FTT) 24,63 0,22%
stellar
Stellar (XLM) 0,123337 3,09%
crypto-com-chain
Cronos (CRO) 0,120904 3,36%
near
NEAR Protocol (NEAR) 3,87 2,29%
algorand
Algorand (ALGO) 0,402017 2,43%
monero
Monero (XMR) 148,36 1,73%
bitcoin-cash
Bitcoin Cash (BCH) 120,98 2,96%
flow
Flow (FLOW) 1,74 1,33%
apecoin
ApeCoin (APE) 5,70 1,48%
vechain
VeChain (VET) 0,023847 2,12%
chain-2
Chain (XCN) 0,079070 1,09%
filecoin
Filecoin (FIL) 5,80 1,92%
terra-luna
Terra Luna Classic (LUNC) 0,000236 7,06%
internet-computer
Internet Computer (ICP) 6,19 2,39%
quant-network
Quant (QNT) 119,43 0,73%
hedera-hashgraph
Hedera (HBAR) 0,063485 0,57%
chiliz
Chiliz (CHZ) 0,274720 0,74%
tezos
Tezos (XTZ) 1,56 0,95%
frax
Frax (FRAX) 1,03 0,05%
the-sandbox
The Sandbox (SAND) 0,920961 3,30%
decentraland
Decentraland (MANA) 0,735394 1,71%
eos
EOS (EOS) 1,25 1,50%
axie-infinity
Axie Infinity (AXS) 13,27 3,29%
theta-token
Theta Network (THETA) 1,16 0,96%
elrond-erd-2
Elrond (EGLD) 49,92 1,10%