Skip to content

Commit 2d8feb7

Browse files
authored
Merge pull request #161 from heymide/Implement-distribute_yield-function
Implement distribute_yield function
2 parents 789676b + b7d910a commit 2d8feb7

1 file changed

Lines changed: 81 additions & 1 deletion

File tree

contracts/vault/src/lib.rs

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![no_std]
22

3+
#[cfg(test)]
34
mod test;
45
#[cfg(test)]
56
mod fuzz_math;
@@ -104,8 +105,15 @@ impl YieldVault {
104105
return Err(VaultError::AlreadyInitialized);
105106
}
106107

108+
let state = VaultState {
109+
total_shares: 0,
110+
total_assets: 0,
111+
is_paused: false,
112+
};
113+
107114
env.storage().instance().set(&DataKey::Admin, &admin);
108115
env.storage().instance().set(&DataKey::TokenAsset, &token);
116+
env.storage().instance().set(&DataKey::State, &state);
109117
env.storage().instance().set(&DataKey::TotalAssets, &0i128);
110118
env.storage().instance().set(&DataKey::TotalShares, &0i128);
111119

@@ -165,8 +173,9 @@ impl YieldVault {
165173
Self::get_state(&env).total_shares
166174
}
167175

168-
/// Read the total underlying assets (idle in vault + invested in strategy).
176+
/// Read the total underlying assets represented by the vault.
169177
pub fn total_assets(env: Env) -> i128 {
178+
Self::get_state(&env).total_assets
170179
let idle_assets = env.storage().instance().get::<_, i128>(&DataKey::TotalAssets).unwrap_or(0);
171180

172181
let strategy_assets = if let Some(strategy_addr) = Self::strategy(env.clone()) {
@@ -723,6 +732,77 @@ impl YieldVault {
723732
pub fn accrue_yield(env: Env, amount: i128) -> Result<(), VaultError> {
724733
let admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap();
725734
admin.require_auth();
735+
736+
let strategy_addr = Self::strategy(env.clone()).expect("no strategy set");
737+
let strategy_client = StrategyClient::new(&env, &strategy_addr);
738+
739+
let mut idle_ta = env.storage().instance().get::<_, i128>(&DataKey::TotalAssets).unwrap_or(0);
740+
if idle_ta < amount { panic!("insufficient idle assets"); }
741+
742+
// Approve and deposit to strategy
743+
let token_addr = Self::token(env.clone());
744+
let token_client = token::Client::new(&env, &token_addr);
745+
token_client.approve(&env.current_contract_address(), &strategy_addr, &amount, &env.ledger().sequence());
746+
747+
strategy_client.deposit(&amount);
748+
749+
// Update idle assets
750+
env.storage().instance().set(&DataKey::TotalAssets, &(idle_ta - amount));
751+
}
752+
753+
/// Recall funds from the strategy.
754+
pub fn divest(env: Env, amount: i128) {
755+
// Can be called by admin or internally by withdraw
756+
let strategy_addr = Self::strategy(env.clone()).expect("no strategy set");
757+
let strategy_client = StrategyClient::new(&env, &strategy_addr);
758+
759+
strategy_client.withdraw(&amount);
760+
761+
// The strategy contract should have transferred funds back to the vault
762+
let idle_ta = env.storage().instance().get::<_, i128>(&DataKey::TotalAssets).unwrap_or(0);
763+
env.storage().instance().set(&DataKey::TotalAssets, &(idle_ta + amount));
764+
}
765+
766+
/// Admin function to distribute realized yield into the vault.
767+
///
768+
/// Yield increases `total_assets` without minting any new shares, which
769+
/// raises the share price for existing holders.
770+
pub fn distribute_yield(env: Env, amount: i128) {
771+
let admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap();
772+
admin.require_auth();
773+
if amount <= 0 {
774+
panic!("yield amount must be > 0");
775+
}
776+
777+
let token_addr = Self::token(env.clone());
778+
let token_client = token::Client::new(&env, &token_addr);
779+
780+
token_client.transfer(&admin, &env.current_contract_address(), &amount);
781+
782+
let ta = env
783+
.storage()
784+
.instance()
785+
.get::<_, i128>(&DataKey::TotalAssets)
786+
.unwrap_or(0);
787+
env.storage().instance().set(&DataKey::TotalAssets, &(ta + amount));
788+
789+
let mut state = Self::get_state(&env);
790+
state.total_assets += amount;
791+
env.storage().instance().set(&DataKey::State, &state);
792+
793+
env.events().publish(
794+
(symbol_short!("yielddist"), admin),
795+
(amount, state.total_assets, state.total_shares),
796+
);
797+
}
798+
799+
/// Legacy admin function retained for compatibility.
800+
pub fn accrue_yield(env: Env, amount: i128) {
801+
Self::distribute_yield(env, amount);
802+
}
803+
804+
pub fn report_benji_yield(env: Env, strategy: Address, amount: i128) {
805+
strategy.require_auth();
726806
if amount <= 0 {
727807
return Err(VaultError::InvalidAmount);
728808
}

0 commit comments

Comments
 (0)