Skip to content

Instantly share code, notes, and snippets.

@rpaskin
Created September 4, 2025 18:00
Show Gist options
  • Select an option

  • Save rpaskin/f221d5fbcf80f838ac60fcc4a48c76e3 to your computer and use it in GitHub Desktop.

Select an option

Save rpaskin/f221d5fbcf80f838ac60fcc4a48c76e3 to your computer and use it in GitHub Desktop.
Contrato de Prestação de Serviços com Pagamento em Escrow (Blockchain)
// 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