diff --git a/contracts/sprungsui/Move.toml b/contracts/sprungsui/Move.toml new file mode 100644 index 0000000..dbcc71b --- /dev/null +++ b/contracts/sprungsui/Move.toml @@ -0,0 +1,14 @@ +[package] +name = "sprungsui" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move + +[dependencies] +Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" } + +[addresses] +sprungsui = "0x0" + +[dev-dependencies] + +[dev-addresses] + diff --git a/contracts/sprungsui/sources/sprungsui.move b/contracts/sprungsui/sources/sprungsui.move new file mode 100644 index 0000000..4eb30db --- /dev/null +++ b/contracts/sprungsui/sources/sprungsui.move @@ -0,0 +1,20 @@ +module sprungsui::sprungsui { + use sui::coin::{Self}; + + public struct SPRUNGSUI has drop {} + + fun init(witness: SPRUNGSUI, ctx: &mut TxContext) { + let (treasury, metadata) = coin::create_currency( + witness, + 9, + b"", + b"Staked SUI", + b"", + option::none(), + ctx + ); + + transfer::public_share_object(metadata); + transfer::public_transfer(treasury, ctx.sender()) + } +} diff --git a/contracts/suilend/Move.toml b/contracts/suilend/Move.toml index 13a1d3a..7557900 100644 --- a/contracts/suilend/Move.toml +++ b/contracts/suilend/Move.toml @@ -20,6 +20,9 @@ git = "https://github.com/solendprotocol/liquid-staking.git" subdir = "contracts" rev = "main" +[dependencies.sprungsui] +local = "../sprungsui" + [addresses] sui = "0x2" # suilend = "0x0" diff --git a/contracts/suilend/sources/lending_market.move b/contracts/suilend/sources/lending_market.move index f158afd..18a3462 100644 --- a/contracts/suilend/sources/lending_market.move +++ b/contracts/suilend/sources/lending_market.move @@ -23,7 +23,6 @@ module suilend::lending_market { use suilend::liquidity_mining::{Self}; use sui::package; use sui::sui::SUI; - use suilend::staker::{STAKER}; // === Errors === const EIncorrectVersion: u64 = 1; @@ -726,11 +725,11 @@ module suilend::lending_market { } /* Staker operations */ - public fun init_staker

( + public fun init_staker( lending_market: &mut LendingMarket

, _: &LendingMarketOwnerCap

, sui_reserve_array_index: u64, - treasury_cap: TreasuryCap, + treasury_cap: TreasuryCap, ctx: &mut TxContext ) { assert!(lending_market.version == CURRENT_VERSION, EIncorrectVersion); @@ -738,7 +737,7 @@ module suilend::lending_market { let reserve = vector::borrow_mut(&mut lending_market.reserves, sui_reserve_array_index); assert!(reserve::coin_type(reserve) == type_name::get(), EWrongType); - reserve::init_staker

(reserve, treasury_cap, ctx); + reserve::init_staker(reserve, treasury_cap, ctx); } public fun rebalance_staker

( diff --git a/contracts/suilend/sources/reserve.move b/contracts/suilend/sources/reserve.move index 969a699..591c550 100644 --- a/contracts/suilend/sources/reserve.move +++ b/contracts/suilend/sources/reserve.move @@ -32,8 +32,9 @@ module suilend::reserve { liquidation_bonus }; use suilend::liquidity_mining::{Self, PoolRewardManager}; - use suilend::staker::{Self, Staker, STAKER}; + use suilend::staker::{Self, Staker}; use sui_system::sui_system::{SuiSystemState}; + use sprungsui::sprungsui::SPRUNGSUI; // === Errors === const EPriceStale: u64 = 0; @@ -497,7 +498,7 @@ module suilend::reserve { request.fee } - public fun staker

(reserve: &Reserve

): &Staker { + public fun staker(reserve: &Reserve

): &Staker { dynamic_field::borrow(&reserve.id, StakerKey {}) } @@ -731,12 +732,13 @@ module suilend::reserve { liquidity } - public(package) fun init_staker

( + public(package) fun init_staker( reserve: &mut Reserve

, - treasury_cap: TreasuryCap, + treasury_cap: TreasuryCap, ctx: &mut TxContext ) { assert!(!dynamic_field::exists_(&reserve.id, StakerKey {}), EStakerAlreadyInitialized); + assert!(type_name::get() == type_name::get(), EWrongType); let staker = staker::create_staker(treasury_cap, ctx); dynamic_field::add(&mut reserve.id, StakerKey {}, staker); @@ -754,7 +756,7 @@ module suilend::reserve { ); let sui = balance::withdraw_all(&mut balances.available_amount); - let staker: &mut Staker = dynamic_field::borrow_mut(&mut reserve.id, StakerKey {}); + let staker: &mut Staker = dynamic_field::borrow_mut(&mut reserve.id, StakerKey {}); staker::deposit(staker, sui); staker::rebalance(staker, system_state, ctx); @@ -797,7 +799,7 @@ module suilend::reserve { }; let withdraw_amount = liquidity_request.amount - balance::value(&balances.available_amount); - let staker: &mut Staker = dynamic_field::borrow_mut(&mut reserve.id, StakerKey {}); + let staker: &mut Staker = dynamic_field::borrow_mut(&mut reserve.id, StakerKey {}); let sui = staker::withdraw( staker, withdraw_amount, diff --git a/contracts/suilend/sources/staker.move b/contracts/suilend/sources/staker.move index 13892b7..f13dc4a 100644 --- a/contracts/suilend/sources/staker.move +++ b/contracts/suilend/sources/staker.move @@ -22,58 +22,41 @@ module suilend::staker { const MIN_DEPLOY_AMOUNT: u64 = 1_000_000; // 1 SUI const MIST_PER_SUI: u64 = 1_000_000_000; - public struct STAKER has drop {} - - fun init(otw: STAKER, ctx: &mut TxContext) { - let (treasury, metadata) = coin::create_currency( - otw, - 9, - b"SprungSui", - b"", - b"", - option::none(), - ctx - ); - - transfer::public_freeze_object(metadata); - transfer::public_transfer(treasury, ctx.sender()) - } - - public struct Staker has store { - admin: AdminCap, - liquid_staking_info: LiquidStakingInfo, - lst_balance: Balance, + public struct Staker has store { + admin: AdminCap

, + liquid_staking_info: LiquidStakingInfo

, + lst_balance: Balance

, sui_balance: Balance, liabilities: u64, // how much sui is owed to the reserve } /* Public-View Functions */ - public(package) fun liabilities(staker: &Staker): u64 { + public(package) fun liabilities

(staker: &Staker

): u64 { staker.liabilities } - public(package) fun lst_balance(staker: &Staker): &Balance { + public(package) fun lst_balance

(staker: &Staker

): &Balance

{ &staker.lst_balance } - public(package) fun sui_balance(staker: &Staker): &Balance { + public(package) fun sui_balance

(staker: &Staker

): &Balance { &staker.sui_balance } // this value can be stale if the staker hasn't refreshed the liquid_staking_info - public(package) fun total_sui_supply(staker: &Staker): u64 { + public(package) fun total_sui_supply

(staker: &Staker

): u64 { staker.liquid_staking_info.total_sui_supply() + staker.sui_balance.value() } - public(package) fun liquid_staking_info(staker: &Staker): &LiquidStakingInfo { + public(package) fun liquid_staking_info

(staker: &Staker

): &LiquidStakingInfo

{ &staker.liquid_staking_info } /* Public Mutative Functions */ - public(package) fun create_staker( - treasury_cap: TreasuryCap, + public(package) fun create_staker( + treasury_cap: TreasuryCap

, ctx: &mut TxContext - ): Staker { + ): Staker

{ assert!(coin::total_supply(&treasury_cap) == 0, ETreasuryCapNonZeroSupply); let (admin_cap, liquid_staking_info) = liquid_staking::create_lst( @@ -91,16 +74,16 @@ module suilend::staker { } } - public(package) fun deposit( - staker: &mut Staker, + public(package) fun deposit

( + staker: &mut Staker

, sui: Balance, ) { staker.liabilities = staker.liabilities + sui.value(); staker.sui_balance.join(sui); } - public(package) fun withdraw( - staker: &mut Staker, + public(package) fun withdraw( + staker: &mut Staker

, withdraw_amount: u64, system_state: &mut SuiSystemState, ctx: &mut TxContext @@ -118,8 +101,8 @@ module suilend::staker { sui } - public(package) fun rebalance( - staker: &mut Staker, + public(package) fun rebalance( + staker: &mut Staker

, system_state: &mut SuiSystemState, ctx: &mut TxContext ) { @@ -146,8 +129,8 @@ module suilend::staker { ); } - public(package) fun claim_fees( - staker: &mut Staker, + public(package) fun claim_fees( + staker: &mut Staker

, system_state: &mut SuiSystemState, ctx: &mut TxContext ): Balance { @@ -178,8 +161,8 @@ module suilend::staker { // liquid_staking_info must be refreshed before calling this // this function can unstake slightly more sui than requested due to rounding. - fun unstake_n_sui( - staker: &mut Staker, + fun unstake_n_sui( + staker: &mut Staker

, system_state: &mut SuiSystemState, sui_amount_out: u64, ctx: &mut TxContext diff --git a/contracts/suilend/tests/lending_market_tests.move b/contracts/suilend/tests/lending_market_tests.move index a80a239..872f19f 100644 --- a/contracts/suilend/tests/lending_market_tests.move +++ b/contracts/suilend/tests/lending_market_tests.move @@ -25,7 +25,7 @@ module suilend::lending_market_tests { use suilend::lending_market::{Self, create_lending_market, LendingMarketOwnerCap, LendingMarket}; use suilend::mock_pyth::{PriceState}; use sui::sui::SUI; - use suilend::staker::{STAKER}; + use sprungsui::sprungsui::SPRUNGSUI; public struct LENDING_MARKET has drop {} @@ -1705,8 +1705,8 @@ module suilend::lending_market_tests { }, &mut scenario); clock::set_for_testing(&mut clock, 1 * 1000); - let treasury_cap = coin::create_treasury_cap_for_testing(scenario.ctx()); - lending_market::init_staker( + let treasury_cap = coin::create_treasury_cap_for_testing(scenario.ctx()); + lending_market::init_staker( &mut lending_market, &owner_cap, *bag::borrow(&type_to_index, type_name::get()), @@ -1715,7 +1715,7 @@ module suilend::lending_market_tests { ); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); assert!(staker.total_sui_supply() == 0); assert!(staker.liabilities() == 0); @@ -1728,7 +1728,7 @@ module suilend::lending_market_tests { ); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); assert!(staker.total_sui_supply() == 100 * MIST_PER_SUI); assert!(staker.liabilities() == 100 * MIST_PER_SUI); @@ -1749,12 +1749,12 @@ module suilend::lending_market_tests { ); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); assert!(staker.total_sui_supply() == 200 * MIST_PER_SUI); assert!(staker.liabilities() == 200 * MIST_PER_SUI); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); std::debug::print(staker); let liquidity_request = lending_market::redeem_ctokens_and_withdraw_liquidity_request( @@ -1783,7 +1783,7 @@ module suilend::lending_market_tests { assert!(coin::value(&sui) == 100 * MIST_PER_SUI, 0); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); assert!(staker.total_sui_supply() == 100 * MIST_PER_SUI); assert!(staker.liabilities() == 100 * MIST_PER_SUI); @@ -1856,8 +1856,8 @@ module suilend::lending_market_tests { }, &mut scenario); clock::set_for_testing(&mut clock, 1 * 1000); - let treasury_cap = coin::create_treasury_cap_for_testing(scenario.ctx()); - lending_market::init_staker( + let treasury_cap = coin::create_treasury_cap_for_testing(scenario.ctx()); + lending_market::init_staker( &mut lending_market, &owner_cap, *bag::borrow(&type_to_index, type_name::get()), @@ -1866,7 +1866,7 @@ module suilend::lending_market_tests { ); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); assert!(staker.total_sui_supply() == 0); assert!(staker.liabilities() == 0); @@ -1971,8 +1971,8 @@ module suilend::lending_market_tests { }, &mut scenario); clock::set_for_testing(&mut clock, 1 * 1000); - let treasury_cap = coin::create_treasury_cap_for_testing(scenario.ctx()); - lending_market::init_staker( + let treasury_cap = coin::create_treasury_cap_for_testing(scenario.ctx()); + lending_market::init_staker( &mut lending_market, &owner_cap, *bag::borrow(&type_to_index, type_name::get()), @@ -1981,7 +1981,7 @@ module suilend::lending_market_tests { ); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); assert!(staker.total_sui_supply() == 0); assert!(staker.liabilities() == 0); @@ -1995,7 +1995,7 @@ module suilend::lending_market_tests { test_scenario::return_shared(system_state); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); assert!(staker.total_sui_supply() == 100 * MIST_PER_SUI); assert!(staker.sui_balance().value() == 0); assert!(staker.liabilities() == 100 * MIST_PER_SUI); @@ -2013,7 +2013,7 @@ module suilend::lending_market_tests { test_scenario::return_shared(system_state); let sui_reserve = lending_market::reserve(&lending_market); - let staker = reserve::staker(sui_reserve); + let staker = reserve::staker(sui_reserve); std::debug::print(&staker.total_sui_supply()); // the extra 50 sui gained has been transferred to the fees balance already assert!(staker.total_sui_supply() == 101 * MIST_PER_SUI); @@ -2039,4 +2039,4 @@ module suilend::lending_market_tests { test_utils::destroy(type_to_index); test_scenario::end(scenario); } -} \ No newline at end of file +} diff --git a/contracts/suilend/tests/staker_tests.move b/contracts/suilend/tests/staker_tests.move index cf8ce77..c6a3c23 100644 --- a/contracts/suilend/tests/staker_tests.move +++ b/contracts/suilend/tests/staker_tests.move @@ -10,7 +10,7 @@ module suilend::staker_tests { }; use sui::balance::{Self}; use sui::coin::{Self}; - use suilend::staker::{create_staker, STAKER}; + use suilend::staker::{create_staker}; use sui_system::sui_system::{SuiSystemState}; use sui::sui::{SUI}; @@ -18,6 +18,8 @@ module suilend::staker_tests { const MIST_PER_SUI: u64 = 1_000_000_000; const SUILEND_VALIDATOR: address = @0xce8e537664ba5d1d5a6a857b17bd142097138706281882be6805e17065ecde89; + public struct STAKER has drop {} + fun setup_sui_system(scenario: &mut Scenario) { test_scenario::next_tx(scenario, SUILEND_VALIDATOR); let validator = create_validator_for_testing(SUILEND_VALIDATOR, 100, test_scenario::ctx(scenario)); @@ -120,4 +122,4 @@ module suilend::staker_tests { test_scenario::end(scenario); } -} \ No newline at end of file +}