Merkeziyetsiz finans (DeFi), aracıları ortadan kaldırarak ve işlemleri otomatik olarak yönetmek için akıllı sözleşmeler kullanarak insanların para ödünç verme ve alma biçimini yeniden şekillendirdi. Eskiden bankalar ve evrak işleri gerektiren süreçler artık birkaç tıklamayla, tamamen zincir üzerinde gerçekleşebiliyor.
Linea, sıfır bilgi toplamaları (zk-rollup'lar) kullanarak işlemleri toplu hâle getirip sıkıştırması sayesinde geliştiricilerin Ethereum mainnet'e kıyasla daha iyi ölçeklenebilirlik ve daha düşük gas maliyetleriyle DeFi uygulamaları oluşturmasına yardımcı olur.
Bu kılavuzda, Linea üzerinde basit bir borç verme ve borç alma akıllı sözleşmesi oluşturup dağıtma sürecini adım adım ele alacağız. Teminat yönetimini, kredi vermeyi ve geri ödeme kurallarını nasıl ayarlayacağınızı öğreneceksiniz; bunların hepsi bir DeFi borç verme sisteminin temel özellikleridir.
Kılavuzun sonunda çalışan bir akıllı sözleşmeye ve DeFi borç vermenin arka planda nasıl işlediğine dair sağlam bir anlayışa sahip olacaksınız. Blockchain geliştirmeye yeni başlıyor olun ya da becerilerinizi geliştirmek istiyor olun, bu adım adım kılavuz size Linea üzerinde geliştirme yapmaya başlamak için gereken araçları sunacak.
Ön Koşullar
Solidity hakkında temel bir anlayışa sahip olmalısınız.
Bilgisayarınızda Nodejs ve Foundry kurulu olmalıdır.
Sözleşmeye genel bakış
Bu sözleşme şunları mümkün kılar:
Teminat Yatırma: Kullanıcılar sözleşmeye teminat yatırabilir; ayrıntılar akıllı sözleşmede güvenli biçimde saklanır.
Borç Alma: Kullanıcılar yatırdıkları teminata karşılık kredi alabilir.
Geri Ödeme: Kullanıcılar teminatlarının kilidini açmak için kredilerini geri ödeyebilir.
Teminat Çekme: Kullanıcılar aktif bir kredi nedeniyle kilitlenmemiş teminatlarını çekebilir.
Proje kurulumu
Bu proje için Foundry framework'ünü kullanacağız. Foundry kurulu durumdayken yeni bir proje başlatmak için aşağıdaki komutu çalıştırın:
forge init lending
Market klasörünü Vscode'da veya tercih ettiğiniz kod düzenleyicide açın ve scripts/counter.s.sol, src/counter.sol ile test/counter.t.sol dosyalarını silin.
Tüm bağımlılıkları yükleyin
forge install foundry-rs/forge-std --no-commit && forge install OpenZeppelin/openzeppelin-contracts --no-commitBorç verme ve borç alma akıllı sözleşmesi için tam kod
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;
uint256 collateral;
bool isActive;
}
IERC20 public immutable collateralToken;
IERC20 public immutable lendingToken;
uint256 public collateralFactor;
mapping(address => uint256) public collateralBalances;
mapping(address => Loan) public 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);
}
}
Koda genel bakış
Loan struct'ı
struct Loan {
uint256 amount;
uint256 collateral;
bool isActive;
}
Loan struct'ı, kullanıcıların aldığı bireysel kredilerin ayrıntılarını saklamak için bir şablon işlevi görür. Struct içindeki her alan, kredinin durumu ve koşulları hakkında önemli bir bilgiyi temsil eder. Alanların açıklaması aşağıda verilmiştir:
Amount: Kullanıcının ödünç aldığı token miktarını saklar. Bu değer, kullanıcının ne kadar borçlu olduğunu takip etmeye, geri ödeme yükümlülüklerini belirlemeye ve kredi koşullarını doğrulamaya yardımcı olur.
Collateral: Kullanıcının krediyi güvence altına almak için yatırdığı teminatın değerini saklar. Borç verenin fonlarını korur ve teminat faktörüne göre maksimum borçlanılabilir miktarı belirlemeye yardımcı olur.
IsActive: Kredinin şu anda aktif olup olmadığını gösterir. Bu alan, kredinin durumunu takip etmeye ve mevcut kredi tamamen geri ödenene kadar kullanıcıların yeni kredi almasını engellemeye yardımcı olur.
Durum değişkenleri
IERC20 public immutable collateralToken;
IERC20 public immutable lendingToken;
uint256 public collateralFactor;
Yukarıdaki kod parçacığı, borç verme platformunun işlevselliğini etkinleştirmede ve güvence altına almada belirli roller üstlenen üç kritik durum değişkeni tanımlar. Bu değişkenlerin açıklaması aşağıda verilmiştir:
CollateralToken: Kullanıcıların kredileri için teminat olarak yatırdığı token'ı temsil eder. Örneğin, teminat olarak USDC kullanılıyorsa bu değişken USDC sözleşmesinin blockchain adresini saklar.
LendingToken: Bu değişken, platformun borçlulara ödünç verdiği token'ı temsil eder. USDT borç verme token'ıysa USDT sözleşmesinin blockchain adresini saklar.
CollateralFactor: Kullanıcının borç alabileceği teminat değerinin yüzdesini tanımlar. 100'ün teminat değerinin %100'ünü temsil ettiği tam sayı olarak ifade edilir. Örneğin, collateralFactor 50 ise kullanıcı teminatının değerinin en fazla %50'si kadar borç alabilir. Bu, borç verme sisteminin güvenliğini korumak amacıyla kredilerin aşırı teminatlı olmasını sağlar. Bir kullanıcı 1.000 $ değerinde teminat yatırırsa ve collateralFactor %50 ise alabileceği maksimum kredi 500 $'dır.
Mapping'ler
mapping(address => uint256) public collateralBalances;
mapping(address => Loan) public loans;
CollateralBalances mapping'i: Her kullanıcının yatırdığı teminat miktarını takip eder. Her kullanıcının adresiyle ilişkilendirilmiş benzersiz bir teminat bakiyesi vardır. Bu mapping, bir kullanıcının kredi almak veya fon çekmek için yeterli teminata sahip olup olmadığını doğrulamaya yardımcı olur.
Loans mapping'i: Her kullanıcının aktif kredi ayrıntılarını adreslerine bağlayarak takip eder. Bir kullanıcının hâlâ aktif bir kredisi varken yeni kredi almasını engeller.
Event'ler
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);
CollateralDeposited event'i – Bir kullanıcı sözleşmeye teminat yatırdığında tetiklenir. Kullanıcının adresini ve yatırılan miktarı kaydeder.
CollateralWithdrawn event'i – Bir kullanıcı sözleşmeden teminat çektiğinde tetiklenir. Kullanıcının adresini ve çekilen miktarı kaydeder.
LoanTaken event'i – Bir kullanıcı kredi aldığında tetiklenir. Kullanıcının adresini ve ödünç alınan miktarı kaydeder.
LoanRepaid event'i – Bir kullanıcı krediyi geri ödediğinde tetiklenir. Kullanıcının adresini ve geri ödeme miktarını kaydeder.
Constructor
constructor(IERC20 _collateralToken, IERC20 _lendingToken, uint256 _collateralFactor) Ownable(msg.sender) {
require(_collateralFactor <= 100, "Collateral factor must be <= 100");
collateralToken = _collateralToken;
lendingToken = _lendingToken;
collateralFactor = _collateralFactor;
}
Constructor, Solidity'de yalnızca sözleşme dağıtımı sırasında bir kez çalışan özel bir fonksiyondur. Amacı şunlardır:
Sözleşmenin başlangıç yapılandırmasını ayarlamak.
Temel durum değişkenlerine değer atamak.
Ownable aracılığıyla sahiplik ve erişim kontrolü oluşturmak.
Constructor üç argüman alır: _collateralToken, _lendingToken ve _collateralFactor.
_collateralToken – Krediler için teminat olarak kullanılan token.
_lendingToken – Kullanıcıların sistemden ödünç aldığı token.
_collateralFactor – Maksimum borçlanma kapasitesini belirleyen ve %100'ü aşmadığından emin olunan teminat yüzdesi.
Başlatma sırasında constructor şunları yapar:
_collateralToken'ı teminat varlığı olarak atar.
_lendingToken'ı borçlanma token'ı olarak ayarlar.
Teminat-kredi oranını belirlemek için _collateralFactor'ı yapılandırır.
Ayrıca Ownable(msg.sender), sözleşmeyi dağıtan kişinin sahibi olmasını sağlayarak gerektiğinde collateralFactor'ı değiştirme gibi yönetimsel ayrıcalıklar tanır.
Teminat faktörünü ayarlama
function setCollateralFactor(uint256 _newFactor) external onlyOwner {
require(_newFactor <= 100, "Collateral factor must be <= 100");
collateralFactor = _newFactor;
}
Bu fonksiyon, sözleşme sahibinin teminat ile borçlanılabilir fonlar arasındaki oranı kontrol eden collateral factor'ı değiştirmesine olanak tanıyan önemli bir yönetim özelliğidir. Collateral factor, kullanıcının teminatına karşılık borç alabileceği maksimum miktarı belirlemek için kullanılır. Bu faktörün güncellenmesine izin verilerek sözleşme, değişen piyasa koşullarına veya risk profillerine uyum sağlayabilir.
Fonksiyon external olarak işaretlenmiştir; bu, yalnızca sözleşme dışından çağrılabileceği anlamına gelir. onlyOwner modifier'ı, yalnızca sözleşme sahibinin (genellikle dağıtımı yapan kişi) bu fonksiyonu çağırabilmesini sağlayarak katı erişim kontrolü sunar.
Fonksiyon, gerçekçi olmayan veya güvensiz değerlerin ayarlanmasını önlemek amacıyla yeni collateral factor'ın 0 ile 100 arasında geçerli bir yüzde olmasını sağlar. Örneğin, 100'ün üzerinde bir faktör, kullanıcıların teminatlarının karşılayabileceğinden daha fazla borç almasına izin verebilir.
Fonksiyon, _newFactor olarak iletilen yeni değerle collateralFactor durum değişkenini günceller.
Teminat yatırma
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);
}
Bu fonksiyon, kullanıcıların sözleşmeye teminat yatırmasına olanak tanıyan kritik bir özelliktir. Kullanıcının kredi alabilmesi için gerekli bir adımdır ve teminatın sözleşme içinde doğru biçimde hesaplanıp saklanmasını sağlar.
Fonksiyon, kullanıcının sıfırdan büyük geçerli bir miktar sağladığını doğrular ve yatırılan miktar kadar kullanıcının teminat bakiyesini artırır. Token'ları kullanıcıdan sözleşmeye aktarmak için transferFrom kullanır; bu, kullanıcının bu fonksiyonu çağırmadan önce sözleşmenin token'larını harcamasına onay vermesini gerektirir.
Bu fonksiyon şunları mümkün kılar:
Teminat yatırma: Kullanıcılar, önceden tanımlanmış bir token'ın (collateralToken) belirli bir miktarını sözleşmeye yatırır. Bu teminat, aldıkları krediler için güvence işlevi görür.
Teminat bakiyelerini takip etme: Yatırılan miktar, collateralBalances mapping'inde takip edilen kullanıcının teminat bakiyesine eklenir.
Borçlanmayı etkinleştirme: Teminat, kullanıcının ne kadar borç alabileceğini hesaplamak için temel oluşturur.
Teminat çekme
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);
}
Bu fonksiyon, kullanıcıların yatırdıkları teminatın bir kısmını veya tamamını çekmesine olanak tanırken aktif bir kredi için güvence olarak kilitlenmiş teminatın çekilmesini engeller.
Fonksiyon, çekim miktarının sıfırdan büyük olduğunu doğrular ve kullanıcının talep edilen çekimi karşılayacak kadar kullanılabilir teminata sahip olduğunu kontrol eder. Aktif bir kredi için kilitlenmiş teminat kısmını hesaplar, kullanıcının teminat bakiyesini çekim miktarı kadar azaltır ve talep edilen token'ları sözleşmeden kullanıcıya geri aktarır.
Özetle, bu fonksiyon şunları mümkün kılar:
Teminat çekme: Kullanıcıların sözleşmedeki kullanılabilir teminatlarını çekmesine olanak tanır.
Kredi koruması: Kullanıcıların aktif bir krediyi güvence altına almak için gereken teminatı çekememesini sağlar.
Durum yönetimi: Başarılı bir çekimin ardından kullanıcının teminat bakiyesini günceller.
Kredi alma
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);
}
Bu fonksiyon, kullanıcıların yatırdıkları teminata dayanarak sözleşmeden token ödünç almasına olanak tanır. Kredi miktarı, kullanıcının yatırdığı teminat ve sözleşmenin collateral factor'ı ile sınırlandırılarak borçlanmanın güvenli sınırlar içinde kalması sağlanır. Bu fonksiyon, sistem güvenliğini korurken kredilerin kolaylaştırılmasında kilit bir rol oynar.
Fonksiyon şunları sağlar:
Kredi miktarının sıfırdan büyük olması.
Kullanıcının aktif bir kredisinin olmaması; böylece eş zamanlı birden fazla kredi alınması engellenir.
Talep edilen kredinin teminata dayalı maksimum borçlanma limitini aşmaması.
loans mapping'inin kullanıcının kredi ayrıntılarıyla güncellenmesi.
Ödünç alınan token'ların sözleşmeden kullanıcıya aktarılması.
Özetle, bu fonksiyon şunları mümkün kılar:
Kredi verme: Kullanıcıların yatırdıkları teminata dayalı token ödünç almasına olanak tanır.
Teminat yönetimi: Kredi miktarının kullanıcının borçlanma kapasitesi dahilinde kalmasını sağlar.
Kredi takibi: Aşırı borçlanmayı önlemek ve sistem bütünlüğünü sağlamak için kullanıcı kredi kayıtlarını tutar.
Kredi geri ödeme
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);
}
Bu fonksiyon, kullanıcıların aktif kredilerini kısmen veya tamamen geri ödemesine olanak tanır. Kredi durumunu günceller ve geri ödemelerin doğru şekilde işlenmesini sağlayarak sistemin bütünlüğünü korur.
Fonksiyon aşağıdaki kontrolleri ve işlemleri gerçekleştirir:
Geçersiz işlemleri önlemek için geri ödeme miktarının sıfırdan büyük olmasını sağlar.
Kullanıcının kredi ayrıntılarını alır ve devam etmeden önce aktif bir kredileri olduğunu doğrular.
Geri ödeme miktarının kalan kredi bakiyesini aşmamasını sağlar.
Belirtilen miktar için önceden onay gerektirerek geri ödeme miktarını kullanıcıdan sözleşmeye aktarır.
Geri ödeme miktarı kadar kredi bakiyesini azaltır.
Kredi tamamen geri ödendiyse fonksiyon onu pasif olarak işaretler.
Özetle, bu fonksiyon şunları mümkün kılar:
Kredi Geri Ödeme: Borçluların ödünç aldıkları miktarı sözleşmeye iade etmesine olanak tanır.
Kredi Takibi: Geri ödemenin ardından kredi bakiyesini ve durumunu günceller.
Şeffaflık: Geri ödeme işlemlerini zincir üzerinde kaydetmek için bir event tetikler.
Testler
src klasöründe bir Token.sol dosyası oluşturun ve aşağıdaki kodu dosyaya ekleyin.
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);
}
}
test klasöründe bir lending.t.sol dosyası oluşturun ve aşağıdaki kodu dosyaya ekleyin.
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);
}
}
Test kurulumu
Bu fonksiyon her test fonksiyonundan önce çağrılır ve durumu başlatmak için kullanılır.
Token sözleşmelerini dağıtır: Hem collateral hem de lendingToken sözleşmeleri dağıtılır.
LendingBorrowing sözleşmesini dağıtır: LendingBorrowing sözleşmesi, collateral token, lendingToken ve %80'lik bir teminat-kredi oranıyla (yani kullanıcının yalnızca teminat değerinin %80'ine kadar borç alabileceği anlamına gelir) başlatılır.
Token basar:- Kullanıcı 1 için 100 collateral token basılır.
Borç verme sözleşmesine 1000 lending token basılır.
Teminat yatırma testi
Bu fonksiyon, bir kullanıcının borç verme sözleşmesine teminat yatırabildiğini test eder. Kullanıcı 1, borç verme sözleşmesinin en fazla 100 collateral token harcamasını onaylar ve sözleşmeye 50 collateral token yatırır. Fonksiyon şunları doğrular:
Kullanıcı 1'in bakiyesi 50 token azalır.
Borç verme sözleşmesinin collateral bakiyesi 50 token artar.
Kredi alma testi
Bu fonksiyon, bir kullanıcının yatırdığı teminata dayanarak kredi alabildiğini test eder. Kullanıcı 1, 50 collateral token yatırır ve borç verme sözleşmesinin bunları harcamasını onaylar.
Test, izin verilen miktardan yüksek veya gerekli minimumun altında (teminata göre) kredi almanın geri döndürüldüğünü doğrular.
Kullanıcı 1, 40 lendingToken token'lık bir krediyi başarıyla alır.
Test, kredi alındıktan sonra Kullanıcı 1'in 40 lendingToken token aldığını doğrular.
Kredi geri ödeme testi
Bu fonksiyon, bir kullanıcının kredisini doğru şekilde geri ödeyebildiğini test eder.
Kullanıcı 1, 50 collateral token yatırır ve 40 lendingToken token'lık bir kredi alır.
Kullanıcı 1, borç verme sözleşmesinin 40 lendingToken token harcamasını onaylar ve krediyi geri öder.
Test, kredi geri ödendikten sonra Kullanıcı 1'in lendingToken bakiyesinin sıfır olduğunu doğrular.
Teminat çekme testi
Bu fonksiyon, bir kullanıcının krediyi geri ödedikten sonra teminatını çekebildiğini test eder.
Kullanıcı 1, 50 collateral token yatırır, 40 lendingToken token'lık bir kredi alır ve krediyi geri öder.
Kredi geri ödendikten sonra Kullanıcı 1 teminatını çeker.
Test şunları doğrular:- Kullanıcı 1, 50 collateral token'ını geri alır.
Kullanıcı 1'in bakiyesi 100'dür (başlangıçta 100 token bastığı için).
Kredi geri ödendikten sonra Kullanıcı 1'in lendingToken bakiyesi sıfırdır.
Testi çalıştırma
forge test
Linea'da dağıtım ve doğrulama
.env dosyasına gerekli değişkenleri ekleyin; .env dosyası kök dizinde olmalıdır.
LINEA_RPC_URL=https://linea-mainnet.infura.io/v3/
PRIVATE_KEY=*************************************************
Aşağıdaki ayrıntıları foundry.toml dosyasına ekleyin.
[etherscan]
linea = { key = "${LINEA_API_KEY}", url = "https://api-sepolia.lineascan.build/api" }
Bir Makefile oluşturun ve aşağıdaki ayrıntıları ekleyin.
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
Dağıtım
make deploy
Doğrulama
make verify
Sonuç
Basit bir borç verme ve borç alma akıllı sözleşmesi oluşturmak, DeFi ve blockchain geliştirmeyi anlamak için bir temel sağlar. Bu kılavuzda şunlar ele alındı:
Teminat yatırma – Kullanıcılar varlıklarını krediler için güvence olarak kilitler.
Kredi alma – Borçlular teminatlarına dayanarak fonlara erişir.
Kredi geri ödeme – Kullanıcılar borçlarını kapatmak için ödünç aldıkları fonları iade eder.
Teminat çekme – Kullanıcılar tam geri ödemenin ardından teminatlarını geri alır.
Bu unsurları bir araya getirerek işlevsel ve otomatik bir borç verme sistemi oluşturduk. DeFi büyüdükçe bu kavramlar, daha gelişmiş finansal uygulamalar için yapı taşları işlevi görür.
Daha fazla uygulamalı eğitim ve blockchain geliştirmeye derinlemesine bakış için MetaMask Developer YouTube kanalına göz atın ve Twitter üzerinden bizi takip ederek en güncel bilgilerden haberdar olun.