diff --git a/contracts/mtoken/Move.lock b/contracts/mtoken/Move.lock index a8ec04a..e04d997 100644 --- a/contracts/mtoken/Move.lock +++ b/contracts/mtoken/Move.lock @@ -2,7 +2,7 @@ [move] version = 3 -manifest_digest = "621AB19773C2DEDCF619E96217605A9FF2BC18173F9DF2D50083C0CE7C974030" +manifest_digest = "1253F4654A86D7FC13E19FC669EA78F29BAC19E2F349101A7A9C44F1BB8E18CC" deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600" dependencies = [ { id = "Sui", name = "Sui" }, diff --git a/contracts/mtoken/sources/mtoken.move b/contracts/mtoken/sources/mtoken.move index 0cb9a12..2eee410 100644 --- a/contracts/mtoken/sources/mtoken.move +++ b/contracts/mtoken/sources/mtoken.move @@ -174,22 +174,8 @@ module mtoken::mtoken { // Ensure current time is within the valid range assert!(current_time >= manager.start_time_s, ERedeemingBeforeStartTime); - // Interpolate penalty linearly - let end_penalty = decimal::from(manager.end_penalty_numerator) - .mul(decimal::from(withdraw_amount)) - .div(decimal::from(manager.penalty_denominator)); - - let penalty_amount = if (current_time < manager.end_time_s) { - let start_penalty = decimal::from(manager.start_penalty_numerator) - .mul(decimal::from(withdraw_amount)) - .div(decimal::from(manager.penalty_denominator)); - - let time_weight = decimal::from(manager.end_time_s) - .sub(decimal::from(current_time)) - .div(decimal::from(manager.end_time_s).sub(decimal::from(manager.start_time_s))); - - start_penalty.mul(time_weight).add(end_penalty.mul(decimal::from(1).sub(time_weight))).ceil() - } else { end_penalty.ceil() }; + // Get penalty amount + let penalty_amount = manager.get_penalty_amount(withdraw_amount, clock); assert!(penalty_coin.value() >= penalty_amount, ENotEnoughPenaltyFunds); @@ -234,6 +220,33 @@ module mtoken::mtoken { coin::from_balance(balance, ctx) } + public fun get_penalty_amount( + manager: &VestingManager, + mtoken_burn_amount: u64, + clock: &Clock, + ): u64 { + let current_time = clock::timestamp_ms(clock) / 1000; + + // Interpolate penalty linearly + let end_penalty = decimal::from(manager.end_penalty_numerator) + .mul(decimal::from(mtoken_burn_amount)) + .div(decimal::from(manager.penalty_denominator)); + + let penalty_amount = if (current_time < manager.end_time_s) { + let start_penalty = decimal::from(manager.start_penalty_numerator) + .mul(decimal::from(mtoken_burn_amount)) + .div(decimal::from(manager.penalty_denominator)); + + let time_weight = decimal::from(manager.end_time_s) + .sub(decimal::from(current_time)) + .div(decimal::from(manager.end_time_s).sub(decimal::from(manager.start_time_s))); + + start_penalty.mul(time_weight).add(end_penalty.mul(decimal::from(1).sub(time_weight))).ceil() + } else { end_penalty.ceil() }; + + penalty_amount + } + // ===== View functions ===== public fun manager(admin_cap: &AdminCap): ID { admin_cap.id.to_inner() }