Skip to content

Commit aeedc87

Browse files
authored
flash loans (solendprotocol#95)
* copying kiplet's code * make flash loans more conservative * happy case test * adding more tests, fixed a bug * moar tests * clippy lints * fix assert * remove clock * remove old flash loan instruction, but keep the instruction packing code * saner flash loan fee calculation * add flash borrow ix arg to flash repay * cargo fmt * add cpi repay test * bump compute units, no idea why github actions is failing * test for malicious use case * remove unused variable * fix coverage, check reserve borrow limit in flash borrow * mark reserves as stale in flash borrow and repay * revert back to old nightly version, install grcov with stable * fix for [repay, borrow, repay] * refactor CPI * recheck stuff in flash repay * explicitly check for out of bounds in flash borrow loop * 0xripleys remove clock (solendprotocol#99) * make clock sysvar optional * remove clock from instructions * add stack height check * fmt
1 parent 1feaffc commit aeedc87

File tree

10 files changed

+2282
-504
lines changed

10 files changed

+2282
-504
lines changed

ci/install-program-deps.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ set -x
1010
cargo --version
1111
cargo install rustfilt || true
1212
cargo install honggfuzz --version=0.5.52 --force || true
13-
cargo install grcov --force
13+
cargo +"$rust_stable" install grcov --force
1414

1515
cargo +"$rust_stable" build-bpf --version

coverage.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ for program in ${programs[@]}; do
5454
(
5555
set -ex
5656
cd $program
57-
cargo +"$rust_nightly" test --features test-bpf --target-dir $here/target/cov
57+
cargo +"$rust_nightly" test --features test-bpf --target-dir $here/target/cov -- --skip fail_repay_from_diff_reserve
5858
)
5959
done
6060

token-lending/program/src/error.rs

+20
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,26 @@ pub enum LendingError {
167167
/// Insufficent protocol fees to redeem or no liquidity availible to process redeem
168168
#[error("Insufficent protocol fees to claim or no liquidity availible")]
169169
InsufficientProtocolFeesToRedeem,
170+
/// No cpi flash borrows allowed
171+
#[error("No cpi flash borrows allowed")]
172+
FlashBorrowCpi,
173+
/// No corresponding repay found for flash borrow
174+
#[error("No corresponding repay found for flash borrow")]
175+
NoFlashRepayFound,
176+
/// Invalid flash repay found for borrow
177+
#[error("Invalid repay found")]
178+
InvalidFlashRepay,
179+
180+
// 50
181+
/// No cpi flash repays allowed
182+
#[error("No cpi flash repays allowed")]
183+
FlashRepayCpi,
184+
/// Multiple flash borrows not allowed in the same transaction
185+
#[error("Multiple flash borrows not allowed in the same transaction")]
186+
MultipleFlashBorrows,
187+
/// Flash loans are disabled for this reserve
188+
#[error("Flash loans are disabled for this reserve")]
189+
FlashLoansDisabled,
170190
/// Deprecated instruction
171191
#[error("Instruction is deprecated")]
172192
DeprecatedInstruction,

token-lending/program/src/instruction.rs

+145-66
Large diffs are not rendered by default.

token-lending/program/src/processor.rs

+480-206
Large diffs are not rendered by default.

token-lending/program/src/state/reserve.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -733,11 +733,16 @@ impl ReserveFees {
733733
&self,
734734
flash_loan_amount: Decimal,
735735
) -> Result<(u64, u64), ProgramError> {
736-
self.calculate_fees(
736+
let (total_fees, host_fee) = self.calculate_fees(
737737
flash_loan_amount,
738738
self.flash_loan_fee_wad,
739739
FeeCalculation::Exclusive,
740-
)
740+
)?;
741+
742+
let origination_fee = total_fees
743+
.checked_sub(host_fee)
744+
.ok_or(LendingError::MathOverflow)?;
745+
Ok((origination_fee, host_fee))
741746
}
742747

743748
fn calculate_fees(
@@ -1330,25 +1335,22 @@ mod test {
13301335
flash_loan_fee_wad,
13311336
host_fee_percentage,
13321337
};
1333-
let (total_fee, host_fee) = fees.calculate_flash_loan_fees(Decimal::from(borrow_amount))?;
1338+
let (origination_fee, host_fee) = fees.calculate_flash_loan_fees(Decimal::from(borrow_amount))?;
13341339

13351340
// The total fee can't be greater than the amount borrowed, as long
13361341
// as amount borrowed is greater than 2.
13371342
// At a borrow amount of 2, we can get a total fee of 2 if a host
13381343
// fee is also specified.
1339-
assert!(total_fee <= borrow_amount);
1340-
1341-
// the host fee can't be greater than the total fee
1342-
assert!(host_fee <= total_fee);
1344+
assert!(origination_fee + host_fee <= borrow_amount);
13431345

13441346
// for all fee rates greater than 0, we must have some fee
13451347
if borrow_fee_wad > 0 {
1346-
assert!(total_fee > 0);
1348+
assert!(origination_fee + host_fee > 0);
13471349
}
13481350

13491351
if host_fee_percentage == 100 {
13501352
// if the host fee percentage is maxed at 100%, it should get all the fee
1351-
assert_eq!(host_fee, total_fee);
1353+
assert_eq!(origination_fee, 0);
13521354
}
13531355

13541356
// if there's a host fee and some borrow fee, host fee must be greater than 0

0 commit comments

Comments
 (0)