diff --git a/contracts/vesting.tmy/include/vesting.tmy/vesting.tmy.hpp b/contracts/vesting.tmy/include/vesting.tmy/vesting.tmy.hpp index 833c7ac..12b1b13 100644 --- a/contracts/vesting.tmy/include/vesting.tmy/vesting.tmy.hpp +++ b/contracts/vesting.tmy/include/vesting.tmy/vesting.tmy.hpp @@ -61,6 +61,9 @@ namespace vestingtoken {26, {days(0 * 30), days(0 * 30), days(5 * 365), 0.0}}, // Platform Dev {27, {days(0 * 30), days(0 * 30), days(5 * 365), 0.0}}, // Staking & Infra Rewards {28, {days(0 * 30), days(0 * 30), days(5 * 365), 0.0}}, // Ecosystem + {29, {days(0 * 30), days(26), days(6 * 30), 0.15}}, // Double Special Round - Full + {30, {days(0 * 30), days(26), days(3 * 30), 0.3}}, // Double Special Round - Part 1 + {31, {days(0 * 30), days(26 + 3 * 30), days(3 * 30), 0.0}}, // Double Special Round - Part 2 // Testing categories: #ifdef BUILD_TEST {997, {days(6 * 30), days(0 * 30), days(2 * 365), 0.0}}, // TESTING ONLY diff --git a/contracts/vesting.tmy/src/vesting.tmy.cpp b/contracts/vesting.tmy/src/vesting.tmy.cpp index a58f878..79ef6c6 100644 --- a/contracts/vesting.tmy/src/vesting.tmy.cpp +++ b/contracts/vesting.tmy/src/vesting.tmy.cpp @@ -99,35 +99,36 @@ namespace vestingtoken // Calculate the vesting end time time_point vesting_end = vesting_start + category.vesting_period; - // Check if vesting period after cliff has started - if (now >= cliff_finished) + // Calculate the claimable amount so far + int64_t total_allocated = vesting_allocation.tokens_allocated.amount; + // Portion unlocked at launch date (TGE unlock) + int64_t claimable = static_cast(total_allocated * category.tge_unlock); + + if (now >= vesting_end) { - // Calculate the total claimable amount - int64_t claimable = 0; - if (now >= vesting_end) - { - claimable = vesting_allocation.tokens_allocated.amount; - } - else - { - // Calculate the percentage of the vesting period that has passed - double vesting_finished = static_cast((now - vesting_start).count()) / category.vesting_period.count(); - // Calculate the claimable amount: - // + tokens allocated * TGE unlock percentage - // + tokens allocated * % of vesting time that has passed * what is left after TGE unlock - claimable = vesting_allocation.tokens_allocated.amount * ((1.0 - category.tge_unlock) * vesting_finished + category.tge_unlock); - // Ensure the claimable amount is not greater than the total allocated amount - claimable = std::min(claimable, vesting_allocation.tokens_allocated.amount); - } + // All tokens have vested by end of schedule + claimable = total_allocated; + } + else if (now >= cliff_finished) + { + // After cliff, linear vesting for the remaining tokens + double vesting_finished = static_cast((now - vesting_start).count()) / category.vesting_period.count(); + int64_t remaining_after_tge = total_allocated - claimable; + claimable = std::min(total_allocated, + claimable + static_cast(remaining_after_tge * vesting_finished)); + } + // Only process if there's anything new to claim + if (claimable > vesting_allocation.tokens_claimed.amount) + { total_claimable += claimable - vesting_allocation.tokens_claimed.amount; // Update the tokens_claimed field eosio::asset tokens_claimed = eosio::asset(claimable, vesting_allocation.tokens_claimed.symbol); - if (claimable == vesting_allocation.tokens_allocated.amount) + if (claimable == total_allocated) { - // Erase and update iterator correctly + // Fully vested and claimed: remove the row iter = vesting_table.erase(iter); } else @@ -141,7 +142,7 @@ namespace vestingtoken } else { - ++iter; + ++iter; } } @@ -175,7 +176,7 @@ namespace vestingtoken // Checks to verify new allocation is valid eosio::check(iter->tokens_allocated.amount == old_amount.amount, "Old amount does not match existing allocation"); eosio::check(iter->vesting_category_type == old_category_id, "Old category does not match existing allocation"); - eosio::check(iter->tokens_claimed.amount < new_amount.amount, "New amount is less than the amount already claimed"); + eosio::check(iter->tokens_claimed.amount <= new_amount.amount, "New amount is less than the amount already claimed"); // Modify the table row data, and update the table vesting_table.modify(iter, get_self(), [&](auto &row)