11use lending_state:: SolendState ;
22use solana_client:: rpc_config:: RpcSendTransactionConfig ;
33use solana_sdk:: { commitment_config:: CommitmentLevel , compute_budget:: ComputeBudgetInstruction } ;
4+ use solend_program:: { instruction:: set_lending_market_owner_and_config, state:: RateLimiterConfig } ;
45use solend_sdk:: {
56 instruction:: {
67 liquidate_obligation_and_redeem_reserve_collateral, redeem_reserve_collateral,
@@ -88,6 +89,12 @@ struct PartialReserveConfig {
8889 pub protocol_liquidation_fee : Option < u8 > ,
8990 /// Protocol take rate is the amount borrowed interest protocol recieves, as a percentage
9091 pub protocol_take_rate : Option < u8 > ,
92+ /// Rate Limiter's max window size
93+ pub rate_limiter_window_duration : Option < u64 > ,
94+ /// Rate Limiter's max outflow per window
95+ pub rate_limiter_max_outflow : Option < u64 > ,
96+ /// Added borrow weight in basis points
97+ pub added_borrow_weight_bps : Option < u64 > ,
9198}
9299
93100/// Reserve Fees with optional fields
@@ -523,6 +530,55 @@ fn main() {
523530 . help ( "Borrow limit" ) ,
524531 )
525532 )
533+ . subcommand (
534+ SubCommand :: with_name ( "set-lending-market-owner-and-config" )
535+ . about ( "Set lending market owner and config" )
536+ . arg (
537+ Arg :: with_name ( "lending_market_owner" )
538+ . long ( "market-owner" )
539+ . validator ( is_keypair)
540+ . value_name ( "KEYPAIR" )
541+ . takes_value ( true )
542+ . required ( true )
543+ . help ( "Owner of the lending market" ) ,
544+ )
545+ . arg (
546+ Arg :: with_name ( "lending_market" )
547+ . long ( "market" )
548+ . validator ( is_pubkey)
549+ . value_name ( "PUBKEY" )
550+ . takes_value ( true )
551+ . required ( true )
552+ . help ( "Lending market address" ) ,
553+ )
554+ . arg (
555+ Arg :: with_name ( "new_lending_market_owner" )
556+ . long ( "new-lending-market-owner" )
557+ . validator ( is_keypair)
558+ . value_name ( "KEYPAIR" )
559+ . takes_value ( true )
560+ . required ( false )
561+ . help ( "Owner of the lending market" ) ,
562+ )
563+ . arg (
564+ Arg :: with_name ( "rate_limiter_window_duration" )
565+ . long ( "rate-limiter-window-duration" )
566+ . validator ( is_parsable :: < u64 > )
567+ . value_name ( "INTEGER" )
568+ . takes_value ( true )
569+ . required ( false )
570+ . help ( "Rate Limiter Window Duration in Slots" ) ,
571+ )
572+ . arg (
573+ Arg :: with_name ( "rate_limiter_max_outflow" )
574+ . long ( "rate-limiter-max-outflow" )
575+ . validator ( is_parsable :: < u64 > )
576+ . value_name ( "INTEGER" )
577+ . takes_value ( true )
578+ . required ( false )
579+ . help ( "Rate Limiter max outflow denominated in dollars within 1 window" ) ,
580+ )
581+ )
526582 . subcommand (
527583 SubCommand :: with_name ( "update-reserve" )
528584 . about ( "Update a reserve config" )
@@ -716,6 +772,33 @@ fn main() {
716772 . required ( false )
717773 . help ( "Switchboard price feed account: https://switchboard.xyz/#/explorer" ) ,
718774 )
775+ . arg (
776+ Arg :: with_name ( "rate_limiter_window_duration" )
777+ . long ( "rate-limiter-window-duration" )
778+ . validator ( is_parsable :: < u64 > )
779+ . value_name ( "INTEGER" )
780+ . takes_value ( true )
781+ . required ( false )
782+ . help ( "Rate Limiter Window Duration in Slots" ) ,
783+ )
784+ . arg (
785+ Arg :: with_name ( "rate_limiter_max_outflow" )
786+ . long ( "rate-limiter-max-outflow" )
787+ . validator ( is_parsable :: < u64 > )
788+ . value_name ( "INTEGER" )
789+ . takes_value ( true )
790+ . required ( false )
791+ . help ( "Rate Limiter max outflow of token amounts within 1 window" ) ,
792+ )
793+ . arg (
794+ Arg :: with_name ( "added_borrow_weight_bps" )
795+ . long ( "added-borrow-weight-bps" )
796+ . validator ( is_parsable :: < u64 > )
797+ . value_name ( "INTEGER" )
798+ . takes_value ( true )
799+ . required ( false )
800+ . help ( "Added borrow weight in basis points" ) ,
801+ )
719802 )
720803 . get_matches ( ) ;
721804
@@ -871,6 +954,7 @@ fn main() {
871954 fee_receiver : liquidity_fee_receiver_keypair. pubkey ( ) ,
872955 protocol_liquidation_fee,
873956 protocol_take_rate,
957+ added_borrow_weight_bps : 10000 ,
874958 } ,
875959 source_liquidity_pubkey,
876960 source_liquidity_owner_keypair,
@@ -883,6 +967,24 @@ fn main() {
883967 source_liquidity,
884968 )
885969 }
970+ ( "set-lending-market-owner-and-config" , Some ( arg_matches) ) => {
971+ let lending_market_owner_keypair =
972+ keypair_of ( arg_matches, "lending_market_owner" ) . unwrap ( ) ;
973+ let lending_market_pubkey = pubkey_of ( arg_matches, "lending_market" ) . unwrap ( ) ;
974+ let new_lending_market_owner_keypair =
975+ keypair_of ( arg_matches, "new_lending_market_owner" ) ;
976+ let rate_limiter_window_duration =
977+ value_of ( arg_matches, "rate_limiter_window_duration" ) ;
978+ let rate_limiter_max_outflow = value_of ( arg_matches, "rate_limiter_max_outflow" ) ;
979+ command_set_lending_market_owner_and_config (
980+ & mut config,
981+ lending_market_pubkey,
982+ lending_market_owner_keypair,
983+ new_lending_market_owner_keypair,
984+ rate_limiter_window_duration,
985+ rate_limiter_max_outflow,
986+ )
987+ }
886988 ( "update-reserve" , Some ( arg_matches) ) => {
887989 let reserve_pubkey = pubkey_of ( arg_matches, "reserve" ) . unwrap ( ) ;
888990 let lending_market_owner_keypair =
@@ -906,6 +1008,10 @@ fn main() {
9061008 let pyth_product_pubkey = pubkey_of ( arg_matches, "pyth_product" ) ;
9071009 let pyth_price_pubkey = pubkey_of ( arg_matches, "pyth_price" ) ;
9081010 let switchboard_feed_pubkey = pubkey_of ( arg_matches, "switchboard_feed" ) ;
1011+ let rate_limiter_window_duration =
1012+ value_of ( arg_matches, "rate_limiter_window_duration" ) ;
1013+ let rate_limiter_max_outflow = value_of ( arg_matches, "rate_limiter_max_outflow" ) ;
1014+ let added_borrow_weight_bps = value_of ( arg_matches, "added_borrow_weight_bps" ) ;
9091015
9101016 let borrow_fee_wad = borrow_fee. map ( |fee| ( fee * WAD as f64 ) as u64 ) ;
9111017 let flash_loan_fee_wad = flash_loan_fee. map ( |fee| ( fee * WAD as f64 ) as u64 ) ;
@@ -930,6 +1036,9 @@ fn main() {
9301036 fee_receiver,
9311037 protocol_liquidation_fee,
9321038 protocol_take_rate,
1039+ rate_limiter_window_duration,
1040+ rate_limiter_max_outflow,
1041+ added_borrow_weight_bps,
9331042 } ,
9341043 pyth_product_pubkey,
9351044 pyth_price_pubkey,
@@ -1437,6 +1546,50 @@ fn command_add_reserve(
14371546 Ok ( ( ) )
14381547}
14391548
1549+ fn command_set_lending_market_owner_and_config (
1550+ config : & mut Config ,
1551+ lending_market_pubkey : Pubkey ,
1552+ lending_market_owner_keypair : Keypair ,
1553+ new_lending_market_owner_keypair : Option < Keypair > ,
1554+ rate_limiter_window_duration : Option < u64 > ,
1555+ rate_limiter_max_outflow : Option < u64 > ,
1556+ ) -> CommandResult {
1557+ let lending_market_info = config. rpc_client . get_account ( & lending_market_pubkey) ?;
1558+ let lending_market = LendingMarket :: unpack_from_slice ( lending_market_info. data . borrow ( ) ) ?;
1559+ println ! ( "{:#?}" , lending_market) ;
1560+
1561+ let recent_blockhash = config. rpc_client . get_latest_blockhash ( ) ?;
1562+ let message = Message :: new_with_blockhash (
1563+ & [ set_lending_market_owner_and_config (
1564+ config. lending_program_id ,
1565+ lending_market_pubkey,
1566+ lending_market_owner_keypair. pubkey ( ) ,
1567+ if let Some ( owner) = new_lending_market_owner_keypair {
1568+ owner. pubkey ( )
1569+ } else {
1570+ lending_market. owner
1571+ } ,
1572+ RateLimiterConfig {
1573+ window_duration : rate_limiter_window_duration
1574+ . unwrap_or ( lending_market. rate_limiter . config . window_duration ) ,
1575+ max_outflow : rate_limiter_max_outflow
1576+ . unwrap_or ( lending_market. rate_limiter . config . max_outflow ) ,
1577+ } ,
1578+ ) ] ,
1579+ Some ( & config. fee_payer . pubkey ( ) ) ,
1580+ & recent_blockhash,
1581+ ) ;
1582+
1583+ let transaction = Transaction :: new (
1584+ & vec ! [ config. fee_payer. as_ref( ) , & lending_market_owner_keypair] ,
1585+ message,
1586+ recent_blockhash,
1587+ ) ;
1588+
1589+ send_transaction ( config, transaction) ?;
1590+ Ok ( ( ) )
1591+ }
1592+
14401593#[ allow( clippy:: too_many_arguments, clippy:: unnecessary_unwrap) ]
14411594fn command_update_reserve (
14421595 config : & mut Config ,
@@ -1450,6 +1603,7 @@ fn command_update_reserve(
14501603) -> CommandResult {
14511604 let reserve_info = config. rpc_client . get_account ( & reserve_pubkey) ?;
14521605 let mut reserve = Reserve :: unpack_from_slice ( reserve_info. data . borrow ( ) ) ?;
1606+ println ! ( "Reserve: {:#?}" , reserve) ;
14531607 let mut no_change = true ;
14541608 if reserve_config. optimal_utilization_rate . is_some ( )
14551609 && reserve. config . optimal_utilization_rate
@@ -1664,6 +1818,46 @@ fn command_update_reserve(
16641818 ) ;
16651819 reserve. liquidity . switchboard_oracle_pubkey = switchboard_feed_pubkey. unwrap ( ) ;
16661820 }
1821+
1822+ if reserve_config. rate_limiter_window_duration . is_some ( )
1823+ && reserve. rate_limiter . config . window_duration
1824+ != reserve_config. rate_limiter_window_duration . unwrap ( )
1825+ {
1826+ no_change = false ;
1827+ println ! (
1828+ "Updating rate_limiter_window_duration from {} to {}" ,
1829+ reserve. rate_limiter. config. window_duration,
1830+ reserve_config. rate_limiter_window_duration. unwrap( ) ,
1831+ ) ;
1832+ reserve. rate_limiter . config . window_duration =
1833+ reserve_config. rate_limiter_window_duration . unwrap ( ) ;
1834+ }
1835+
1836+ if reserve_config. rate_limiter_max_outflow . is_some ( )
1837+ && reserve. rate_limiter . config . max_outflow
1838+ != reserve_config. rate_limiter_max_outflow . unwrap ( )
1839+ {
1840+ no_change = false ;
1841+ println ! (
1842+ "Updating rate_limiter_max_outflow from {} to {}" ,
1843+ reserve. rate_limiter. config. max_outflow,
1844+ reserve_config. rate_limiter_max_outflow. unwrap( ) ,
1845+ ) ;
1846+ reserve. rate_limiter . config . max_outflow = reserve_config. rate_limiter_max_outflow . unwrap ( ) ;
1847+ }
1848+
1849+ if reserve_config. added_borrow_weight_bps . is_some ( )
1850+ && reserve. config . added_borrow_weight_bps != reserve_config. added_borrow_weight_bps . unwrap ( )
1851+ {
1852+ no_change = false ;
1853+ println ! (
1854+ "Updating added_borrow_weight_bps from {} to {}" ,
1855+ reserve. config. added_borrow_weight_bps,
1856+ reserve_config. added_borrow_weight_bps. unwrap( ) ,
1857+ ) ;
1858+ reserve. config . added_borrow_weight_bps = reserve_config. added_borrow_weight_bps . unwrap ( ) ;
1859+ }
1860+
16671861 if no_change {
16681862 println ! ( "No changes made for reserve {}" , reserve_pubkey) ;
16691863 return Ok ( ( ) ) ;
@@ -1675,6 +1869,10 @@ fn command_update_reserve(
16751869 & [ update_reserve_config (
16761870 config. lending_program_id ,
16771871 reserve. config ,
1872+ RateLimiterConfig {
1873+ window_duration : reserve. rate_limiter . config . window_duration ,
1874+ max_outflow : reserve. rate_limiter . config . max_outflow ,
1875+ } ,
16781876 reserve_pubkey,
16791877 lending_market_pubkey,
16801878 lending_market_owner_keypair. pubkey ( ) ,
0 commit comments