@@ -17,6 +17,7 @@ mod invariants;
1717mod lock;
1818
1919pub mod rewards;
20+ pub mod staking;
2021mod storage_types;
2122pub mod strategy;
2223pub mod token;
@@ -200,14 +201,6 @@ impl NesteraContract {
200201 true
201202 }
202203
203- pub fn mint ( env : Env , payload : MintPayload , signature : BytesN < 64 > ) -> i128 {
204- Self :: verify_signature ( env. clone ( ) , payload. clone ( ) , signature) ;
205- let amount = payload. amount ;
206- env. events ( )
207- . publish ( ( symbol_short ! ( "mint" ) , payload. user ) , amount) ;
208- amount
209- }
210-
211204 pub fn is_initialized ( env : Env ) -> bool {
212205 env. storage ( ) . instance ( ) . has ( & DataKey :: Initialized )
213206 }
@@ -776,6 +769,151 @@ impl NesteraContract {
776769 token:: get_token_metadata ( & env)
777770 }
778771
772+ // ========== Token Minting & Burning Functions (#376, #377) ==========
773+
774+ /// Mints new tokens to the specified address.
775+ /// Only callable by governance or rewards module.
776+ /// Updates total supply and emits TokenMinted event.
777+ ///
778+ /// # Arguments
779+ /// * `caller` - Address calling the function (must be governance or rewards)
780+ /// * `to` - Address to receive the minted tokens
781+ /// * `amount` - Amount of tokens to mint (must be positive)
782+ ///
783+ /// # Returns
784+ /// * `Ok(i128)` - New total supply after minting
785+ /// * `Err(SavingsError)` if unauthorized, invalid amount, or overflow
786+ pub fn mint_tokens (
787+ env : Env ,
788+ caller : Address ,
789+ to : Address ,
790+ amount : i128 ,
791+ ) -> Result < i128 , SavingsError > {
792+ caller. require_auth ( ) ;
793+
794+ // Check if caller is governance or admin
795+ let is_governance = crate :: governance:: validate_admin_or_governance ( & env, & caller) . is_ok ( ) ;
796+ let admin: Address = env
797+ . storage ( )
798+ . instance ( )
799+ . get ( & DataKey :: Admin )
800+ . ok_or ( SavingsError :: Unauthorized ) ?;
801+ let is_admin = admin == caller;
802+
803+ if !is_governance && !is_admin {
804+ return Err ( SavingsError :: Unauthorized ) ;
805+ }
806+
807+ token:: mint ( & env, to, amount)
808+ }
809+
810+ /// Burns tokens from the specified address.
811+ /// Reduces total supply and emits TokenBurned event.
812+ ///
813+ /// # Arguments
814+ /// * `env` - Contract environment
815+ /// * `from` - Address to burn tokens from
816+ /// * `amount` - Amount of tokens to burn (must be positive)
817+ ///
818+ /// # Returns
819+ /// * `Ok(i128)` - New total supply after burning
820+ /// * `Err(SavingsError)` if invalid amount or underflow
821+ pub fn burn ( env : Env , from : Address , amount : i128 ) -> Result < i128 , SavingsError > {
822+ from. require_auth ( ) ;
823+ token:: burn ( & env, from, amount)
824+ }
825+
826+ // ========== Staking Functions (#442) ==========
827+
828+ /// Initializes staking configuration (admin only)
829+ pub fn init_staking_config (
830+ env : Env ,
831+ admin : Address ,
832+ config : staking:: storage_types:: StakingConfig ,
833+ ) -> Result < ( ) , SavingsError > {
834+ let stored_admin: Address = env
835+ . storage ( )
836+ . instance ( )
837+ . get ( & DataKey :: Admin )
838+ . ok_or ( SavingsError :: Unauthorized ) ?;
839+ stored_admin. require_auth ( ) ;
840+ if admin != stored_admin {
841+ return Err ( SavingsError :: Unauthorized ) ;
842+ }
843+ staking:: storage:: initialize_staking_config ( & env, config)
844+ }
845+
846+ /// Updates staking configuration (admin only)
847+ pub fn update_staking_config (
848+ env : Env ,
849+ admin : Address ,
850+ config : staking:: storage_types:: StakingConfig ,
851+ ) -> Result < ( ) , SavingsError > {
852+ let stored_admin: Address = env
853+ . storage ( )
854+ . instance ( )
855+ . get ( & DataKey :: Admin )
856+ . ok_or ( SavingsError :: Unauthorized ) ?;
857+ stored_admin. require_auth ( ) ;
858+ if admin != stored_admin {
859+ return Err ( SavingsError :: Unauthorized ) ;
860+ }
861+ staking:: storage:: update_staking_config ( & env, config)
862+ }
863+
864+ /// Gets the staking configuration
865+ pub fn get_staking_config (
866+ env : Env ,
867+ ) -> Result < staking:: storage_types:: StakingConfig , SavingsError > {
868+ staking:: storage:: get_staking_config ( & env)
869+ }
870+
871+ /// Stakes tokens for a user
872+ pub fn stake ( env : Env , user : Address , amount : i128 ) -> Result < i128 , SavingsError > {
873+ user. require_auth ( ) ;
874+ ensure_not_paused ( & env) ?;
875+ crate :: security:: acquire_reentrancy_guard ( & env) ?;
876+ let res = staking:: storage:: stake ( & env, user, amount) ;
877+ crate :: security:: release_reentrancy_guard ( & env) ;
878+ res
879+ }
880+
881+ /// Unstakes tokens for a user
882+ pub fn unstake ( env : Env , user : Address , amount : i128 ) -> Result < ( i128 , i128 ) , SavingsError > {
883+ user. require_auth ( ) ;
884+ ensure_not_paused ( & env) ?;
885+ crate :: security:: acquire_reentrancy_guard ( & env) ?;
886+ let res = staking:: storage:: unstake ( & env, user, amount) ;
887+ crate :: security:: release_reentrancy_guard ( & env) ;
888+ res
889+ }
890+
891+ /// Claims staking rewards for a user
892+ pub fn claim_staking_rewards ( env : Env , user : Address ) -> Result < i128 , SavingsError > {
893+ user. require_auth ( ) ;
894+ ensure_not_paused ( & env) ?;
895+ crate :: security:: acquire_reentrancy_guard ( & env) ?;
896+ let res = staking:: storage:: claim_staking_rewards ( & env, user) ;
897+ crate :: security:: release_reentrancy_guard ( & env) ;
898+ res
899+ }
900+
901+ /// Gets a user's stake information
902+ pub fn get_user_stake ( env : Env , user : Address ) -> staking:: storage_types:: Stake {
903+ staking:: storage:: get_user_stake ( & env, & user)
904+ }
905+
906+ /// Gets pending staking rewards for a user
907+ pub fn get_pending_staking_rewards ( env : Env , user : Address ) -> Result < i128 , SavingsError > {
908+ staking:: storage:: update_rewards ( & env) ?;
909+ staking:: storage:: calculate_pending_rewards ( & env, & user)
910+ }
911+
912+ /// Gets staking statistics (total_staked, total_rewards, reward_per_token)
913+ pub fn get_staking_stats ( env : Env ) -> Result < ( i128 , i128 , i128 ) , SavingsError > {
914+ staking:: storage:: get_staking_stats ( & env)
915+ }
916+
779917 // ========== Rewards Functions ==========
780918
781919 pub fn init_rewards_config (
@@ -1365,8 +1503,12 @@ mod governance_tests;
13651503#[ cfg( test) ]
13661504mod rates_test;
13671505#[ cfg( test) ]
1506+ mod staking_tests;
1507+ #[ cfg( test) ]
13681508mod test;
13691509#[ cfg( test) ]
1510+ mod token_tests;
1511+ #[ cfg( test) ]
13701512mod transition_tests;
13711513#[ cfg( test) ]
13721514mod ttl_tests;
0 commit comments