diff --git a/hardhat/contracts/BorrowerManager.sol b/hardhat/contracts/BorrowerManager.sol new file mode 100644 index 0000000..9fc498c --- /dev/null +++ b/hardhat/contracts/BorrowerManager.sol @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "./ValeToken.sol"; +import "./VaultManager.sol"; + +interface IDataStorage { + struct ValidatorInfo { + uint256 balance; + uint256 rewards; + uint256 lastTimestamp; + } + + struct PriceInfo { + uint256 price; // ETH price in USD (with 8 decimals) + uint256 lastTimestamp; + } + + function getValidatorInfo(string memory _validatorId) external view returns (ValidatorInfo memory); + function ethPrice() external view returns (PriceInfo memory); +} + +contract BorrowerManager is ReentrancyGuard, Ownable { + IDataStorage public oracle; + + struct CompleteValidatorInfo { + uint256 balance; // in wei + uint256 rewards; // in wei + uint256 ethPrice; // ETH/USD with 8 decimals + uint256 balanceUSD; // balance in USD with 8 decimals + uint256 rewardsUSD; // rewards in USD with 8 decimals + uint256 validatorTimestamp; + uint256 priceTimestamp; + } + ValeToken public valeToken; + VaultManager public vaultmanager; + IERC20 public usdc; + + uint256 public constant LTV_RATIO = 85; // 85% rate loan/value max + uint256 public constant RATIO_DENOMINATOR = 100; + uint256 public constant LIQUIDATION_AMOUNT = 32 ether; + uint256 public lastMonthTotalRewards = 0; + uint256[] public validatorTokenIds; + + + struct BorrowerInfo { + uint256 debt; + uint256 validatorTokenId; + uint256 borrowTimestamp; + bool isLiquidated; + } + + mapping(address => BorrowerInfo) public borrowers; + mapping(uint256 => address) public validatorOwners; + mapping(uint256 => uint256) public validatorPrices; // Prix des validators + + + event Liquidated( + address indexed borrower, + address indexed liquidator, + uint256 tokenId, + uint256 debt, + uint256 bonus + ); + + constructor(address _valeToken, address _usdc, address _vaultmanager) Ownable(msg.sender) { + valeToken = ValeToken(_valeToken); + vaultmanager = VaultManager(_vaultmanager); + usdc = IERC20(_usdc); + oracle = IDataStorage(0x22Ba0717ff5b1382B92AbD1d07aD03639f5E2d9b); + } + + function getCompleteValidatorInfo(string memory _validatorId) public view returns (CompleteValidatorInfo memory info) + { + // Get validator data + IDataStorage.ValidatorInfo memory validatorData = oracle.getValidatorInfo(_validatorId); + + // Get price data + IDataStorage.PriceInfo memory priceData = oracle.ethPrice(); + + // Calculate USD values (considering 18 decimals for ETH and 8 decimals for price) + uint256 balanceUSD = (validatorData.balance * priceData.price) / 1e18; + uint256 rewardsUSD = (validatorData.rewards * priceData.price) / 1e18; + + return CompleteValidatorInfo({ + balance: validatorData.balance, + rewards: validatorData.rewards, + ethPrice: priceData.price, + balanceUSD: balanceUSD, + rewardsUSD: rewardsUSD, + validatorTimestamp: validatorData.lastTimestamp, + priceTimestamp: priceData.lastTimestamp + }); + } + + // Ajouter un validateur à la liste (appelé lors de l'ajout d'un NFT) + function addValidator(uint256 tokenId) internal { + validatorTokenIds.push(tokenId); + } + + // Supprime un validateur (ex : en cas de liquidation) + function removeValidator(uint256 tokenId) internal { + for (uint256 i = 0; i < validatorTokenIds.length; i++) { + if (validatorTokenIds[i] == tokenId) { + validatorTokenIds[i] = validatorTokenIds[validatorTokenIds.length - 1]; // Remplace par le dernier élément + validatorTokenIds.pop(); // Supprime le dernier élément + break; + } + } + } + + function borrow(uint256 tokenId, address borrower) external nonReentrant { + // Fetch the balance of the validator and the ethprice + CompleteValidatorInfo memory info = getCompleteValidatorInfo(valeToken.getPublicKey(tokenId)); + uint256 validatorValue = info.balance; + uint256 amount = info.ethPrice* validatorValue; + require(amount > 0, "Amount must be greater than 0"); + require(borrowers[borrower].debt == 0, "Existing debt must be repaid"); + + //Calcul max Borrox + uint256 maxBorrow = (validatorValue * LTV_RATIO) / RATIO_DENOMINATOR; + require(amount <= maxBorrow, "Amount exceeds maximum borrowable value"); + + //Depose the NFT on the contract + valeToken.transferFrom(borrower, address(this), tokenId); + + borrowers[borrower] = BorrowerInfo({ + debt: amount, + validatorTokenId: tokenId, + borrowTimestamp: block.timestamp, + isLiquidated: false + }); + validatorOwners[tokenId] = borrower; + addValidator(tokenId); + lastMonthTotalRewards += info.rewards; + + usdc.transferFrom(address(vaultmanager), borrower,amount); + } + + function repay(address borrower) external nonReentrant { + BorrowerInfo storage info = borrowers[borrower]; + uint256 tokenId = info.validatorTokenId; + CompleteValidatorInfo memory complete = getCompleteValidatorInfo(valeToken.getPublicKey(tokenId)); + + require(info.debt > 0, "No debt to repay"); + require(!info.isLiquidated, "Position liquidated"); + + uint256 amount = info.debt * complete.ethPrice; + + usdc.transferFrom(borrower, address(vaultmanager), amount); + valeToken.transferFrom(address(this), borrower, tokenId); + + removeValidator(info.validatorTokenId); + lastMonthTotalRewards-= complete.rewards; + + delete borrowers[borrower]; + delete validatorOwners[tokenId]; + } + + + function canBeLiquidated(address borrower) public view returns (bool) { + BorrowerInfo memory info = borrowers[borrower]; + uint256 tokenId = info.validatorTokenId; + if (info.debt == 0 || info.isLiquidated) return false; + + CompleteValidatorInfo memory validator_info = getCompleteValidatorInfo(valeToken.getPublicKey(tokenId)); + uint256 validatorBalance = validator_info.balance; + + return validatorBalance >= LIQUIDATION_AMOUNT; + } + + function liquidate(address borrower) external nonReentrant { + BorrowerInfo storage info = borrowers[borrower]; + uint256 debt = info.debt; + uint256 tokenId = info.validatorTokenId; + require(canBeLiquidated(borrower), "Position not liquidatable"); + + // Transférer le NFT à l'adresse du contrat (vaultManager) + valeToken.transferFrom(address(this), msg.sender, tokenId); + + // Marquer la position comme liquidée + info.isLiquidated = true; + + removeValidator(info.validatorTokenId); + CompleteValidatorInfo memory toremove = getCompleteValidatorInfo(valeToken.getPublicKey(tokenId)); + + lastMonthTotalRewards-= toremove.rewards; + + // Émettre l'événement de liquidation + emit Liquidated(borrower, msg.sender, tokenId, debt, 0); + } + + function getTotalBorrowedTokens() public view returns (uint256) { + uint256 totalBorrowed = 0; + + for (uint256 i = 0; i < validatorTokenIds.length; i++) { + uint256 tokenId = validatorTokenIds[i]; + address borrower = validatorOwners[tokenId]; + + if (borrower != address(0)) { // Vérifier que le NFT est bien emprunté + totalBorrowed += borrowers[borrower].debt; + }} + return totalBorrowed; + } + + // Fonction pour calculer les rewards mensuels sans paramètre + function calculateMonthlyRewards() public returns (uint256) { + uint256 totalCurrentRewards = 0; + + // Parcours tous les validateurs enregistrés + for (uint256 i = 0; i < validatorTokenIds.length; i++) { + string memory publicKey = valeToken.getPublicKey(validatorTokenIds[i]); + CompleteValidatorInfo memory info = getCompleteValidatorInfo(publicKey); + totalCurrentRewards += info.rewards; + } + + uint256 rate_loan_value = vaultmanager.getUtilizationRatio(); + + // Calcul des nouveaux rewards gagnés ce mois-ci + uint256 monthlyRewards = totalCurrentRewards - lastMonthTotalRewards; + uint256 monthlyRewards_loaners = monthlyRewards*rate_loan_value; + + lastMonthTotalRewards = totalCurrentRewards; + + return monthlyRewards_loaners; // Cette valeur sera redistribuée aux prêteurs + } + +} \ No newline at end of file diff --git a/hardhat/contracts/DataStorage.sol b/hardhat/contracts/DataStorage.sol deleted file mode 100644 index ad7e405..0000000 --- a/hardhat/contracts/DataStorage.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract DataStorage { - string public lastData; - uint256 public lastTimestamp; - address public owner; - - event DataUpdated(string data, uint256 timestamp); - - constructor() { - owner = msg.sender; - } - - modifier onlyOwner() { - require(msg.sender == owner, "Not owner"); - _; - } - - function updateData(string memory _data) public onlyOwner { - lastData = _data; - lastTimestamp = block.timestamp; - emit DataUpdated(_data, block.timestamp); - } - - function getData() public view returns (string memory, uint256) { - return (lastData, lastTimestamp); - } -} \ No newline at end of file diff --git a/hardhat/contracts/LendingPool.sol b/hardhat/contracts/LendingPool.sol new file mode 100644 index 0000000..aa8ea23 --- /dev/null +++ b/hardhat/contracts/LendingPool.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "./VaultManager.sol"; +import "./BorrowerManager.sol"; + + +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract LendingPool is Ownable { + VaultManager public vaultManager; + BorrowerManager public borrowerManager; + + constructor( + address _usdc, + address _validatorNFT, + address _vaultmanager + ) Ownable(msg.sender) { + vaultManager = new VaultManager(_usdc); + borrowerManager = new BorrowerManager(_validatorNFT, _usdc, _vaultmanager); + } + + // Fonction pour les prêteurs + function deposit(uint256 amount) external { + vaultManager.deposit(amount, msg.sender); + } + + function withdraw(uint256 amount) external { + vaultManager.withdraw(amount, msg.sender, msg.sender); + } + + function distributeinterests(address user) external{ + vaultManager.distributeinterests(msg.sender); + } + + function claimPendingToShares(address user) external { + vaultManager.claimPendingToShares(msg.sender); + } + + function getPendingAmount(address user) external{ + vaultManager.getPendingAmount(msg.sender); + } + + // Fonction pour les emprunteurs + function borrow(uint256 tokenId, address borrower) external { + borrowerManager.borrow(tokenId, borrower); + } + + function repay() external { + borrowerManager.repay(msg.sender); + } + + function canBeLiquidated(address borrower) external { + borrowerManager.canBeLiquidated(borrower); + } + + function liquidate(address borrower) external { + borrowerManager.liquidate(borrower); + } + +} \ No newline at end of file diff --git a/hardhat/contracts/RewardManager.sol b/hardhat/contracts/RewardManager.sol new file mode 100644 index 0000000..d5d7ff0 --- /dev/null +++ b/hardhat/contracts/RewardManager.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "./ValeToken.sol"; + +interface IDataStorage { + struct ValidatorInfo { + uint256 balance; + uint256 rewards; + uint256 lastTimestamp; + } + + struct PriceInfo { + uint256 price; // ETH price in USD (with 8 decimals) + uint256 lastTimestamp; + } + + function getValidatorInfo(string memory _validatorId) external view returns (ValidatorInfo memory); + function ethPrice() external view returns (PriceInfo memory); +} + +contract RewardManager is Ownable { + IERC20 public usdc; + ValeToken public valeToken; + + IDataStorage public oracle; + + struct CompleteValidatorInfo { + uint256 balance; // in wei + uint256 rewards; // in wei + uint256 ethPrice; // ETH/USD with 8 decimals + uint256 balanceUSD; // balance in USD with 8 decimals + uint256 rewardsUSD; // rewards in USD with 8 decimals + uint256 validatorTimestamp; + uint256 priceTimestamp; + } + + uint256 public totalRewardsCollected; + uint256 public lastRewardDistribution; + uint256 public constant REWARD_RATE = 500; // 5% annuel + uint256 public constant COMPANY_SHARE = 2000; // 20% pour l'entreprise + uint256 public constant TOTAL_BASIS_POINTS = 10000; // 100% + + address public companyWallet; + uint256 public companyRewards; + + event RewardsCollected(uint256 total, uint256 companyPart, uint256 lendersPart); + event CompanyRewardsWithdrawn(uint256 amount); + + constructor(address _usdc, address _valeToken) Ownable(msg.sender) { + usdc = IERC20(_usdc); + oracle = IDataStorage(0x17BAa4ab9145654365cB6C87F1D3722e5b247900); + lastRewardDistribution = block.timestamp; + valeToken = ValeToken(_valeToken); + } + + function getCompleteValidatorInfo(string memory _validatorId) public view returns (CompleteValidatorInfo memory info) + { + // Get validator data + IDataStorage.ValidatorInfo memory validatorData = oracle.getValidatorInfo(_validatorId); + + // Get price data + IDataStorage.PriceInfo memory priceData = oracle.ethPrice(); + + // Calculate USD values (considering 18 decimals for ETH and 8 decimals for price) + uint256 balanceUSD = (validatorData.balance * priceData.price) / 1e18; + uint256 rewardsUSD = (validatorData.rewards * priceData.price) / 1e18; + + return CompleteValidatorInfo({ + balance: validatorData.balance, + rewards: validatorData.rewards, + ethPrice: priceData.price, + balanceUSD: balanceUSD, + rewardsUSD: rewardsUSD, + validatorTimestamp: validatorData.lastTimestamp, + priceTimestamp: priceData.lastTimestamp + }); + } + + function setCompanyWallet(address _wallet) external onlyOwner { + companyWallet = _wallet; + } + + function collectAndDistribute(uint256[] memory validators, uint256 totalDeposits) external { + uint256 newRewards = calculateValidatorRewards(validators); + + // Part entreprise + uint256 companyPart = (newRewards * COMPANY_SHARE) / TOTAL_BASIS_POINTS; + companyRewards += companyPart; + + // Part prêteurs + uint256 lendersPart = newRewards - companyPart; + totalRewardsCollected += lendersPart; + + emit RewardsCollected(newRewards, companyPart, lendersPart); + + // Distribution aux prêteurs si il y a des dépôts + if (totalDeposits > 0) { + uint256 timeElapsed = block.timestamp - lastRewardDistribution; + uint256 rewardsToDistribute = (totalDeposits * REWARD_RATE * timeElapsed) / (365 days * 10000); + + if (rewardsToDistribute > totalRewardsCollected) { + rewardsToDistribute = totalRewardsCollected; + } + + totalRewardsCollected -= rewardsToDistribute; + lastRewardDistribution = block.timestamp; + + usdc.transfer(address(this), rewardsToDistribute); + } + } + + function withdrawCompanyRewards() external { + require(msg.sender == companyWallet, "Only company wallet"); + require(companyRewards > 0, "No rewards to withdraw"); + + uint256 amount = companyRewards; + companyRewards = 0; + + require(usdc.transfer(companyWallet, amount), "Transfer failed"); + emit CompanyRewardsWithdrawn(amount); + } + + function calculateValidatorRewards(uint256[] memory validators) internal view returns (uint256) { + // À implémenter : calcul réel des rewards + //return 0.1 ether * validators.length; + } + + function testoracle() external view returns (uint256,uint256,uint256,uint256){ + CompleteValidatorInfo memory validator_info = getCompleteValidatorInfo(valeToken.getPublicKey(1)); + return (validator_info.balance, validator_info.rewards, validator_info.ethPrice, validator_info.validatorTimestamp); + } + +} \ No newline at end of file diff --git a/hardhat/contracts/Usdc.sol b/hardhat/contracts/Usdc.sol new file mode 100644 index 0000000..0eada28 --- /dev/null +++ b/hardhat/contracts/Usdc.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract Usdc is ERC20 { + constructor() ERC20("Mock USDC", "USDC") { + _mint(msg.sender, 100000000000000000000 * 10**6); // 1 million USDC avec 6 décimales + } + + function mint(address to, uint256 amount) external { + _mint(to, amount); + } +} diff --git a/hardhat/contracts/ValeToken.sol b/hardhat/contracts/ValeToken.sol new file mode 100644 index 0000000..40c6e0f --- /dev/null +++ b/hardhat/contracts/ValeToken.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract ValeToken is ERC721, Ownable { + // Available public keys definition + string[] public availablePublicKeys = [ + "0x91104f28e17de8c6bec26c5a8e64a149ba3ed2a35273197c33ed2f2bc74b8dbda96f9098517a6e946247c169c89deb34", //21958 + "0x820b2cf260a032e87555692de4732ae05f92b37f9a9153e684c43e31aea4b974245a33fecf9e137408c8ede88fe54f1e", //66458 + "0x85ba506bab27f6f32063a5c1b8392390c65f2ef5a6ca11ed29d3edae4788aec30c8e5af99412e47c66cbd10a6a34f92f", //17970 + "0xaed72df183c23c2820774bf4729402130bcce5d83e861a9eb2cf6b7e12eca818df39088c35a109437a6f4fa06649fb37", //89290 + "0x9217e329dbf1ec6f2ef3f048c92e2035d7dea61ad0a6ed2a82db40769635d5e024a8fd1ef38892a77bbc56f99decc34a" //170221 + ]; + + uint256 private currentKeyIndex; + uint256 private _nextTokenId; + + // Mapping to associate tokenId with its public key + mapping(uint256 => string) private tokenToPublicKey; + + constructor() ERC721("ValeToken", "VALE") Ownable(msg.sender) { + // Mint all NFTs at deployment + for(uint256 i = 0; i < availablePublicKeys.length; i++) { + mint(msg.sender); + } + } + + function mint(address to) public onlyOwner { + require(currentKeyIndex < availablePublicKeys.length, "All public keys have been assigned"); + + uint256 tokenId = _nextTokenId++; + string memory publicKey = availablePublicKeys[currentKeyIndex]; + + _safeMint(to, tokenId); + tokenToPublicKey[tokenId] = publicKey; + currentKeyIndex++; + } + + function getPublicKey(uint256 tokenId) public view returns (string memory) { + require(_ownerOf(tokenId) != address(0), "Token does not exist"); + return tokenToPublicKey[tokenId]; + } +} diff --git a/hardhat/contracts/VaultManager.sol b/hardhat/contracts/VaultManager.sol new file mode 100644 index 0000000..bca0779 --- /dev/null +++ b/hardhat/contracts/VaultManager.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "./BorrowerManager.sol"; + + +contract VaultManager is ERC4626 { + uint256 private constant LOCK_PERIOD = 30 days; + uint256 private constant MIN_DEPOSIT = 100e6; // 100 USDC (6 decimals) + + uint256 private totalInterestsEarned; + uint256 private interestsPerShare; + uint256 private constant interestS_PRECISION = 1e12; + uint256 public totalWithdrawn; + + BorrowerManager public borrowerManager; + + mapping(address => uint256) public depositTimestamps; + mapping(address => uint256) public interestDebt; + mapping(address => uint256) public pendingAmounts; + + event interestsDistributed(uint256 amount); + event interestsClaimed(address indexed user, uint256 amount); + + constructor(address _usdc) ERC4626(IERC20(_usdc)) ERC20("Vale Part", "VP") {} + + function deposit(uint256 assets, address receiver) public override returns (uint256) { + require(assets >= MIN_DEPOSIT, "Minimum deposit is 100 USDC"); + depositTimestamps[receiver] = block.timestamp; + updateinterestDebt(receiver); + + uint256 shares = super.deposit(assets, receiver); + interestDebt[receiver] = (shares * interestsPerShare) / interestS_PRECISION; + + return shares; + } + + // withdraw to track withdrawals +function withdraw(uint256 assets, address receiver, address owner) public override returns (uint256) { + require( + block.timestamp >= depositTimestamps[owner] + LOCK_PERIOD, + "Funds are locked for 30 days" + ); + + claimPendingToShares(owner); + + totalWithdrawn += assets; + return super.withdraw(assets, receiver, owner); +} + + function getUserSharePercentage(address user) public view returns (uint256) { + uint256 totalShares = totalSupply(); + if (totalShares == 0) return 0; + return (balanceOf(user) * 10000) / totalShares; + } + + function distributeinterests(address user) public { + uint256 totalAmount= borrowerManager.calculateMonthlyRewards(); + // Get user share percentage (in basis points) + uint256 userPercentage = getUserSharePercentage(user); + require(userPercentage > 0, "No shares owned"); + + // Calculate user's portion of amount + uint256 userAmount = (totalAmount * userPercentage) / 10000; + + // Add to pending amounts + pendingAmounts[user] += userAmount; +} + + function claimPendingToShares(address user) public returns (uint256) { + uint256 pendingAmount = pendingAmounts[user]; + require(pendingAmount > 0, "No pending rewards"); + + // Convert pending amount to shares + uint256 newShares = convertToShares(pendingAmount); + + // Reset pending amount + pendingAmounts[user] = 0; + + // Mint new shares to user + _mint(user, newShares); + + return newShares; +} + +function getPendingAmount(address user) public view returns (uint256) { + return pendingAmounts[user]; +} + +// Add function to get current lending amount +function getCurrentLendingAmount() public view returns (uint256) { + uint256 totalDeposited = totalAssets(); // From ERC4626 + return totalDeposited - totalWithdrawn; +} + +function getUtilizationRatio() public view returns (uint256) { + uint256 currentLending = getCurrentLendingAmount(); + if (currentLending == 0) return 0; + + uint256 totalBorrowed = borrowerManager.getTotalBorrowedTokens(); + return (totalBorrowed * 10000) / currentLending; + } + + function updateinterestDebt(address user) internal { + uint256 shares = balanceOf(user); + if (shares > 0) { + interestDebt[user] = (shares * interestsPerShare) / interestS_PRECISION; + } + } + + +} \ No newline at end of file diff --git a/hardhat/hardhat.config.js b/hardhat/hardhat.config.js index 109778e..a6c668f 100644 --- a/hardhat/hardhat.config.js +++ b/hardhat/hardhat.config.js @@ -1,10 +1,11 @@ require("@nomicfoundation/hardhat-toolbox"); +require("@nomicfoundation/hardhat-verify"); require("dotenv").config(); module.exports = { - solidity: "0.8.19", + solidity: "0.8.20", paths: { - sources: "../contracts", + sources: "./contracts", artifacts: "./artifacts", cache: "./cache" }, @@ -19,4 +20,4 @@ module.exports = { etherscan: { apiKey: process.env.ETHERSCAN_API_KEY } -}; \ No newline at end of file +}; \ No newline at end of file diff --git a/hardhat/package-lock.json b/hardhat/package-lock.json index 1af86ee..45ba9b4 100644 --- a/hardhat/package-lock.json +++ b/hardhat/package-lock.json @@ -8,6 +8,9 @@ "name": "hardhat", "version": "1.0.0", "license": "ISC", + "dependencies": { + "@openzeppelin/contracts": "^5.2.0" + }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", "dotenv": "^16.4.7", @@ -1509,6 +1512,12 @@ "node": ">= 12" } }, + "node_modules/@openzeppelin/contracts": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.2.0.tgz", + "integrity": "sha512-bxjNie5z89W1Ea0NZLZluFh8PrFNn9DH8DQlujEok2yjsOlraUPKID5p1Wk3qdNbf6XkQ1Os2RvfiHrrXLHWKA==", + "license": "MIT" + }, "node_modules/@scure/base": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", diff --git a/hardhat/package.json b/hardhat/package.json index 1d49899..451d5f3 100644 --- a/hardhat/package.json +++ b/hardhat/package.json @@ -13,5 +13,8 @@ "@nomicfoundation/hardhat-toolbox": "^5.0.0", "dotenv": "^16.4.7", "hardhat": "^2.22.18" + }, + "dependencies": { + "@openzeppelin/contracts": "^5.2.0" } } diff --git a/hardhat/scripts/deploy.js b/hardhat/scripts/deploy.js deleted file mode 100644 index 933276b..0000000 --- a/hardhat/scripts/deploy.js +++ /dev/null @@ -1,28 +0,0 @@ -async function main() { - const DataStorage = await ethers.getContractFactory("DataStorage"); - const dataStorage = await DataStorage.deploy(); - - // Wait for the deployment transaction to be mined - await dataStorage.waitForDeployment(); - - const deployedAddress = await dataStorage.getAddress(); - console.log("DataStorage deployed to:", deployedAddress); - - console.log("Waiting for block confirmations..."); - // Wait for few block confirmations - const deploymentReceipt = await dataStorage.deploymentTransaction().wait(6); - - // Verify the contract - console.log("Verifying contract..."); - await hre.run("verify:verify", { - address: deployedAddress, - constructorArguments: [], - }); -} - -main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error); - process.exit(1); - }); \ No newline at end of file diff --git a/hardhat/scripts/deployAll.js b/hardhat/scripts/deployAll.js new file mode 100644 index 0000000..2836387 --- /dev/null +++ b/hardhat/scripts/deployAll.js @@ -0,0 +1,37 @@ +const hre = require("hardhat"); + +async function main() { +// Déploiement de ValeToken + const VaultManager = await hre.ethers.getContractFactory("VaultManager"); + const vaultManager = await VaultManager.deploy(usdcAddress); + await vaultManager.waitForDeployment(); + const vaultManagerAddress = await vaultManager.getAddress(); + console.log(`✅ VaultManager déployé à : ${vaultManagerAddress}`); + + // Déploiement de BorrowerManager + const BorrowerManager = await hre.ethers.getContractFactory("BorrowerManager"); + const borrowerManager = await BorrowerManager.deploy(valeTokenAddress, usdcAddress, vaultManagerAddress); + await borrowerManager.waitForDeployment(); + const borrowerManagerAddress = await borrowerManager.getAddress(); + console.log(`✅ BorrowerManager déployé à : ${borrowerManagerAddress}`); + + // Déploiement de LendingPool + const LendingPool = await hre.ethers.getContractFactory("LendingPool"); + const lendingPool = await LendingPool.deploy(usdcAddress, valeTokenAddress, vaultManagerAddress); + await lendingPool.waitForDeployment(); + const lendingPoolAddress = await lendingPool.getAddress(); + console.log(`✅ LendingPool déployé à : ${lendingPoolAddress}`); + + // Approve BorrowerManager pour utiliser les tokens USDC depuis VaultManager + const approveTx = await usdc.approve(borrowerManagerAddress, hre.ethers.parseUnits("1000000", 6)); // 1M USDC + await approveTx.wait(); + console.log(`✅ VaultManager a approuvé BorrowerManager pour 1M USDC`); + + console.log("🚀 Tous les contrats ont été déployés avec succès !"); +} + +// Gestion des erreurs +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/hardhat/scripts/deployBorrowerManager.js b/hardhat/scripts/deployBorrowerManager.js new file mode 100644 index 0000000..596a133 --- /dev/null +++ b/hardhat/scripts/deployBorrowerManager.js @@ -0,0 +1,17 @@ +const hre = require("hardhat"); + +async function main() { + + const BorrowerManager = await hre.ethers.getContractFactory("BorrowerManager"); + const borrowerManager = await BorrowerManager.deploy(); + + await borrowerManager.waitForDeployment(); + + const address = await borrowerManager.getAddress(); + console.log(`BorrowerManager deployed to: ${address}`); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/hardhat/scripts/deployRewardsManager.js b/hardhat/scripts/deployRewardsManager.js new file mode 100644 index 0000000..c1d28cf --- /dev/null +++ b/hardhat/scripts/deployRewardsManager.js @@ -0,0 +1,24 @@ +const hre = require("hardhat"); + +async function main() { + const VALE_TOKEN_ADDRESS = "0x40E0f2b9f03A9Df3fC7553a91bd239AA1748Df1f"; // Adresse du token ValeToken + const USDC_ADDRESS = "0xb9284c55444a01ca79c9f839f53411f5e511ed3a"; // Adresse du token USDC + + const RewardManager = await hre.ethers.getContractFactory("RewardManager"); + + // ✅ Passer les adresses au constructeur + const rewardManager = await RewardManager.deploy(USDC_ADDRESS, VALE_TOKEN_ADDRESS); + + await rewardManager.waitForDeployment(); + const address = await rewardManager.getAddress(); + + console.log(`RewardManager deployed to: ${address}`); + + const result = await rewardManager.testoracle(); + console.log(`🔍 testoracle result:`, result.toString()); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/hardhat/scripts/deployUsdc.js b/hardhat/scripts/deployUsdc.js new file mode 100644 index 0000000..0a1f590 --- /dev/null +++ b/hardhat/scripts/deployUsdc.js @@ -0,0 +1,19 @@ +const hre = require("hardhat"); + +async function main() { + + const Usdc = await hre.ethers.getContractFactory("Usdc"); + const usdc = await Usdc.deploy(); + + await usdc.waitForDeployment(); + + const address = await usdc.getAddress(); + console.log(`Usdc deployed to: ${address}`); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); + + diff --git a/hardhat/scripts/deployValeToken.js b/hardhat/scripts/deployValeToken.js new file mode 100644 index 0000000..6c7e099 --- /dev/null +++ b/hardhat/scripts/deployValeToken.js @@ -0,0 +1,19 @@ +const hre = require("hardhat"); + +async function main() { + + const ValeToken = await hre.ethers.getContractFactory("ValeToken"); + const valeToken = await ValeToken.deploy(); + + await valeToken.waitForDeployment(); + + const address = await valeToken.getAddress(); + console.log(`ValeToken deployed to: ${address}`); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); + + diff --git a/project_structure b/project_structure deleted file mode 100644 index 7a92491..0000000 --- a/project_structure +++ /dev/null @@ -1,13 +0,0 @@ -project_root/ -├── contracts/ -│ └── DataStorage.sol -├── hardhat/ -│ ├── scripts/ -│ │ └── deploy.js -│ ├── hardhat.config.js -│ └── package.json -├── python/ -│ ├── .env -│ ├── requirements.txt -│ └── main.py -└── .gitignore \ No newline at end of file