Aller au contenu

Créer un smart contract simple de prêt et d'emprunt sur Linea

Apprenez à créer et déployer un smart contract simple de prêt et d'emprunt sur Linea.

13 min de lecture
Créer un smart contract simple de prêt et d'emprunt sur Linea

La finance décentralisée (DeFi) a transformé la façon dont les gens prêtent et empruntent de l'argent en supprimant les intermédiaires et en utilisant des smart contracts pour gérer les transactions automatiquement. Ce qui nécessitait autrefois des banques et de la paperasse peut désormais se faire en quelques clics, entièrement on-chain.

Linea aide les développeurs à créer des applications DeFi avec une meilleure scalabilité et des frais de gas réduits par rapport au mainnet Ethereum, en utilisant des zero-knowledge rollups (zk-rollups) pour regrouper et compresser les transactions.

Dans ce guide, nous allons vous accompagner pas à pas dans la création et le déploiement d'un smart contract simple de prêt et d'emprunt sur Linea. Vous apprendrez à gérer les garanties, émettre des prêts et configurer des règles de remboursement — toutes des fonctionnalités essentielles d'un système de prêt DeFi.

À la fin, vous disposerez d'un smart contract fonctionnel et d'une solide compréhension du fonctionnement interne des prêts DeFi. Que vous soyez novice en développement blockchain ou que vous souhaitiez perfectionner vos compétences, ce guide étape par étape vous donnera les outils nécessaires pour commencer à développer sur Linea.

Prérequis

  • Vous devez avoir une compréhension de base de Solidity.

  • Vous devez avoir Nodejs et Foundry installés sur votre PC.

Présentation du contrat

Ce contrat permet :

  1. Dépôt de garantie : Les utilisateurs peuvent déposer des garanties dans le contrat, avec les détails stockés de manière sécurisée dans le smart contract.

  2. Emprunt : Les utilisateurs peuvent contracter un prêt en échange de leur garantie déposée.

  3. Remboursement : Les utilisateurs peuvent rembourser leurs prêts pour débloquer leur garantie.

  4. Retrait de garantie : Les utilisateurs peuvent retirer les garanties qui ne sont pas bloquées en raison d'un prêt actif.

Configuration du projet

Nous utiliserons le framework Foundry pour ce projet. Une fois Foundry installé, exécutez la commande ci-dessous pour initier un nouveau projet :

forge init lending

Ouvrez le dossier market sur Vscode ou votre éditeur de code préféré, et supprimez les fichiers scripts/counter.s.sol, src/counter.sol et test/counter.t.sol.

Installer toutes les dépendances

forge install foundry-rs/forge-std --no-commit && forge install OpenZeppelin/openzeppelin-contracts --no-commit

Code complet du smart contract de prêt et d'emprunt

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import "lib/openzeppelin-contracts/contracts/access/Ownable.sol";
contract LendingBorrowing is Ownable {
    struct Loan {
        uint256 amount; // Borrowed amount
        uint256 collateral; // Collateral amount
        bool isActive; // Loan status
    }
    IERC20 public immutable collateralToken;
    IERC20 public immutable lendingToken;
    uint256 public collateralFactor; // Percentage of collateral allowed to be borrowed (e.g., 50%)
    mapping(address => uint256) public collateralBalances; // User collateral balances
    mapping(address => Loan) public loans; // User loans
    event CollateralDeposited(address indexed user, uint256 amount);
    event CollateralWithdrawn(address indexed user, uint256 amount);
    event LoanTaken(address indexed user, uint256 amount);
    event LoanRepaid(address indexed user, uint256 amount);
    constructor(IERC20 _collateralToken, IERC20 _lendingToken, uint256 _collateralFactor) Ownable(msg.sender) {
        require(_collateralFactor <= 100, "Collateral factor must be <= 100");
        collateralToken = _collateralToken;
        lendingToken = _lendingToken;
        collateralFactor = _collateralFactor;
    }
    function setCollateralFactor(uint256 _newFactor) external onlyOwner {
        require(_newFactor <= 100, "Collateral factor must be <= 100");
        collateralFactor = _newFactor;
    }
    function depositCollateral(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than zero");
        collateralBalances[msg.sender] += _amount;
        collateralToken.transferFrom(msg.sender, address(this), _amount);
        emit CollateralDeposited(msg.sender, _amount);
    }
    function withdrawCollateral(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than zero");
        require(collateralBalances[msg.sender] >= _amount, "Insufficient collateral");
        uint256 maxWithdrawable = collateralBalances[msg.sender] - _loanRequiredCollateral(msg.sender);
        require(_amount <= maxWithdrawable, "Cannot withdraw collateral locked for a loan");
        collateralBalances[msg.sender] -= _amount;
        collateralToken.transfer(msg.sender, _amount);
        emit CollateralWithdrawn(msg.sender, _amount);
    }
    function takeLoan(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than zero");
        require(loans[msg.sender].isActive == false, "Existing loan must be repaid first");
        uint256 maxLoan = (collateralBalances[msg.sender] * collateralFactor) / 100;
        require(_amount <= maxLoan, "Loan exceeds collateral limit");
        loans[msg.sender] = Loan({
            amount: _amount,
            collateral: collateralBalances[msg.sender],
            isActive: true
        });
        lendingToken.transfer(msg.sender, _amount);
        emit LoanTaken(msg.sender, _amount);
    }
    function repayLoan(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than zero");
        Loan storage userLoan = loans[msg.sender];
        require(userLoan.isActive, "No active loan");
        require(_amount <= userLoan.amount, "Repay amount exceeds loan");
        lendingToken.transferFrom(msg.sender, address(this), _amount);
        userLoan.amount -= _amount;
        if (userLoan.amount == 0) {
            userLoan.isActive = false;
        }
        emit LoanRepaid(msg.sender, _amount);
    }
    function _loanRequiredCollateral(address _user) internal view returns (uint256) {
        Loan memory userLoan = loans[_user];
        if (!userLoan.isActive) return 0;
        return (userLoan.amount * 100) / collateralFactor;
    }
    function getLoanDetails(address _user) external view returns (uint256 amount, uint256 collateral, bool isActive) {
        Loan memory userLoan = loans[_user];
        return (userLoan.amount, userLoan.collateral, userLoan.isActive);
    }
}
Copier

Présentation du code

Struct Loan

struct Loan {
        uint256 amount; // Borrowed amount
        uint256 collateral; // Collateral amount
        bool isActive; // Loan status
    }
Copier

La struct Loan sert de modèle pour stocker les détails des prêts individuels contractés par les utilisateurs. Chaque champ de la struct représente une information clé sur le statut et les conditions du prêt. Voici une description de ses champs :

  • Amount : Stocke le montant des tokens que l'utilisateur a empruntés. Cette valeur permet de suivre le montant dû par l'utilisateur, de déterminer les obligations de remboursement et de valider les conditions du prêt.

  • Collateral : Stocke la valeur de la garantie déposée par l'utilisateur pour sécuriser le prêt. Elle protège les fonds du prêteur et permet de déterminer le montant maximum empruntable en fonction du facteur de garantie.

  • IsActive : Indique si le prêt est actuellement actif. Ce champ permet de suivre le statut du prêt et empêche les utilisateurs de contracter un nouveau prêt tant que le prêt existant n'est pas entièrement remboursé.

Variables d'état

IERC20 public immutable collateralToken;
    IERC20 public immutable lendingToken;
    uint256 public collateralFactor; // Percentage of collateral allowed to be borrowed (e.g., 50%)
Copier

L'extrait ci-dessus définit trois variables d'état critiques, chacune jouant un rôle spécifique dans l'activation et la sécurisation des fonctionnalités de la plateforme de prêt. Voici une description de ces variables :

  • CollateralToken : Représente le token que les utilisateurs déposent en garantie pour leurs prêts. Par exemple, si USDC est utilisé comme garantie, cette variable stocke l'adresse blockchain du contrat USDC.

  • LendingToken : Cette variable représente le token que la plateforme prête aux emprunteurs. Si USDT est le token de prêt, elle stocke l'adresse blockchain du contrat USDT.

  • CollateralFactor : Définit le pourcentage de la valeur de la garantie qu'un utilisateur peut emprunter. Il est exprimé sous forme de nombre entier, où 100 représente 100 % de la valeur de la garantie. Par exemple, si le collateralFactor est de 50, un utilisateur peut emprunter jusqu'à 50 % de la valeur de sa garantie. Cela garantit que les prêts sont sur-collatéralisés afin de maintenir la sécurité du système de prêt. Si un utilisateur dépose une garantie d'une valeur de 1 000 $ et que le collateralFactor est de 50 %, le prêt maximum qu'il peut contracter est de 500 $.

Mappings

mapping(address => uint256) public collateralBalances; // User collateral balances
 mapping(address => Loan) public loans; // User loans
Copier
  • Mapping CollateralBalances : Suit le montant de garantie déposé par chaque utilisateur. Chaque utilisateur dispose d'un solde de garantie unique associé à son adresse. Ce mapping permet de vérifier si un utilisateur dispose de suffisamment de garanties pour contracter un prêt ou retirer des fonds.

  • Mapping Loans : Suit les détails des prêts actifs pour chaque utilisateur en associant leur adresse à leurs informations de prêt. Il garantit qu'un utilisateur ne peut pas contracter un nouveau prêt tant qu'il en a déjà un actif.

Événements

 event CollateralDeposited(address indexed user, uint256 amount); 
 event CollateralWithdrawn(address indexed user, uint256 amount);
 event LoanTaken(address indexed user, uint256 amount);
 event LoanRepaid(address indexed user, uint256 amount);
Copier
  • Événement CollateralDeposited – Émis lorsqu'un utilisateur dépose une garantie dans le contrat. Il enregistre l'adresse de l'utilisateur et le montant déposé.

  • Événement CollateralWithdrawn – Émis lorsqu'un utilisateur retire une garantie du contrat. Il enregistre l'adresse de l'utilisateur et le montant retiré.

  • Événement LoanTaken – Émis lorsqu'un utilisateur contracte un prêt. Il enregistre l'adresse de l'utilisateur et le montant emprunté.

  • Événement LoanRepaid – Émis lorsqu'un utilisateur rembourse un prêt. Il enregistre l'adresse de l'utilisateur et le montant du remboursement.

Constructeur

 constructor(IERC20 _collateralToken, IERC20 _lendingToken, uint256 _collateralFactor) Ownable(msg.sender) {
        require(_collateralFactor <= 100, "Collateral factor must be <= 100");
        collateralToken = _collateralToken;
        lendingToken = _lendingToken;
        collateralFactor = _collateralFactor;
    }
Copier

Le constructeur est une fonction spéciale en Solidity qui ne s'exécute qu'une seule fois lors du déploiement du contrat. Son objectif est de :

  • Configurer la configuration initiale du contrat.

  • Attribuer des valeurs aux variables d'état clés.

  • Établir la propriété et le contrôle d'accès via Ownable.

Le constructeur prend trois arguments : _collateralToken, _lendingToken et _collateralFactor.

  • _collateralToken – Le token utilisé comme garantie pour les prêts.

  • _lendingToken – Le token que les utilisateurs empruntent au système.

  • _collateralFactor – Le pourcentage de garantie qui détermine la capacité d'emprunt maximale, en s'assurant qu'elle ne dépasse pas 100 %.

Lors de l'initialisation, le constructeur :

  • Assigne _collateralToken comme actif de garantie.

  • Définit _lendingToken comme token d'emprunt.

  • Configure _collateralFactor pour établir le ratio garantie/prêt.

De plus, Ownable(msg.sender) garantit que le déployeur du contrat en devient le propriétaire, lui accordant des privilèges administratifs, tels que la modification du collateralFactor si nécessaire.

Définir le facteur de garantie

function setCollateralFactor(uint256 _newFactor) external onlyOwner {
        require(_newFactor <= 100, "Collateral factor must be <= 100");
        collateralFactor = _newFactor;
    }
Copier

Cette fonction est une fonctionnalité administrative essentielle qui permet au propriétaire du contrat de modifier le facteur de garantie, qui contrôle le ratio entre la garantie et les fonds empruntables. Le facteur de garantie est utilisé pour déterminer le montant maximum qu'un utilisateur peut emprunter en échange de sa garantie. En permettant des mises à jour de ce facteur, le contrat peut s'adapter à l'évolution des conditions du marché ou des profils de risque.

La fonction est marquée comme external, ce qui signifie qu'elle ne peut être appelée que depuis l'extérieur du contrat. Le modificateur onlyOwner garantit que seul le propriétaire du contrat (généralement le déployeur) peut appeler cette fonction, assurant un contrôle d'accès strict.

La fonction s'assure que le nouveau facteur de garantie est un pourcentage valide compris entre 0 et 100 pour éviter de définir des valeurs irréalistes ou non sécurisées. Par exemple, un facteur supérieur à 100 pourrait permettre aux utilisateurs d'emprunter plus que ce que couvre leur garantie.

La fonction met à jour la variable d'état collateralFactor avec la nouvelle valeur passée en tant que _newFactor.

Dépôt de garantie

 function depositCollateral(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than zero");
        collateralBalances[msg.sender] += _amount;
        collateralToken.transferFrom(msg.sender, address(this), _amount);
        emit CollateralDeposited(msg.sender, _amount);
    }
Copier

Cette fonction est une fonctionnalité essentielle qui permet aux utilisateurs de déposer des garanties dans le contrat. C'est une étape obligatoire avant qu'un utilisateur puisse contracter un prêt et garantit que la garantie est correctement comptabilisée et stockée dans le contrat.

La fonction vérifie que l'utilisateur fournit un montant valide supérieur à zéro et augmente le solde de garantie de l'utilisateur du montant déposé. Elle utilise transferFrom pour transférer les tokens de l'utilisateur vers le contrat, ce qui nécessite que l'utilisateur approuve le contrat pour dépenser ses tokens avant d'appeler cette fonction.

Cette fonction permet les opérations suivantes :

  • Dépôt de garantie : Les utilisateurs déposent un montant spécifié d'un token prédéfini (collateralToken) dans le contrat. Cette garantie sert de sécurité pour tout prêt qu'ils contractent.

  • Suivi des soldes de garantie : Le montant déposé est ajouté au solde de garantie de l'utilisateur, qui est suivi dans le mapping collateralBalances.

  • Activation de l'emprunt : La garantie sert de base pour calculer le montant que l'utilisateur peut emprunter.

Retrait de garantie

function withdrawCollateral(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than zero");
        require(collateralBalances[msg.sender] >= _amount, "Insufficient collateral");
        uint256 maxWithdrawable = collateralBalances[msg.sender] - _loanRequiredCollateral(msg.sender);
        require(_amount <= maxWithdrawable, "Cannot withdraw collateral locked for a loan");
        collateralBalances[msg.sender] -= _amount;
        collateralToken.transfer(msg.sender, _amount);
        emit CollateralWithdrawn(msg.sender, _amount);
    }
Copier

Cette fonction permet aux utilisateurs de retirer une partie ou la totalité de leur garantie déposée, tout en s'assurant que la garantie bloquée en tant que sécurité pour un prêt actif ne peut pas être retirée.

La fonction vérifie que le montant du retrait est supérieur à zéro et s'assure que l'utilisateur dispose de suffisamment de garanties disponibles pour couvrir le retrait demandé. Elle calcule la portion de garantie bloquée pour tout prêt actif, diminue le solde de garantie de l'utilisateur du montant du retrait et transfère les tokens demandés du contrat vers l'utilisateur.

En résumé, cette fonction permet les opérations suivantes :

  • Retrait de garantie : Permet aux utilisateurs de retirer leur garantie disponible du contrat.

  • Protection du prêt : Garantit que les utilisateurs ne peuvent pas retirer la garantie nécessaire pour sécuriser un prêt actif.

  • Gestion de l'état : Met à jour le solde de garantie de l'utilisateur après un retrait réussi.

Contracter un prêt

function takeLoan(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than zero");
        require(loans[msg.sender].isActive == false, "Existing loan must be repaid first");
        uint256 maxLoan = (collateralBalances[msg.sender] * collateralFactor) / 100;
        require(_amount <= maxLoan, "Loan exceeds collateral limit");
        loans[msg.sender] = Loan({
            amount: _amount,
            collateral: collateralBalances[msg.sender],
            isActive: true
        });
        lendingToken.transfer(msg.sender, _amount);
        emit LoanTaken(msg.sender, _amount);
    }
Copier

Cette fonction permet aux utilisateurs d'emprunter des tokens du contrat en fonction de leur garantie déposée. Le montant du prêt est limité par la garantie déposée par l'utilisateur et le facteur de garantie du contrat, garantissant que l'emprunt reste dans des limites sûres. Cette fonction joue un rôle clé dans la facilitation des prêts tout en maintenant la sécurité du système.

La fonction garantit les points suivants :

  • Le montant du prêt est supérieur à zéro.

  • L'utilisateur n'a pas de prêt actif, empêchant plusieurs prêts simultanés.

  • Le prêt demandé ne dépasse pas la limite d'emprunt maximale basée sur la garantie.

  • Le mapping loans est mis à jour avec les détails du prêt de l'utilisateur.

  • Les tokens empruntés sont transférés du contrat vers l'utilisateur.

En résumé, cette fonction permet les opérations suivantes :

  • Émission de prêt : Permet aux utilisateurs d'emprunter des tokens garantis par leur garantie déposée.

  • Gestion de la garantie : Garantit que le montant du prêt reste dans la capacité d'emprunt de l'utilisateur.

  • Suivi des prêts : Maintient les enregistrements de prêts des utilisateurs pour éviter le sur-emprunt et assurer l'intégrité du système.

Rembourser un prêt

function repayLoan(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than zero");
        Loan storage userLoan = loans[msg.sender];
        require(userLoan.isActive, "No active loan");
        require(_amount <= userLoan.amount, "Repay amount exceeds loan");
        lendingToken.transferFrom(msg.sender, address(this), _amount);
        userLoan.amount -= _amount;
        if (userLoan.amount == 0) {
            userLoan.isActive = false;
        }
        emit LoanRepaid(msg.sender, _amount);
    }
Copier

Cette fonction permet aux utilisateurs de rembourser leurs prêts actifs, partiellement ou intégralement. Elle met à jour le statut du prêt et garantit que les remboursements sont traités correctement, contribuant ainsi à maintenir l'intégrité du système.

La fonction effectue les vérifications et actions suivantes :

  • S'assure que le montant du remboursement est supérieur à zéro pour éviter les opérations invalides.

  • Récupère les détails du prêt de l'utilisateur et confirme qu'il dispose d'un prêt actif avant de continuer.

  • S'assure que le montant du remboursement ne dépasse pas le solde restant du prêt.

  • Transfère le montant du remboursement de l'utilisateur vers le contrat, nécessitant une approbation préalable pour le montant spécifié.

  • Réduit le solde du prêt du montant du remboursement.

  • Si le prêt est entièrement remboursé, la fonction le marque comme inactif.

En résumé, cette fonction permet les opérations suivantes :

  • Remboursement du prêt : Permet aux emprunteurs de restituer le montant emprunté au contrat.

  • Suivi des prêts : Met à jour le solde et le statut du prêt après remboursement.

  • Transparence : Émet un événement pour enregistrer les transactions de remboursement on-chain.

Tests

Créez un fichier Token.sol dans le dossier src et ajoutez le code ci-dessous au fichier.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {ERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {
    constructor(string memory name, string memory symbol) ERC20(name, symbol){}
    function mint(address user, uint256 amount) public {
        _mint(user, amount);
    }
}
Copier

Créez un fichier lending.t.sol dans le dossier test et ajoutez le code ci-dessous au fichier.

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import { LendingBorrowing} from "../src/Lending.sol";
import { Token } from "../src/Token.sol";
contract LendingTest is Test {
     LendingBorrowing public lending;
     Token public collateral;
     Token public lendingToken;
     address public user1 = makeAddr("user1");
     address public user2 = makeAddr("user2");
     address public user3 = makeAddr("user3");

    function setUp() public {
        collateral = new Token("collateralToken", "ct");
        lendingToken = new Token("lendingToken", "lt");
        lending = new LendingBorrowing(collateral, lendingToken, 80);
        collateral.mint(user1, 100 ether);
        lendingToken.mint(address(lending), 1000 ether);
    }
    function test_DepositCollateral() public {
        vm.startPrank(user1);
        collateral.approve(address(lending), 100 ether);
        lending.depositCollateral(50 ether);

        assert(collateral.balanceOf(user1) == 50 ether);
        assert(collateral.balanceOf(address(lending)) == 50 ether);  
    }

    function test_TakeLoan() public {
        vm.startPrank(user1);
        collateral.approve(address(lending), 100 ether);
        lending.depositCollateral(50 ether);
        vm.expectRevert();
        lending.takeLoan(100 ether);
        vm.expectRevert();
        lending.takeLoan(49 ether);
        lending.takeLoan(40 ether);
        assert(lendingToken.balanceOf(user1) == 40 ether);
    }

    function test_RepayLoan() public {
        vm.startPrank(user1);
        collateral.approve(address(lending), 100 ether);
        lending.depositCollateral(50 ether);
        lending.takeLoan(40 ether);
        lendingToken.approve(address(lending), 40 ether);
        lending.repayLoan(40 ether);
        assert(lendingToken.balanceOf(user1) == 0 ether);
    }

    function test_WithdrawCollateral() public {
        vm.startPrank(user1);
        collateral.approve(address(lending), 100 ether);
        lending.depositCollateral(50 ether);
        lending.takeLoan(40 ether);
         lendingToken.approve(address(lending), 40 ether);
        lending.repayLoan(40 ether);
        lending.withdrawCollateral(50 ether);
        assert(lendingToken.balanceOf(user1) == 0 ether);
        assert(collateral.balanceOf(user1) == 100 ether);
    }

}
Copier

Configuration des tests

Cette fonction est appelée avant chaque fonction de test et est utilisée pour initialiser l'état.

  • Elle déploie les contrats de tokens : Les contrats collateral et lendingToken sont tous deux déployés.

  • Elle déploie le contrat LendingBorrowing : Le contrat LendingBorrowing est initialisé avec le token de garantie, le lendingToken et un ratio garantie/prêt de 80 % (ce qui signifie qu'un utilisateur ne peut emprunter que jusqu'à 80 % de la valeur de sa garantie).

  • Mint de tokens :- 100 tokens de garantie sont mintés pour l'Utilisateur 1.

  • 1000 tokens de prêt sont mintés vers le contrat de prêt.

Test de dépôt de garantie

Cette fonction teste qu'un utilisateur peut déposer des garanties dans le contrat de prêt. L'Utilisateur 1 approuve le contrat de prêt pour dépenser jusqu'à 100 de ses tokens de garantie et dépose 50 tokens de garantie dans le contrat. La fonction vérifie que :

  • Le solde de l'Utilisateur 1 est réduit de 50 tokens.

  • Le solde de garantie du contrat de prêt augmente de 50 tokens.

Test de contraction de prêt

Cette fonction teste qu'un utilisateur peut contracter un prêt en fonction de la garantie qu'il a déposée. L'Utilisateur 1 dépose 50 tokens de garantie et approuve le contrat de prêt pour les dépenser.

  • Le test s'assure que la contraction d'un prêt supérieur au montant autorisé ou inférieur au minimum requis (en fonction de la garantie) est annulée.

  • L'Utilisateur 1 contracte avec succès un prêt de 40 tokens lendingToken.

  • Le test vérifie que l'Utilisateur 1 reçoit 40 tokens lendingToken après avoir contracté le prêt.

Test de remboursement de prêt

Cette fonction teste qu'un utilisateur peut rembourser son prêt correctement.

  • L'Utilisateur 1 dépose 50 tokens de garantie et contracte un prêt de 40 tokens lendingToken.

  • L'Utilisateur 1 approuve le contrat de prêt pour dépenser 40 tokens lendingToken et rembourse le prêt.

  • Le test vérifie que le solde lendingToken de l'Utilisateur 1 est nul après le remboursement du prêt.

Test de retrait de garantie

Cette fonction teste qu'un utilisateur peut retirer sa garantie après avoir remboursé le prêt.

  • L'Utilisateur 1 dépose 50 tokens de garantie, contracte un prêt de 40 tokens lendingToken et rembourse le prêt.

  • Après le remboursement du prêt, l'Utilisateur 1 retire sa garantie.

  • Le test vérifie que :- L'Utilisateur 1 récupère ses 50 tokens de garantie.

  • Le solde de l'Utilisateur 1 est de 100 (puisqu'il a initialement minté 100 tokens).

  • Le solde lendingToken de l'Utilisateur 1 est nul après le remboursement du prêt.

Exécuter les tests

forge test

Déploiement et vérification sur Linea

Ajoutez les variables nécessaires au fichier .env, qui doit se trouver à la racine du projet.

LINEA_RPC_URL=https://linea-mainnet.infura.io/v3/ // Infura RPC endpoint for connecting to Linea 
PRIVATE_KEY=************************************************* // Wallet private key for signing transactions LINEA_API_KEY=************************* // API key for accessing Linea services via Infura
Copier

Ajoutez les détails ci-dessous à foundry.toml

[etherscan]
linea = { key = "${LINEA_API_KEY}", url = "https://api-sepolia.lineascan.build/api" }
Copier

Créez un Makefile et ajoutez les détails ci-dessous

deploy:
    forge create src/Lending.sol: LendingBorrowing  --rpc-url $(LINEA_RPC_URL) --private-key $(PRIVATE_KEY)

verify:; forge verify-contract --rpc-url $(LINEA_RPC_URL) --chain linea <contract address> src/Lending.sol:LendingBorrowing --constructor-args arg1 arg2
Copier

Déploiement

make deploy

Vérification

make verify

Conclusion

La création d'un smart contract simple de prêt et d'emprunt constitue une base pour comprendre la DeFi et le développement blockchain. Ce guide a couvert les points suivants :

  • Dépôt de garantie – Les utilisateurs bloquent des actifs en tant que sécurité pour les prêts.

  • Contraction de prêts – Les emprunteurs accèdent aux fonds en fonction de leur garantie.

  • Remboursement de prêts – Les utilisateurs restituent les fonds empruntés pour solder leur dette.

  • Retrait de garantie – Les utilisateurs récupèrent leur garantie après remboursement intégral.

En intégrant ces éléments, nous avons créé un système de prêt fonctionnel et automatisé. À mesure que la DeFi se développe, ces concepts servent de blocs de construction pour des applications financières plus avancées.

Pour plus de tutoriels pratiques et d'analyses approfondies sur le développement blockchain, consultez la chaîne YouTube MetaMask Developer et restez informé de nos dernières actualités en nous suivant sur Twitter.

Traduit par IA. Peut contenir des erreurs. Veuillez toujours vérifier les informations.

Évaluer la traduction

Cet article a été rédigé par :

  • Kingsley Okonkwo

    Kingsley, développeur blockchain Ethereum certifié, occupe le poste de rédacteur technique chez Consensys, avec une spécialisation dans les outils destinés aux développeurs. Avant de rejoindre Consensys, Kingsley a travaillé en tant que développeur backend freelance sur plusieurs plateformes, dont Gigster et Braintrust. Fort de 5 ans d'expérience en développement logiciel, il maîtrise des outils tels que JavaScript (Node.js & React), GoLang, SQL et Docker. Kingsley excelle dans la création de tutoriels pas à pas et de guides pratiques, en s'appuyant sur les dernières technologies web3 pour aider les développeurs à créer de meilleures dapps. Actuellement basé à Dubaï, Kingsley aime jouer au basketball et au football pendant son temps libre.

    Lire tous les articles