Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions academy/lending-protocol/contracts/CollateralManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ pragma solidity ^0.8.28;
import "@nilfoundation/smart-contracts/contracts/Nil.sol";
import "@nilfoundation/smart-contracts/contracts/NilTokenBase.sol";

/// @title GlobalLedger
/// @dev The GlobalLedger contract is responsible for tracking user deposits and loans in the lending protocol.
/// It stores the deposit balances for users and keeps track of the loans each user has taken.
contract GlobalLedger {
// Contract to handle collateral manager functionality and embedded GlobalLedger
contract CollateralManager {
// Define the role-based access modifier for Factory control
address public lendingPoolFactory;

/// @dev Mapping of user addresses to their token deposits (token -> amount).
mapping(address => mapping(TokenId => uint256)) public deposits;

Expand All @@ -20,12 +21,30 @@ contract GlobalLedger {
TokenId token;
}

/// @notice Modifier to restrict access to only the lending pool factory
modifier onlyLendingPoolFactory() {
require(
msg.sender == lendingPoolFactory,
"Only LendingPoolFactory can call this"
);
_;
}

// Constructor to set the factory address
constructor(address _lendingPoolFactory) {
lendingPoolFactory = _lendingPoolFactory;
}

/// @notice Records a user's deposit into the ledger.
/// @dev Increases the deposit balance for the user for the specified token.
/// @param user The address of the user making the deposit.
/// @param token The token type being deposited (e.g., USDT, ETH).
/// @param amount The amount of the token being deposited.
function recordDeposit(address user, TokenId token, uint256 amount) public {
function recordDeposit(
address user,
TokenId token,
uint256 amount
) public onlyLendingPoolFactory {
deposits[user][token] += amount;
}

Expand All @@ -46,7 +65,11 @@ contract GlobalLedger {
/// @param user The address of the user taking the loan.
/// @param token The token type used for the loan (e.g., USDT, ETH).
/// @param amount The amount of the loan being taken.
function recordLoan(address user, TokenId token, uint256 amount) public {
function recordLoan(
address user,
TokenId token,
uint256 amount
) public onlyLendingPoolFactory {
loans[user] = Loan(amount, token);
}

Expand All @@ -60,4 +83,12 @@ contract GlobalLedger {
) public view returns (uint256, TokenId) {
return (loans[user].amount, loans[user].token);
}

/// @notice Allows the lending pool factory to set the factory address if required
/// @param newFactory Address of the new lending pool factory
function setLendingPoolFactory(
address newFactory
) external onlyLendingPoolFactory {
lendingPoolFactory = newFactory;
}
}
90 changes: 90 additions & 0 deletions academy/lending-protocol/contracts/LendingPoolFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

import "./LendingPool.sol";
import "@nilfoundation/smart-contracts/contracts/Nil.sol";

/// @title LendingPoolFactory
/// @dev Deploys LendingPool contracts across shards and registers them in GlobalLedger
contract LendingPoolFactory {
address public globalLedger;
uint8 public globalLedgerShardId;
address public interestManager;
address public oracle;
TokenId public usdt;
TokenId public eth;

uint8 public shardCounter;
uint256 public saltCounter; //added for uniqueness in deployments

event LendingPoolDeployed(address pool, uint8 shardId, address owner);

constructor(
address _globalLedger,
uint8 _globalLedgerShardId,
address _interestManager,
address _oracle,
TokenId _usdt,
TokenId _eth
) {
globalLedger = _globalLedger;
globalLedgerShardId = _globalLedgerShardId;
interestManager = _interestManager;
oracle = _oracle;
usdt = _usdt;
eth = _eth;
shardCounter = 0;
saltCounter = 0;
}

function deployLendingPool() external {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the deployment of the contract, there should be a function which calls the globalLedger to register the lending pool

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well noted Sir, I will make changes

bytes memory constructorArgs = abi.encode(
globalLedger,
interestManager,
oracle,
usdt,
eth,
msg.sender
);

bytes memory bytecode = bytes.concat(
type(LendingPool).creationCode,
constructorArgs
);

// Deploy the LendingPool contract to the next shard using salt for uniqueness
address poolAddress = Nil.asyncDeploy(
shardCounter,
msg.sender,
address(0),
0,
0,
0,
bytecode,
saltCounter //dynamic salt value
);

//increment salt counter to avoid reuse
unchecked {
saltCounter++;
}

Nil.asyncCall(
globalLedgerShardId,
address(0),
globalLedger,
0,
0,
0,
abi.encodeWithSignature(
"registerLendingPool(address)",
poolAddress
),
0
);

emit LendingPoolDeployed(poolAddress, shardCounter, msg.sender);

shardCounter = (shardCounter + 1) % 4; // Cycle through 4 shards
}
}
25 changes: 10 additions & 15 deletions academy/lending-protocol/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,31 @@
import "@nomicfoundation/hardhat-chai-matchers";
import "@nomicfoundation/hardhat-ignition-ethers";
import "@nomicfoundation/hardhat-ethers";
import "@nomicfoundation/hardhat-ignition-ethers";
import "@typechain/hardhat";
import "@nomicfoundation/hardhat-toolbox";
import "@nomiclabs/hardhat-ethers";


import * as dotenv from "dotenv";
import type { HardhatUserConfig } from "hardhat/config";

// Import niljs (correct scoped package)
import "@nilfoundation/niljs";

import "./task/run-lending-protocol";

dotenv.config();
dotenv.config(); // Load .env variables

const config: HardhatUserConfig = {
ignition: {
requiredConfirmations: 1,
},
defaultNetwork: "nil",
solidity: {
version: "0.8.28", // or your desired version
version: "0.8.28", // Match your Solidity version
settings: {
viaIR: true, // needed to compile router
optimizer: {
enabled: true,
runs: 200,
},
},
},
networks: {
nil: {
url: process.env.NIL_RPC_ENDPOINT,
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
},
},
};

export default config;
export default config;
Loading