Skip to content

Commit

Permalink
flash loans (solana-labs#95)
Browse files Browse the repository at this point in the history
* 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 (solana-labs#99)

* make clock sysvar optional

* remove clock from instructions

* add stack height check

* fmt
  • Loading branch information
0xripleys authored Aug 31, 2022
1 parent 1feaffc commit aeedc87
Show file tree
Hide file tree
Showing 10 changed files with 2,282 additions and 504 deletions.
2 changes: 1 addition & 1 deletion ci/install-program-deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ set -x
cargo --version
cargo install rustfilt || true
cargo install honggfuzz --version=0.5.52 --force || true
cargo install grcov --force
cargo +"$rust_stable" install grcov --force

cargo +"$rust_stable" build-bpf --version
2 changes: 1 addition & 1 deletion coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ for program in ${programs[@]}; do
(
set -ex
cd $program
cargo +"$rust_nightly" test --features test-bpf --target-dir $here/target/cov
cargo +"$rust_nightly" test --features test-bpf --target-dir $here/target/cov -- --skip fail_repay_from_diff_reserve
)
done

Expand Down
20 changes: 20 additions & 0 deletions token-lending/program/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,26 @@ pub enum LendingError {
/// Insufficent protocol fees to redeem or no liquidity availible to process redeem
#[error("Insufficent protocol fees to claim or no liquidity availible")]
InsufficientProtocolFeesToRedeem,
/// No cpi flash borrows allowed
#[error("No cpi flash borrows allowed")]
FlashBorrowCpi,
/// No corresponding repay found for flash borrow
#[error("No corresponding repay found for flash borrow")]
NoFlashRepayFound,
/// Invalid flash repay found for borrow
#[error("Invalid repay found")]
InvalidFlashRepay,

// 50
/// No cpi flash repays allowed
#[error("No cpi flash repays allowed")]
FlashRepayCpi,
/// Multiple flash borrows not allowed in the same transaction
#[error("Multiple flash borrows not allowed in the same transaction")]
MultipleFlashBorrows,
/// Flash loans are disabled for this reserve
#[error("Flash loans are disabled for this reserve")]
FlashLoansDisabled,
/// Deprecated instruction
#[error("Instruction is deprecated")]
DeprecatedInstruction,
Expand Down
211 changes: 145 additions & 66 deletions token-lending/program/src/instruction.rs

Large diffs are not rendered by default.

686 changes: 480 additions & 206 deletions token-lending/program/src/processor.rs

Large diffs are not rendered by default.

20 changes: 11 additions & 9 deletions token-lending/program/src/state/reserve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,11 +733,16 @@ impl ReserveFees {
&self,
flash_loan_amount: Decimal,
) -> Result<(u64, u64), ProgramError> {
self.calculate_fees(
let (total_fees, host_fee) = self.calculate_fees(
flash_loan_amount,
self.flash_loan_fee_wad,
FeeCalculation::Exclusive,
)
)?;

let origination_fee = total_fees
.checked_sub(host_fee)
.ok_or(LendingError::MathOverflow)?;
Ok((origination_fee, host_fee))
}

fn calculate_fees(
Expand Down Expand Up @@ -1330,25 +1335,22 @@ mod test {
flash_loan_fee_wad,
host_fee_percentage,
};
let (total_fee, host_fee) = fees.calculate_flash_loan_fees(Decimal::from(borrow_amount))?;
let (origination_fee, host_fee) = fees.calculate_flash_loan_fees(Decimal::from(borrow_amount))?;

// The total fee can't be greater than the amount borrowed, as long
// as amount borrowed is greater than 2.
// At a borrow amount of 2, we can get a total fee of 2 if a host
// fee is also specified.
assert!(total_fee <= borrow_amount);

// the host fee can't be greater than the total fee
assert!(host_fee <= total_fee);
assert!(origination_fee + host_fee <= borrow_amount);

// for all fee rates greater than 0, we must have some fee
if borrow_fee_wad > 0 {
assert!(total_fee > 0);
assert!(origination_fee + host_fee > 0);
}

if host_fee_percentage == 100 {
// if the host fee percentage is maxed at 100%, it should get all the fee
assert_eq!(host_fee, total_fee);
assert_eq!(origination_fee, 0);
}

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

0 comments on commit aeedc87

Please sign in to comment.