Skip to content

danielatort/PrestamoDeFi.sol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;

contract PrestamoDeFi {

address private _socioPrincipal;

struct Prestamo {
    uint256 id;
    address prestatario;
    uint256 monto;
    uint256 plazo;
    uint256 tiempoSolicitud;
    uint256 tiempoLimite;
    bool aprobado;
    bool reembolsado;
    bool liquidado;
}

struct Cliente {
    bool activado;
    uint256 saldoGarantia;
    mapping(uint256 => Prestamo) prestamos;
    uint256[] prestamoIds;
}

mapping(address => Cliente) public clientes;

mapping(address => bool) public empleadosPrestamista;

event SolicitudPrestamo(
    uint256 indexed prestamoId,
    address indexed prestatario, 
    uint256 monto, 
    uint256 plazo);

event PrestamoAprobado(uint256 indexed prestamoId, address prestatario);

event PrestamoReembolsado(uint256 indexed prestamoId, address prestatario);

event GarantiaLiquidada(uint256 indexed prestamoId, address prestatario);

modifier soloSocioPrincipal() {
    require(msg.sender == _socioPrincipal, "ERROR: No eres la persona autorizada");
    _;
}

modifier soloEmpleadoPrestamista() {
    require(empleadosPrestamista[msg.sender], "ERROR: No eres la persona autorizada");
    _;
}

modifier soloClienteRegistrado() {
    require(clientes[msg.sender].activado, "ERROR: Cliente no registrado o inactivo");
    _;
}

constructor(){
    _socioPrincipal = msg.sender;
}

function altaPrestamista(address nuevoPrestamista) public soloSocioPrincipal {
    require(!empleadosPrestamista[nuevoPrestamista], "El prestamista ya esta dado de alta");
    empleadosPrestamista[nuevoPrestamista] = true;
}

function altaCliente(address nuevoCliente) public soloEmpleadoPrestamista {
    require(!clientes[nuevoCliente].activado, "El cliente ya esta registrado");
    Cliente storage structNuevoCliente = clientes[nuevoCliente];
    structNuevoCliente.saldoGarantia = 0;
    structNuevoCliente.activado = true;
}

function depositarGarantia(uint256 monto_) public payable soloClienteRegistrado {
    require (msg.value> 0, "ERROR: No hay fondos a depositar");
    clientes[msg.sender].saldoGarantia += monto_;
}

function solicitarPrestamo(uint256 monto_, uint256 plazo_) public soloClienteRegistrado returns (uint256) {
    require(clientes[msg.sender].saldoGarantia >= monto_, "ERROR: Saldo de garantía insuficiente");
    uint256 nuevoId = clientes[msg.sender].prestamoIds.length + 1;

    Prestamo storage nuevoPrestamo = clientes[msg.sender].prestamos[nuevoId];
    nuevoPrestamo.id = nuevoId;
    nuevoPrestamo.prestatario = msg.sender;
    nuevoPrestamo.monto = monto_;
    nuevoPrestamo.plazo = plazo_;
    nuevoPrestamo.tiempoSolicitud = block.timestamp;
    nuevoPrestamo.tiempoLimite = 0; 
    nuevoPrestamo.aprobado = false;
    nuevoPrestamo.reembolsado = false;
    nuevoPrestamo.liquidado = false;

    clientes[msg.sender].prestamoIds.push(nuevoId);

    emit SolicitudPrestamo(nuevoId, msg.sender, monto_, plazo_);

    return nuevoId;
}

function aprobarPrestamo(address prestatario_, uint256 id_) public soloEmpleadoPrestamista {
    Cliente storage prestatario = clientes[prestatario_];
    require(id_ > 0 && prestatario.prestamoIds.length >= id_, "ERROR: Préstamo no encontrado");

    Prestamo storage prestamo = prestatario.prestamos[id_];
    require(!prestamo.aprobado, "ERROR: Préstamo ya aprobado");
    require(!prestamo.reembolsado, "ERROR: Préstamo ya reembolsado");
    require(!prestamo.liquidado, "ERROR: Préstamo ya liquidado");

    prestamo.aprobado = true;

    prestamo.tiempoLimite = block.timestamp + prestamo.plazo;

    emit PrestamoAprobado(id_, prestatario_, prestatario.saldoGarantia);
}

function reembolsarPrestamo(uint256 id_) public soloClienteRegistrado {
    Cliente storage prestatario = clientes[msg.sender];
    require(id_ > 0 && prestatario.prestamoIds.length >= id_, "ERROR: Préstamo no encontrado");
    
    Prestamo storage prestamo = prestatario.prestamos[id_];
    require(msg.sender == prestamo.prestatario, "ERROR: No eres el prestatario del préstamo");
    require(prestamo.aprobado, "ERROR: Préstamo no aprobado");
    require(!prestamo.reembolsado, "ERROR: Préstamo ya reembolsado");
    require(!prestamo.liquidado, "ERROR: Préstamo liquidado");
    require(prestamo.tiempoLimite >= block.timestamp, "ERROR: Tiempo límite vencido");

    _socioPrincipal.transfer(prestamo.monto);

    prestamo.reembolsado = true;
    prestatario.saldoGarantia -= prestamo.monto;

    emit PrestamoReembolsado(id_, msg.sender, prestamo.monto, prestatario.saldoGarantia);
}

function liquidarGarantia(address prestatario_, uint256 id_) public soloEmpleadoPrestamista {
    Cliente storage prestatario = clientes[prestatario_];
    require(id_ > 0 && prestatario.prestamoIds.length >= id_, "ERROR: Préstamo no encontrado");

    Prestamo storage prestamo = prestatario.prestamos[id_];
    require(prestamo.aprobado, "ERROR: Préstamo no aprobado");
    require(!prestamo.reembolsado, "ERROR: Préstamo ya reembolsado");
    require(!prestamo.liquidado, "ERROR: Préstamo ya liquidado");
    require(prestamo.tiempoLimite < block.timestamp, "ERROR: Tiempo límite no vencido");

    _socioPrincipal.transfer(prestamo.monto);

    prestamo.liquidado = true;
    
    prestatario.saldoGarantia -= prestamo.monto;

    emit GarantiaLiquidada(id_, prestatario_, prestamo.monto, prestatario.saldoGarantia);
}

function obtenerPrestamosPorPrestatario(address prestatario_) public view returns (uint256[] memory) {
    return clientes[prestatario_].prestamoIds;
}

function obtenerDetalleDePrestamo(address prestatario_, uint256 id_) public view returns (Prestamo memory) {
    return clientes[prestatario_].prestamos[id_];
}

}

About

Proyecto final

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published