Update BigStake
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -208,6 +208,16 @@ contract CunaFinanceBase is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
emit FundsWithdrawn(msg.sender, BASE_TOKEN, _amount);
|
emit FundsWithdrawn(msg.sender, BASE_TOKEN, _amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Admin function to adjust withdraw liabilities (for fixing decimal conversion issues)
|
||||||
|
/// @param token The token address to adjust
|
||||||
|
/// @param newAmount The new liability amount (should be in token's native decimals)
|
||||||
|
function adjustWithdrawLiability(address token, uint256 newAmount) external onlyOwner {
|
||||||
|
uint256 oldAmount = withdrawLiabilities[token];
|
||||||
|
withdrawLiabilities[token] = newAmount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function setPriceOracle(address _token, address _oracle) external onlyOwner {
|
function setPriceOracle(address _token, address _oracle) external onlyOwner {
|
||||||
priceOracles[_token] = _oracle;
|
priceOracles[_token] = _oracle;
|
||||||
}
|
}
|
||||||
@@ -357,6 +367,54 @@ contract CunaFinanceBase is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
currentEpochId++;
|
currentEpochId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Re-enter/update the most recent epoch with new values and recalculated unlock percentage
|
||||||
|
/// @param estDaysRemaining Estimated days remaining for the protocol
|
||||||
|
/// @param currentTreasuryTvl Current treasury total value locked
|
||||||
|
/// @param _paybackPercent Percentage multiplier for unlock calculation (scaled by 10000)
|
||||||
|
/// @param _currentLiability Current total liability amount
|
||||||
|
function reenterEpoch(uint256 estDaysRemaining, uint256 currentTreasuryTvl, uint256 _paybackPercent, uint256 _currentLiability) external onlyOwner {
|
||||||
|
require(currentEpochId > 0, "No epochs to update");
|
||||||
|
|
||||||
|
uint256 epochId = currentEpochId - 1; // Most recent epoch
|
||||||
|
|
||||||
|
uint256 unlockPercentage = 0;
|
||||||
|
// Calculate current ratio
|
||||||
|
if (_currentLiability > 0) {
|
||||||
|
uint256 currentRatio = (currentTreasuryTvl * 10000) / _currentLiability;
|
||||||
|
|
||||||
|
if (epochId > 0) {
|
||||||
|
// Calculate unlock percentage BEFORE updating highest ratio
|
||||||
|
unlockPercentage = calculateUnlockPercentage(currentRatio, _paybackPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update highest ratio AFTER calculating unlock percentage
|
||||||
|
if (currentRatio > highestRatio) {
|
||||||
|
highestRatio = currentRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that unlock percentage doesn't exceed maximum
|
||||||
|
require(unlockPercentage <= maxUnlockPercentage, "Unlock percentage high");
|
||||||
|
|
||||||
|
// Update the existing epoch entry
|
||||||
|
epochs[epochId] = Epoch({
|
||||||
|
estDaysRemaining: estDaysRemaining,
|
||||||
|
currentTreasuryTvl: currentTreasuryTvl,
|
||||||
|
totalLiability: _currentLiability,
|
||||||
|
paybackPercent: _paybackPercent,
|
||||||
|
unlockPercentage: unlockPercentage,
|
||||||
|
timestamp: block.timestamp
|
||||||
|
});
|
||||||
|
|
||||||
|
emit EpochEnded(epochId, currentTreasuryTvl, unlockPercentage, _paybackPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Set a manual currentEpochId
|
||||||
|
/// @param epochId The epoch ID to set as the currentEpochId
|
||||||
|
function setEpochId(uint256 epochId) external onlyOwner {
|
||||||
|
currentEpochId = epochId;
|
||||||
|
}
|
||||||
|
|
||||||
/// @notice Calculate total unclaimed funds for a user across all epochs since last claim
|
/// @notice Calculate total unclaimed funds for a user across all epochs since last claim
|
||||||
function calculateUnclaimedFunds(address user) public view returns (uint256 totalUnclaimed) {
|
function calculateUnclaimedFunds(address user) public view returns (uint256 totalUnclaimed) {
|
||||||
uint256 remainingStake = getNetStake(user);
|
uint256 remainingStake = getNetStake(user);
|
||||||
@@ -452,8 +510,8 @@ contract CunaFinanceBase is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
transferAmount = amount / 1e12; // Convert from 18 decimals to 6 decimals
|
transferAmount = amount / 1e12; // Convert from 18 decimals to 6 decimals
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrement withdraw liabilities for all tokens (using original 18-decimal amount)
|
// Decrement withdraw liabilities (using correct decimal precision)
|
||||||
withdrawLiabilities[token] -= amount;
|
withdrawLiabilities[token] -= transferAmount;
|
||||||
|
|
||||||
// Transfer tokens to user based on the specified token (using converted amount)
|
// Transfer tokens to user based on the specified token (using converted amount)
|
||||||
IERC20(token).safeTransfer(msg.sender, transferAmount);
|
IERC20(token).safeTransfer(msg.sender, transferAmount);
|
||||||
@@ -507,35 +565,35 @@ contract CunaFinanceBase is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
|
|
||||||
// Bot Functions for Staking Management
|
// Bot Functions for Staking Management
|
||||||
|
|
||||||
/// @notice Create a withdraw stake for a user (for admin/migration purposes)
|
// /// @notice Create a withdraw stake for a user (for admin/migration purposes)
|
||||||
/// @dev Only to be used by bots for manual withdraw stake creation
|
// /// @dev Only to be used by bots for manual withdraw stake creation
|
||||||
/// @param user The user address to create the withdraw stake for
|
// /// @param user The user address to create the withdraw stake for
|
||||||
/// @param amount The amount for the withdraw stake
|
// /// @param amount The amount for the withdraw stake
|
||||||
/// @param unlockTime The unlock timestamp for the withdraw stake
|
// /// @param unlockTime The unlock timestamp for the withdraw stake
|
||||||
/// @param token The token address for the withdraw stake
|
// /// @param token The token address for the withdraw stake
|
||||||
/// @param isVesting Whether this is a vesting-related stake (adds 1e6 to stakeId)
|
// /// @param isVesting Whether this is a vesting-related stake (adds 1e6 to stakeId)
|
||||||
function createWithdrawStakeForUser(address user, uint256 amount, uint256 unlockTime, address token, bool isVesting) external onlyBot {
|
// function createWithdrawStakeForUser(address user, uint256 amount, uint256 unlockTime, address token, bool isVesting) external onlyBot {
|
||||||
require(user != address(0), "Invalid user address");
|
// require(user != address(0), "Invalid user address");
|
||||||
require(amount > 0, "Invalid amount");
|
// require(amount > 0, "Invalid amount");
|
||||||
require(token != address(0), "Invalid token address");
|
// require(token != address(0), "Invalid token address");
|
||||||
|
|
||||||
// Generate unique stakeId
|
// // Generate unique stakeId
|
||||||
stakeIdCounter++;
|
// stakeIdCounter++;
|
||||||
uint256 finalStakeId = isVesting ? stakeIdCounter + 1e6 : stakeIdCounter;
|
// uint256 finalStakeId = isVesting ? stakeIdCounter + 1e6 : stakeIdCounter;
|
||||||
|
|
||||||
// Create the withdraw stake
|
// // Create the withdraw stake
|
||||||
withdrawStakes[user].push(WithdrawStake({
|
// withdrawStakes[user].push(WithdrawStake({
|
||||||
stakeId: finalStakeId,
|
// stakeId: finalStakeId,
|
||||||
amount: amount,
|
// amount: amount,
|
||||||
unlockTime: unlockTime,
|
// unlockTime: unlockTime,
|
||||||
token: token
|
// token: token
|
||||||
}));
|
// }));
|
||||||
|
|
||||||
// Increment withdraw liabilities for this token
|
// // Increment withdraw liabilities for this token
|
||||||
withdrawLiabilities[token] += amount;
|
// withdrawLiabilities[token] += amount;
|
||||||
|
|
||||||
emit StakeWithdrawn(user, amount, finalStakeId);
|
// emit StakeWithdrawn(user, amount, finalStakeId);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// @notice Batch create stakes for multiple users (efficient for migration)
|
/// @notice Batch create stakes for multiple users (efficient for migration)
|
||||||
/// @dev Only to be used by bots for initial setup
|
/// @dev Only to be used by bots for initial setup
|
||||||
@@ -1201,8 +1259,8 @@ contract CunaFinanceBase is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
|
|
||||||
// Only update liabilities and emit event if something was actually claimed
|
// Only update liabilities and emit event if something was actually claimed
|
||||||
if (totalBonusClaimed > 0) {
|
if (totalBonusClaimed > 0) {
|
||||||
// Increment withdraw liabilities for BASE_TOKEN
|
// Increment withdraw liabilities for BASE_TOKEN (convert from 18 decimals to 6 decimals)
|
||||||
withdrawLiabilities[BASE_TOKEN] += totalBonusClaimed;
|
withdrawLiabilities[BASE_TOKEN] += totalBonusClaimed / 1e12;
|
||||||
emit BonusClaimed(msg.sender, totalBonusClaimed);
|
emit BonusClaimed(msg.sender, totalBonusClaimed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1321,7 +1379,7 @@ contract CunaFinanceBase is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
/// @notice Test function for upgrade verification
|
/// @notice Test function for upgrade verification
|
||||||
/// @return Returns a constant value to verify upgrade worked
|
/// @return Returns a constant value to verify upgrade worked
|
||||||
function testUpgradeFunction() external pure returns (uint256) {
|
function testUpgradeFunction() external pure returns (uint256) {
|
||||||
return 1000; // Updated value to trigger upgrade detection
|
return 1002; // Added adjustWithdrawLiability admin function
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -530,11 +530,39 @@ contract CunaFinanceBsc is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
emit StakeWithdrawn(user, amount, finalStakeId);
|
emit StakeWithdrawn(user, amount, finalStakeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Batch create stakes for multiple users (efficient for migration)
|
// /// @notice Batch create stakes for multiple users
|
||||||
/// @dev Only to be used by bots for initial setup
|
// /// @dev Only to be used by bots for initial setup
|
||||||
|
// /// @param users Array of user addresses
|
||||||
|
// /// @param amounts Array of stake amounts (must match users length)
|
||||||
|
// function batchCreateUserStakes(address[] calldata users, uint256[] calldata amounts) external onlyBot {
|
||||||
|
// require(users.length == amounts.length, "Array length mismatch");
|
||||||
|
// require(users.length > 0, "Empty arrays");
|
||||||
|
|
||||||
|
// for (uint256 i = 0; i < users.length; i++) {
|
||||||
|
// require(users[i] != address(0), "Invalid address");
|
||||||
|
// require(amounts[i] > 0, "Invalid amount");
|
||||||
|
|
||||||
|
// // Update totalBigStakes directly (subtract old, add new)
|
||||||
|
// totalBigStakes = totalBigStakes - userBigStake[users[i]] + amounts[i];
|
||||||
|
|
||||||
|
// // Set original stake
|
||||||
|
// userOriginalStake[users[i]] = amounts[i];
|
||||||
|
|
||||||
|
// // Set last claimed epoch to current epoch
|
||||||
|
// userLastClaimedEpoch[users[i]] = currentEpochId;
|
||||||
|
|
||||||
|
// // Set user's big stake
|
||||||
|
// userBigStake[users[i]] = amounts[i];
|
||||||
|
|
||||||
|
// emit StakeCreated(users[i], amounts[i]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// @notice Batch add to stakes for multiple users
|
||||||
|
/// @dev Only to be used by bots for edits
|
||||||
/// @param users Array of user addresses
|
/// @param users Array of user addresses
|
||||||
/// @param amounts Array of stake amounts (must match users length)
|
/// @param amounts Array of stake amounts to ADD to a users bigStake
|
||||||
function batchCreateUserStakes(address[] calldata users, uint256[] calldata amounts) external onlyBot {
|
function batchUpdateUserStakes(address[] calldata users, uint256[] calldata amounts) external onlyBot {
|
||||||
require(users.length == amounts.length, "Array length mismatch");
|
require(users.length == amounts.length, "Array length mismatch");
|
||||||
require(users.length > 0, "Empty arrays");
|
require(users.length > 0, "Empty arrays");
|
||||||
|
|
||||||
@@ -542,19 +570,18 @@ contract CunaFinanceBsc is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
require(users[i] != address(0), "Invalid address");
|
require(users[i] != address(0), "Invalid address");
|
||||||
require(amounts[i] > 0, "Invalid amount");
|
require(amounts[i] > 0, "Invalid amount");
|
||||||
|
|
||||||
// Update totalBigStakes directly (subtract old, add new)
|
// Update totalBigStakes directly (add new)
|
||||||
totalBigStakes = totalBigStakes - userBigStake[users[i]] + amounts[i];
|
totalBigStakes = totalBigStakes + amounts[i];
|
||||||
|
|
||||||
// Set original stake
|
// Add to original stake
|
||||||
userOriginalStake[users[i]] = amounts[i];
|
userOriginalStake[users[i]] += amounts[i];
|
||||||
|
|
||||||
// Set last claimed epoch to current epoch
|
// Set last claimed epoch to current epoch
|
||||||
userLastClaimedEpoch[users[i]] = currentEpochId;
|
// userLastClaimedEpoch[users[i]] = currentEpochId; DONT Update
|
||||||
|
|
||||||
// Set user's big stake
|
// Increment user's big stake
|
||||||
userBigStake[users[i]] = amounts[i];
|
userBigStake[users[i]] += amounts[i];
|
||||||
|
|
||||||
emit StakeCreated(users[i], amounts[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -795,30 +822,30 @@ contract CunaFinanceBsc is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bot Functions for Emergency Management
|
// Bot Functions for Emergency Management
|
||||||
/// @notice This function will end and clear a user's vestings.
|
// @notice This function will end and clear a user's vestings.
|
||||||
/// @dev Only to be used by bots in emergencies
|
// @dev Only to be used by bots in emergencies
|
||||||
/// @param user The user whose vestings will be ended and 0'd
|
// @param user The user whose vestings will be ended and 0'd
|
||||||
// function clearVesting(address user) external onlyBot {
|
function clearVesting(address user) external onlyBot {
|
||||||
// for (uint256 i = 0; i < vestings[user].length; ++i) {
|
for (uint256 i = 0; i < vestings[user].length; ++i) {
|
||||||
// Vesting storage vesting = vestings[user][i];
|
Vesting storage vesting = vestings[user][i];
|
||||||
|
|
||||||
// // Decrement accounting variables before clearing
|
// Decrement accounting variables before clearing
|
||||||
// if (!vesting.complete) {
|
if (!vesting.complete) {
|
||||||
// if (dollarsVested[user] >= vesting.usdAmount) {
|
if (dollarsVested[user] >= vesting.usdAmount) {
|
||||||
// dollarsVested[user] -= vesting.usdAmount;
|
dollarsVested[user] -= vesting.usdAmount;
|
||||||
// }
|
}
|
||||||
// if (vestedTotal[vesting.token] >= vesting.amount) {
|
if (vestedTotal[vesting.token] >= vesting.amount) {
|
||||||
// vestedTotal[vesting.token] -= vesting.amount;
|
vestedTotal[vesting.token] -= vesting.amount;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// vesting.amount = 0;
|
vesting.amount = 0;
|
||||||
// vesting.bonus = 0;
|
vesting.bonus = 0;
|
||||||
// vesting.claimedAmount = 0;
|
vesting.claimedAmount = 0;
|
||||||
// vesting.claimedBonus = 0;
|
vesting.claimedBonus = 0;
|
||||||
// vesting.complete = true;
|
vesting.complete = true;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
/// @notice Creates a vesting for a given user
|
/// @notice Creates a vesting for a given user
|
||||||
/// @dev Only to be used by bots for manual vesting creation
|
/// @dev Only to be used by bots for manual vesting creation
|
||||||
@@ -846,45 +873,45 @@ contract CunaFinanceBsc is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
vestedTotal[token] += amount - claimedAmount;
|
vestedTotal[token] += amount - claimedAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Update an existing vesting at a specific index
|
// /// @notice Update an existing vesting at a specific index
|
||||||
/// @dev Only updates existing vestings. Fails if the index doesn't exist.
|
// /// @dev Only updates existing vestings. Fails if the index doesn't exist.
|
||||||
/// @param user The user address to update vesting for
|
// /// @param user The user address to update vesting for
|
||||||
/// @param vestingIndex The index of the existing vesting to update
|
// /// @param vestingIndex The index of the existing vesting to update
|
||||||
/// @param amount The vesting amount
|
// /// @param amount The vesting amount
|
||||||
/// @param bonus The bonus amount
|
// /// @param bonus The bonus amount
|
||||||
/// @param lockedUntil The lock timestamp
|
// /// @param lockedUntil The lock timestamp
|
||||||
/// @param token The token address
|
// /// @param token The token address
|
||||||
/// @param usdAmount The USD value
|
// /// @param usdAmount The USD value
|
||||||
/// @param lastClaimed The last claimed timestamp
|
// /// @param lastClaimed The last claimed timestamp
|
||||||
/// @param createdAt The creation timestamp
|
// /// @param createdAt The creation timestamp
|
||||||
/// @param claimedAmount The already claimed amount
|
// /// @param claimedAmount The already claimed amount
|
||||||
/// @param claimedBonus The already claimed bonus
|
// /// @param claimedBonus The already claimed bonus
|
||||||
function updateVesting(address user, uint256 vestingIndex, uint256 amount, uint256 bonus, uint256 lockedUntil, address token, uint256 usdAmount, uint256 lastClaimed, uint256 createdAt, uint256 claimedAmount, uint256 claimedBonus) public onlyBot {
|
// function updateVesting(address user, uint256 vestingIndex, uint256 amount, uint256 bonus, uint256 lockedUntil, address token, uint256 usdAmount, uint256 lastClaimed, uint256 createdAt, uint256 claimedAmount, uint256 claimedBonus) public onlyBot {
|
||||||
require(vestingIndex < vestings[user].length, "Vesting index does not exist");
|
// require(vestingIndex < vestings[user].length, "Vesting index does not exist");
|
||||||
|
|
||||||
// Subtract old values from totals first
|
// // Subtract old values from totals first
|
||||||
Vesting storage oldVesting = vestings[user][vestingIndex];
|
// Vesting storage oldVesting = vestings[user][vestingIndex];
|
||||||
dollarsVested[user] -= oldVesting.usdAmount;
|
// dollarsVested[user] -= oldVesting.usdAmount;
|
||||||
vestedTotal[oldVesting.token] -= (oldVesting.amount - oldVesting.claimedAmount);
|
// vestedTotal[oldVesting.token] -= (oldVesting.amount - oldVesting.claimedAmount);
|
||||||
|
|
||||||
// Update the vesting at the specified index
|
// // Update the vesting at the specified index
|
||||||
vestings[user][vestingIndex] = Vesting({
|
// vestings[user][vestingIndex] = Vesting({
|
||||||
amount: amount,
|
// amount: amount,
|
||||||
bonus: bonus,
|
// bonus: bonus,
|
||||||
lockedUntil: lockedUntil,
|
// lockedUntil: lockedUntil,
|
||||||
claimedAmount: claimedAmount,
|
// claimedAmount: claimedAmount,
|
||||||
claimedBonus: claimedBonus,
|
// claimedBonus: claimedBonus,
|
||||||
lastClaimed: lastClaimed,
|
// lastClaimed: lastClaimed,
|
||||||
createdAt: createdAt,
|
// createdAt: createdAt,
|
||||||
token: token,
|
// token: token,
|
||||||
complete: false,
|
// complete: false,
|
||||||
usdAmount: usdAmount
|
// usdAmount: usdAmount
|
||||||
});
|
// });
|
||||||
|
|
||||||
// Add new values to totals
|
// // Add new values to totals
|
||||||
dollarsVested[user] += usdAmount;
|
// dollarsVested[user] += usdAmount;
|
||||||
vestedTotal[token] += amount - claimedAmount;
|
// vestedTotal[token] += amount - claimedAmount;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// /// @notice Migrates all vestings from an old address to a new address
|
// /// @notice Migrates all vestings from an old address to a new address
|
||||||
// /// @dev Only to be used by bots for account migrations
|
// /// @dev Only to be used by bots for account migrations
|
||||||
@@ -1314,7 +1341,7 @@ contract CunaFinanceBsc is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
/// @notice Test function for upgrade verification
|
/// @notice Test function for upgrade verification
|
||||||
/// @return Returns a constant value to verify upgrade worked
|
/// @return Returns a constant value to verify upgrade worked
|
||||||
function testUpgradeFunction() external pure returns (uint256) {
|
function testUpgradeFunction() external pure returns (uint256) {
|
||||||
return 999; // Different value from bsc_paca to distinguish contracts
|
return 1001; // Different value from bsc_paca to distinguish contracts
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -208,44 +208,52 @@ contract CunaFinanceSonic is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
emit FundsWithdrawn(msg.sender, SONIC_TOKEN, _amount);
|
emit FundsWithdrawn(msg.sender, SONIC_TOKEN, _amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Admin function to adjust withdraw liabilities (for fixing decimal conversion issues)
|
||||||
|
/// @param token The token address to adjust
|
||||||
|
/// @param newAmount The new liability amount (should be in token's native decimals)
|
||||||
|
function adjustWithdrawLiability(address token, uint256 newAmount) external onlyOwner {
|
||||||
|
withdrawLiabilities[token] = newAmount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function setPriceOracle(address _token, address _oracle) external onlyOwner {
|
function setPriceOracle(address _token, address _oracle) external onlyOwner {
|
||||||
priceOracles[_token] = _oracle;
|
priceOracles[_token] = _oracle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Set unlock schedule for a token using percentage-based steps
|
// /// @notice Set unlock schedule for a token using percentage-based steps
|
||||||
/// @param _token The token address to set the schedule for
|
// /// @param _token The token address to set the schedule for
|
||||||
/// @param _lockTime The initial lock time in seconds
|
// /// @param _lockTime The initial lock time in seconds
|
||||||
/// @param _percentagePerStep The percentage to unlock at each step (scaled by 10000)
|
// /// @param _percentagePerStep The percentage to unlock at each step (scaled by 10000)
|
||||||
function setUnlockScheduleByPercentage(address _token, uint256 _lockTime, uint256 _percentagePerStep) external onlyOwner {
|
// function setUnlockScheduleByPercentage(address _token, uint256 _lockTime, uint256 _percentagePerStep) external onlyOwner {
|
||||||
require(_token != address(0), "Invalid token address");
|
// require(_token != address(0), "Invalid token address");
|
||||||
require(_percentagePerStep > 0 && _percentagePerStep <= 10000, "Invalid percentage");
|
// require(_percentagePerStep > 0 && _percentagePerStep <= 10000, "Invalid percentage");
|
||||||
|
|
||||||
// Clear existing schedule
|
// // Clear existing schedule
|
||||||
delete unlockSchedules[_token];
|
// delete unlockSchedules[_token];
|
||||||
|
|
||||||
uint256 totalPercentage = 0;
|
// uint256 totalPercentage = 0;
|
||||||
uint256 timeOffset = _lockTime;
|
// uint256 timeOffset = _lockTime;
|
||||||
|
|
||||||
// Create unlock steps until we reach 100%
|
// // Create unlock steps until we reach 100%
|
||||||
while (totalPercentage < 10000) {
|
// while (totalPercentage < 10000) {
|
||||||
uint256 stepPercentage = _percentagePerStep;
|
// uint256 stepPercentage = _percentagePerStep;
|
||||||
|
|
||||||
// Adjust last step to exactly reach 100%
|
// // Adjust last step to exactly reach 100%
|
||||||
if (totalPercentage + stepPercentage > 10000) {
|
// if (totalPercentage + stepPercentage > 10000) {
|
||||||
stepPercentage = 10000 - totalPercentage;
|
// stepPercentage = 10000 - totalPercentage;
|
||||||
}
|
// }
|
||||||
|
|
||||||
unlockSchedules[_token].push(UnlockStep({
|
// unlockSchedules[_token].push(UnlockStep({
|
||||||
timeOffset: timeOffset,
|
// timeOffset: timeOffset,
|
||||||
percentage: stepPercentage
|
// percentage: stepPercentage
|
||||||
}));
|
// }));
|
||||||
|
|
||||||
totalPercentage += stepPercentage;
|
// totalPercentage += stepPercentage;
|
||||||
timeOffset += _lockTime; // Each step adds the same time interval
|
// timeOffset += _lockTime; // Each step adds the same time interval
|
||||||
}
|
// }
|
||||||
|
|
||||||
emit UnlockScheduleSet(_token);
|
// emit UnlockScheduleSet(_token);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// /// @notice Set custom unlock schedule for a token with specific steps
|
// /// @notice Set custom unlock schedule for a token with specific steps
|
||||||
// /// @param _token The token address to set the schedule for
|
// /// @param _token The token address to set the schedule for
|
||||||
@@ -357,6 +365,48 @@ contract CunaFinanceSonic is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
currentEpochId++;
|
currentEpochId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Re-enter/update the most recent epoch with new values and recalculated unlock percentage
|
||||||
|
/// @param estDaysRemaining Estimated days remaining for the protocol
|
||||||
|
/// @param currentTreasuryTvl Current treasury total value locked
|
||||||
|
/// @param _paybackPercent Percentage multiplier for unlock calculation (scaled by 10000)
|
||||||
|
/// @param _currentLiability Current total liability amount
|
||||||
|
function reenterEpoch(uint256 estDaysRemaining, uint256 currentTreasuryTvl, uint256 _paybackPercent, uint256 _currentLiability) external onlyOwner {
|
||||||
|
require(currentEpochId > 0, "No epochs to update");
|
||||||
|
|
||||||
|
uint256 epochId = currentEpochId - 1; // Most recent epoch
|
||||||
|
|
||||||
|
uint256 unlockPercentage = 0;
|
||||||
|
// Calculate current ratio
|
||||||
|
if (_currentLiability > 0) {
|
||||||
|
uint256 currentRatio = (currentTreasuryTvl * 10000) / _currentLiability;
|
||||||
|
|
||||||
|
if (epochId > 0) {
|
||||||
|
// Calculate unlock percentage BEFORE updating highest ratio
|
||||||
|
unlockPercentage = calculateUnlockPercentage(currentRatio, _paybackPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update highest ratio AFTER calculating unlock percentage
|
||||||
|
if (currentRatio > highestRatio) {
|
||||||
|
highestRatio = currentRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that unlock percentage doesn't exceed maximum
|
||||||
|
require(unlockPercentage <= maxUnlockPercentage, "Unlock percentage high");
|
||||||
|
|
||||||
|
// Update the existing epoch entry
|
||||||
|
epochs[epochId] = Epoch({
|
||||||
|
estDaysRemaining: estDaysRemaining,
|
||||||
|
currentTreasuryTvl: currentTreasuryTvl,
|
||||||
|
totalLiability: _currentLiability,
|
||||||
|
paybackPercent: _paybackPercent,
|
||||||
|
unlockPercentage: unlockPercentage,
|
||||||
|
timestamp: block.timestamp
|
||||||
|
});
|
||||||
|
|
||||||
|
emit EpochEnded(epochId, currentTreasuryTvl, unlockPercentage, _paybackPercent);
|
||||||
|
}
|
||||||
|
|
||||||
/// @notice Calculate total unclaimed funds for a user across all epochs since last claim
|
/// @notice Calculate total unclaimed funds for a user across all epochs since last claim
|
||||||
function calculateUnclaimedFunds(address user) public view returns (uint256 totalUnclaimed) {
|
function calculateUnclaimedFunds(address user) public view returns (uint256 totalUnclaimed) {
|
||||||
uint256 remainingStake = getNetStake(user);
|
uint256 remainingStake = getNetStake(user);
|
||||||
@@ -452,8 +502,8 @@ contract CunaFinanceSonic is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
transferAmount = amount / 1e12; // Convert from 18 decimals to 6 decimals
|
transferAmount = amount / 1e12; // Convert from 18 decimals to 6 decimals
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrement withdraw liabilities for all tokens (using original 18-decimal amount)
|
// Decrement withdraw liabilities (using correct decimal precision)
|
||||||
withdrawLiabilities[token] -= amount;
|
withdrawLiabilities[token] -= transferAmount;
|
||||||
|
|
||||||
// Transfer tokens to user based on the specified token (using converted amount)
|
// Transfer tokens to user based on the specified token (using converted amount)
|
||||||
IERC20(token).safeTransfer(msg.sender, transferAmount);
|
IERC20(token).safeTransfer(msg.sender, transferAmount);
|
||||||
@@ -507,35 +557,35 @@ contract CunaFinanceSonic is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
|
|
||||||
// Bot Functions for Staking Management
|
// Bot Functions for Staking Management
|
||||||
|
|
||||||
/// @notice Create a withdraw stake for a user (for admin/migration purposes)
|
// /// @notice Create a withdraw stake for a user (for admin/migration purposes)
|
||||||
/// @dev Only to be used by bots for manual withdraw stake creation
|
// /// @dev Only to be used by bots for manual withdraw stake creation
|
||||||
/// @param user The user address to create the withdraw stake for
|
// /// @param user The user address to create the withdraw stake for
|
||||||
/// @param amount The amount for the withdraw stake
|
// /// @param amount The amount for the withdraw stake
|
||||||
/// @param unlockTime The unlock timestamp for the withdraw stake
|
// /// @param unlockTime The unlock timestamp for the withdraw stake
|
||||||
/// @param token The token address for the withdraw stake
|
// /// @param token The token address for the withdraw stake
|
||||||
/// @param isVesting Whether this is a vesting-related stake (adds 1e6 to stakeId)
|
// /// @param isVesting Whether this is a vesting-related stake (adds 1e6 to stakeId)
|
||||||
function createWithdrawStakeForUser(address user, uint256 amount, uint256 unlockTime, address token, bool isVesting) external onlyBot {
|
// function createWithdrawStakeForUser(address user, uint256 amount, uint256 unlockTime, address token, bool isVesting) external onlyBot {
|
||||||
require(user != address(0), "Invalid user address");
|
// require(user != address(0), "Invalid user address");
|
||||||
require(amount > 0, "Invalid amount");
|
// require(amount > 0, "Invalid amount");
|
||||||
require(token != address(0), "Invalid token address");
|
// require(token != address(0), "Invalid token address");
|
||||||
|
|
||||||
// Generate unique stakeId
|
// // Generate unique stakeId
|
||||||
stakeIdCounter++;
|
// stakeIdCounter++;
|
||||||
uint256 finalStakeId = isVesting ? stakeIdCounter + 1e6 : stakeIdCounter;
|
// uint256 finalStakeId = isVesting ? stakeIdCounter + 1e6 : stakeIdCounter;
|
||||||
|
|
||||||
// Create the withdraw stake
|
// // Create the withdraw stake
|
||||||
withdrawStakes[user].push(WithdrawStake({
|
// withdrawStakes[user].push(WithdrawStake({
|
||||||
stakeId: finalStakeId,
|
// stakeId: finalStakeId,
|
||||||
amount: amount,
|
// amount: amount,
|
||||||
unlockTime: unlockTime,
|
// unlockTime: unlockTime,
|
||||||
token: token
|
// token: token
|
||||||
}));
|
// }));
|
||||||
|
|
||||||
// Increment withdraw liabilities for this token
|
// // Increment withdraw liabilities for this token
|
||||||
withdrawLiabilities[token] += amount;
|
// withdrawLiabilities[token] += amount;
|
||||||
|
|
||||||
emit StakeWithdrawn(user, amount, finalStakeId);
|
// emit StakeWithdrawn(user, amount, finalStakeId);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// @notice Batch create stakes for multiple users (efficient for migration)
|
/// @notice Batch create stakes for multiple users (efficient for migration)
|
||||||
/// @dev Only to be used by bots for initial setup
|
/// @dev Only to be used by bots for initial setup
|
||||||
@@ -1201,8 +1251,8 @@ contract CunaFinanceSonic is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
|
|
||||||
// Only update liabilities and emit event if something was actually claimed
|
// Only update liabilities and emit event if something was actually claimed
|
||||||
if (totalBonusClaimed > 0) {
|
if (totalBonusClaimed > 0) {
|
||||||
// Increment withdraw liabilities for SONIC_TOKEN
|
// Increment withdraw liabilities for SONIC_TOKEN (convert from 18 decimals to 6 decimals)
|
||||||
withdrawLiabilities[SONIC_TOKEN] += totalBonusClaimed;
|
withdrawLiabilities[SONIC_TOKEN] += totalBonusClaimed / 1e12;
|
||||||
emit BonusClaimed(msg.sender, totalBonusClaimed);
|
emit BonusClaimed(msg.sender, totalBonusClaimed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1284,44 +1334,11 @@ contract CunaFinanceSonic is Initializable, ReentrancyGuardUpgradeable {
|
|||||||
return totalClaimed[user];
|
return totalClaimed[user];
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// @notice Search marketplace history for stakes where address was seller or buyer
|
|
||||||
// /// @param targetAddress The address to search for as seller or buyer
|
|
||||||
// /// @return Array of MarketplaceHistory structs where address was involved
|
|
||||||
// function searchMarketplaceHistory(address targetAddress) external view returns (MarketplaceHistory[] memory) {
|
|
||||||
// require(targetAddress != address(0), "Invalid address");
|
|
||||||
|
|
||||||
// // Count matches first to size the result array properly
|
|
||||||
// uint256 matchCount = 0;
|
|
||||||
// for (uint256 i = 0; i < marketplaceHistory.length; i++) {
|
|
||||||
// if (marketplaceHistory[i].seller == targetAddress || marketplaceHistory[i].buyer == targetAddress) {
|
|
||||||
// matchCount++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Return empty array if no matches
|
|
||||||
// if (matchCount == 0) {
|
|
||||||
// return new MarketplaceHistory[](0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Create result array with exact size needed
|
|
||||||
// MarketplaceHistory[] memory result = new MarketplaceHistory[](matchCount);
|
|
||||||
// uint256 resultIndex = 0;
|
|
||||||
|
|
||||||
// // Populate result array
|
|
||||||
// for (uint256 i = 0; i < marketplaceHistory.length; i++) {
|
|
||||||
// if (marketplaceHistory[i].seller == targetAddress || marketplaceHistory[i].buyer == targetAddress) {
|
|
||||||
// result[resultIndex] = marketplaceHistory[i];
|
|
||||||
// resultIndex++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// @notice Test function for upgrade verification
|
/// @notice Test function for upgrade verification
|
||||||
/// @return Returns a constant value to verify upgrade worked
|
/// @return Returns a constant value to verify upgrade worked
|
||||||
function testUpgradeFunction() external pure returns (uint256) {
|
function testUpgradeFunction() external pure returns (uint256) {
|
||||||
return 999; // Different value from bsc_paca to distinguish contracts
|
return 1002; // Added adjustWithdrawLiability admin function
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user