Skip to content

Commit b0e8a84

Browse files
committed
fix: utilize Nil.tokenBalance(address) to simplify the contract
1 parent 51497b2 commit b0e8a84

1 file changed

Lines changed: 44 additions & 147 deletions

File tree

academy/lending-protocol/contracts/LendingPool.sol

Lines changed: 44 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ contract LendingPool is NilBase, NilTokenBase {
2222
error InvalidCaller();
2323
error InvalidShardId();
2424
error ExcessTransfer();
25-
error InsufficientFunds(string message);
2625
error InvalidPoolAddress();
2726
error PoolAlreadyRegistered();
2827
error InvalidTransferAmount();
2928
error InsufficientCollateral();
29+
error NoLendingPoolsRegistered();
3030
error FailedToRetrieveCollateral();
31+
error InsufficientFunds(string message);
3132
error CrossShardCallFailed(string message);
3233

3334
/// @dev Mapping to track lending pools on different shards
@@ -65,12 +66,16 @@ contract LendingPool is NilBase, NilTokenBase {
6566
eth = _eth;
6667

6768
deployer = msg.sender;
69+
70+
/// @notice Register the current contract as a lending pool
71+
/// @dev This ensures that the current contract is recognized as a valid lending pool
72+
registerLendingPool(address(this));
6873
}
6974

7075
/// @notice Register a new lending pool on a different shard
7176
/// @dev Allows registration of other lending pools for cross-shard borrowing
7277
/// @param poolAddress The address of the lending pool to register
73-
function registerLendingPool(address poolAddress) external onlyDeployer {
78+
function registerLendingPool(address poolAddress) public onlyDeployer {
7479
if (poolAddress == address(0)) revert InvalidPoolAddress();
7580

7681
uint256 shardId = Nil.getShardId(poolAddress);
@@ -82,101 +87,6 @@ contract LendingPool is NilBase, NilTokenBase {
8287
lendingPoolCount++;
8388
}
8489

85-
/// @notice Check liquidity across all registered lending pools
86-
/// @dev Queries each registered lending pool for available liquidity
87-
/// @param token The token to check liquidity for
88-
/// @param amount The amount needed
89-
/// @param requestId Unique identifier for this borrow request
90-
function checkCrossShardLiquidity(
91-
TokenId token,
92-
uint256 amount,
93-
bytes32 requestId,
94-
address borrower
95-
) internal {
96-
uint256 currentShardId = Nil.getShardId(address(this));
97-
98-
if (lendingPoolCount > 0) {
99-
for (uint256 i = 0; i < lendingPools.length; i++) {
100-
address poolAddress = lendingPools[i];
101-
uint256 poolShardId = Nil.getShardId(poolAddress);
102-
103-
// Skip if the pool is on the same shard
104-
if (poolShardId == currentShardId) {
105-
continue;
106-
}
107-
108-
// Query the other pool's token balance
109-
bytes memory callData = abi.encodeWithSignature(
110-
"getTokenBalance(address)",
111-
token
112-
);
113-
114-
bytes memory context = abi.encodeWithSelector(
115-
this.handleLiquidityCheck.selector,
116-
token,
117-
amount,
118-
poolAddress,
119-
poolShardId,
120-
requestId,
121-
borrower
122-
);
123-
124-
Nil.sendRequest(poolAddress, 0, 6_000_000, context, callData);
125-
}
126-
}
127-
}
128-
129-
/// @notice Handle the response from liquidity check
130-
/// @dev If liquidity is found on another shard, initiate the cross-shard transfer
131-
function handleLiquidityCheck(
132-
bool success,
133-
bytes memory returnData,
134-
bytes memory context
135-
) public payable {
136-
if (!success) revert CrossShardCallFailed("Liquidity check failed");
137-
138-
(
139-
TokenId token,
140-
uint256 amount,
141-
address sourcePool,
142-
,
143-
bytes32 requestId,
144-
address borrower
145-
) = abi.decode(
146-
context,
147-
(TokenId, uint256, address, uint256, bytes32, address)
148-
);
149-
150-
uint256 availableLiquidity = abi.decode(returnData, (uint256));
151-
152-
// Only process if this request hasn't been fulfilled yet
153-
if (!activeBorrowRequests[requestId] && availableLiquidity >= amount) {
154-
// Mark this request as active to prevent other shards from processing it
155-
activeBorrowRequests[requestId] = true;
156-
157-
// Continue with the normal borrow process first
158-
TokenId collateralToken = (token == usdt) ? eth : usdt;
159-
160-
bytes memory callData = abi.encodeWithSignature(
161-
"getPrice(address)",
162-
token
163-
);
164-
165-
// Pass the source pool information in the context for later use
166-
bytes memory priceContext = abi.encodeWithSelector(
167-
this.processLoan.selector,
168-
borrower,
169-
amount,
170-
token,
171-
collateralToken,
172-
requestId,
173-
sourcePool
174-
);
175-
176-
Nil.sendRequest(oracle, 0, 9_000_000, priceContext, callData);
177-
}
178-
}
179-
18090
/// @notice Transfer liquidity to another shard
18191
/// @dev Called by other shards to request liquidity,
18292
/// @dev loan are to be sent directly to the borrower therefore we need to record the loan first
@@ -244,52 +154,48 @@ contract LendingPool is NilBase, NilTokenBase {
244154
/// @dev Prevents invalid token types from being borrowed.
245155
if (borrowToken != usdt && borrowToken != eth) revert InvalidToken();
246156

247-
/// @notice Check local liquidity first
248-
/// @dev If local pool has sufficient liquidity, process the borrow locally
157+
/// @notice Determine which collateral token will be used (opposite of the borrow token)
158+
/// @dev Identifies the collateral token by comparing the borrow token.
159+
TokenId collateralToken = (borrowToken == usdt) ? eth : usdt;
249160

250-
// Create a unique request ID at the start of the borrow process
251-
bytes32 requestId = keccak256(
252-
abi.encodePacked(block.timestamp, msg.sender, borrowToken, amount)
161+
/// @notice Prepare a call to the Oracle to get the price of the borrow token
162+
/// @dev The price of the borrow token is fetched from the Oracle to calculate collateral.
163+
/// @param callData The encoded data to fetch the price from the Oracle.
164+
bytes memory callData = abi.encodeWithSignature(
165+
"getPrice(address)",
166+
borrowToken
253167
);
254168

255-
// Check local liquidity first
256-
if (Nil.tokenBalance(address(this), borrowToken) >= amount) {
257-
/// @notice Determine which collateral token will be used (opposite of the borrow token)
258-
/// @dev Identifies the collateral token by comparing the borrow token.
259-
TokenId collateralToken = (borrowToken == usdt) ? eth : usdt;
260-
261-
/// @notice Prepare a call to the Oracle to get the price of the borrow token
262-
/// @dev The price of the borrow token is fetched from the Oracle to calculate collateral.
263-
/// @param callData The encoded data to fetch the price from the Oracle.
264-
bytes memory callData = abi.encodeWithSignature(
265-
"getPrice(address)",
169+
/// @notice Check if there are any lending pools registered
170+
/// @dev If there are no registered lending pools, revert with an error message
171+
if (lendingPoolCount == 0) revert NoLendingPoolsRegistered();
172+
173+
/// @notice Iterate through all registered lending pools
174+
/// @dev Check if any lending pool has sufficient balance of the borrow token
175+
/// @notice we expect that the first lending pool has this contract in the array thereby checking local liquidity first
176+
for (uint256 i = 0; i < lendingPools.length; i++) {
177+
uint256 shardBalnce = Nil.tokenBalance(
178+
lendingPools[i],
266179
borrowToken
267180
);
268181

269-
/// @notice Encoding the context to process the loan after the price is fetched
270-
/// @dev The context contains the borrower's details, loan amount, borrow token, and collateral token.
271-
bytes memory context = abi.encodeWithSelector(
272-
this.processLoan.selector,
273-
msg.sender,
274-
amount,
275-
borrowToken,
276-
collateralToken,
277-
requestId,
278-
address(this)
279-
);
182+
if (shardBalnce >= amount) {
183+
bytes memory context = abi.encodeWithSelector(
184+
this.processLoan.selector,
185+
msg.sender,
186+
amount,
187+
borrowToken,
188+
collateralToken,
189+
lendingPools[i]
190+
);
280191

281-
/// @notice Send a request to the Oracle to get the price of the borrow token.
282-
/// @dev This request is processed with a fee for the transaction, allowing the system to fetch the token price.
283-
Nil.sendRequest(oracle, 0, 9_000_000, context, callData);
284-
} else {
285-
/// @notice If local liquidity is insufficient, check cross-shard liquidity
286-
/// @dev Queries other lending pools across shards for available liquidity
287-
checkCrossShardLiquidity(
288-
borrowToken,
289-
amount,
290-
requestId,
291-
msg.sender
292-
);
192+
/// @notice Send a request to the Oracle to get the price of the borrow token.
193+
/// @dev This request is processed with a fee for the transaction, allowing the system to fetch the token price.
194+
Nil.sendRequest(oracle, 0, 9_000_000, context, callData);
195+
196+
/// @notice Break out of the loop after finding a sufficient balance
197+
break;
198+
}
293199
}
294200
}
295201

@@ -314,12 +220,8 @@ contract LendingPool is NilBase, NilTokenBase {
314220
uint256 amount,
315221
TokenId borrowToken,
316222
TokenId collateralToken,
317-
bytes32 requestId,
318223
address sourcePool
319-
) = abi.decode(
320-
context,
321-
(address, uint256, TokenId, TokenId, bytes32, address)
322-
);
224+
) = abi.decode(context, (address, uint256, TokenId, TokenId, address));
323225

324226
/// @notice Decode the price data returned from the Oracle
325227
/// @dev The returned price data is used to calculate the loan value in USD.
@@ -347,7 +249,6 @@ contract LendingPool is NilBase, NilTokenBase {
347249
amount,
348250
borrowToken,
349251
requiredCollateral,
350-
requestId,
351252
sourcePool
352253
);
353254

@@ -383,12 +284,8 @@ contract LendingPool is NilBase, NilTokenBase {
383284
uint256 amount,
384285
TokenId borrowToken,
385286
uint256 requiredCollateral,
386-
,
387287
address sourcePool
388-
) = abi.decode(
389-
context,
390-
(address, uint256, TokenId, uint256, bytes32, address)
391-
);
288+
) = abi.decode(context, (address, uint256, TokenId, uint256, address));
392289

393290
/// @notice Decode the user's collateral balance from GlobalLedger
394291
/// @dev Retrieves the user's collateral balance from the GlobalLedger to compare it with the required collateral.

0 commit comments

Comments
 (0)