Created
September 4, 2025 18:00
-
-
Save rpaskin/f221d5fbcf80f838ac60fcc4a48c76e3 to your computer and use it in GitHub Desktop.
Contrato de Prestação de Serviços com Pagamento em Escrow (Blockchain)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.20; | |
| /// @title ServiceEscrow - Exemplo didático de escrow para prestação de serviços | |
| /// @notice Contrato simples: buyer deposita; se aceitar no prazo, paga seller; se prazo expirar sem aceite, reembolsa buyer. | |
| contract ServiceEscrow { | |
| enum State { Created, Funded, Completed, Refunded } | |
| address public buyer; // Contratante | |
| address payable public seller; // Prestadora | |
| uint256 public price; // Valor em wei | |
| uint256 public deadline; // Timestamp limite (segundos desde epoch) | |
| State public state; | |
| bool private locked; // Trava simples anti-reentrância | |
| event Funded(address indexed buyer, uint256 amount); | |
| event Paid(address indexed seller, uint256 amount); | |
| event Refunded(address indexed buyer, uint256 amount); | |
| modifier onlyBuyer() { | |
| require(msg.sender == buyer, "Apenas a contratante"); | |
| _; | |
| } | |
| modifier inState(State s) { | |
| require(state == s, "Estado invalido"); | |
| _; | |
| } | |
| modifier nonReentrant() { | |
| require(!locked, "Reentrancia"); | |
| locked = true; | |
| _; | |
| locked = false; | |
| } | |
| /// @param _buyer Endereco da contratante | |
| /// @param _seller Endereco da prestadora (pagamento sera enviado aqui) | |
| /// @param _price Valor fixo do contrato em wei | |
| /// @param _deadline Timestamp limite para aceite (deve ser > block.timestamp) | |
| constructor(address _buyer, address payable _seller, uint256 _price, uint256 _deadline) { | |
| require(_buyer != address(0) && _seller != address(0), "Enderecos invalidos"); | |
| require(_price > 0, "Preco deve ser > 0"); | |
| require(_deadline > block.timestamp, "Deadline deve ser futuro"); | |
| buyer = _buyer; | |
| seller = _seller; | |
| price = _price; | |
| deadline = _deadline; | |
| state = State.Created; | |
| } | |
| /// @notice Deposita exatamente o valor acordado (apenas a contratante) | |
| function fund() external payable onlyBuyer inState(State.Created) { | |
| require(msg.value == price, "Valor incorreto"); | |
| state = State.Funded; | |
| emit Funded(msg.sender, msg.value); | |
| } | |
| /// @notice Confirma a entrega e libera o pagamento ao seller (apenas a contratante) | |
| function confirmDelivery() external onlyBuyer inState(State.Funded) nonReentrant { | |
| state = State.Completed; | |
| uint256 amount = address(this).balance; | |
| (bool ok, ) = seller.call{value: amount}(""); | |
| require(ok, "Falha no pagamento"); | |
| emit Paid(seller, amount); | |
| } | |
| /// @notice Reembolsa a contratante se o prazo expirou sem confirmacao (qualquer parte pode acionar) | |
| function refundIfLate() external inState(State.Funded) nonReentrant { | |
| require(block.timestamp > deadline, "Prazo ainda nao expirou"); | |
| state = State.Refunded; | |
| uint256 amount = address(this).balance; | |
| (bool ok, ) = payable(buyer).call{value: amount}(""); | |
| require(ok, "Falha no reembolso"); | |
| emit Refunded(buyer, amount); | |
| } | |
| /// @notice Saldo atual em escrow | |
| function getBalance() external view returns (uint256) { | |
| return address(this).balance; | |
| } | |
| /// @dev Evita que ETH sejam enviados por engano diretamente | |
| receive() external payable { | |
| revert("Use a funcao fund()"); | |
| } | |
| fallback() external payable { | |
| revert("Funcao inexistente"); | |
| } | |
| } | |
| // Depósito | |
| // A contratante deve colocar no contrato o valor exato do serviço. | |
| // Aceite | |
| // Se a contratante confirmar que o serviço foi entregue dentro do prazo, o valor é pago automaticamente à prestadora. | |
| // Reembolso | |
| // Se o prazo acabar sem confirmação, o valor é devolvido automaticamente à contratante. | |
| // 1. Criar contrato | |
| // Define quem é a contratante e quem é a prestadora. | |
| // Define o valor do serviço e o prazo final. | |
| // O contrato começa vazio, sem fundos. | |
| // 2. Depositar fundos | |
| // A contratante deve depositar exatamente o valor combinado. | |
| // Se o depósito estiver correto, o contrato passa a ter fundos disponíveis. | |
| // 3. Confirmar entrega | |
| // A contratante confirma que recebeu o serviço. | |
| // O dinheiro vai automaticamente para a prestadora. | |
| // O contrato é marcado como concluído. | |
| // 4. Reembolso por atraso | |
| // Se o prazo acabar sem confirmação de entrega, qualquer parte pode pedir o reembolso. | |
| // O dinheiro volta para a contratante. | |
| // O contrato é marcado como reembolsado. | |
| // 5. Consultar saldo | |
| // Qualquer pessoa pode ver quanto de dinheiro ainda está guardado no contrato. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment