Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
442391e
veLike: update withdraw interface to support partial withdraw and rem…
rickmak Feb 25, 2026
56afe3c
veLike: add legacy reward claim infrastructure for reward rotation
rickmak Feb 25, 2026
50a8906
test: update tests for no-lock model and partial withdraw
rickmak Feb 25, 2026
4e74282
test: add legacy reward claim tests
rickmak Feb 25, 2026
0ad5aab
test: add reward rotation integration test
rickmak Feb 25, 2026
11cb16f
veLike: add claimLegacyReward hardhat task
rickmak Feb 25, 2026
ab2744d
veLikeRewardNoLock: copy veLikeReward as starting point
rickmak Feb 27, 2026
d28037e
veLikeRewardNoLock: add no-lock changes with lazy staker sync
rickmak Feb 27, 2026
a03c3e1
veLike: reorder _deposit to call reward contract before mint
rickmak Feb 26, 2026
1f23fed
test: add veLikeRewardNoLock fixtures and update tests for auto-enrol…
rickmak Feb 26, 2026
2e7011a
ignition: add veLikeRewardNoLock deployment module
rickmak Feb 26, 2026
6c8ea4c
chore: Run prettier
rickmak Feb 27, 2026
19a9acd
test: add legacy reward with lock rotation test
rickmak Feb 27, 2026
b021b66
test: add syncStakers and stale-balance fix tests
rickmak Feb 28, 2026
1c45529
veLike: add test for multiple claim of LegacyReward and lazy rollover
rickmak Mar 3, 2026
72fdde0
veLike: add deployment operation doc
rickmak Mar 3, 2026
4199430
veLike: Address comments on extra guard in initTotalStaked
rickmak Mar 3, 2026
5f0872a
veLike: Add veLikeUpgradeV2 ignition modules
rickmak Mar 3, 2026
c1a434c
veLike: Update the velike deployment procedure
rickmak Mar 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions likecoin3/contracts/veLike.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface IRewardContract {
bool restake
) external returns (uint256);
function deposit(address account, uint256 rewardAmount) external;
function withdraw(address account) external;
function withdraw(address account, uint256 amount) external;
}

/// @custom:security-contact [email protected]
Expand All @@ -33,6 +33,7 @@ contract veLike is
struct veLikeStorage {
address rewardContract;
uint256 lockTime;
mapping(address => bool) isLegacyRewardContract;
}

// keccak256(abi.encode(uint256(keccak256("veLike.storage")) - 1)) & ~bytes32(uint256(0xff))
Expand All @@ -50,6 +51,7 @@ contract veLike is
error ErrNoRewardToClaim();
error ErrNonTransferable();
error ErrWithdrawLocked();
error ErrNotLegacyRewardContract();

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
Expand Down Expand Up @@ -83,6 +85,48 @@ contract veLike is
$.rewardContract = rewardContract;
}

/**
* setLegacyRewardContract function
*
* Add or remove a legacy reward contract from the allowlist.
* Legacy reward contracts can be claimed by users after reward rotation.
*
* @param rewardContract - the legacy reward contract address
* @param allowed - true to allow, false to disallow
*/
function setLegacyRewardContract(
address rewardContract,
bool allowed
) public onlyOwner {
veLikeStorage storage $ = _getveLikeData();
$.isLegacyRewardContract[rewardContract] = allowed;
}

/**
* claimLegacyReward function
*
* Claim reward from a legacy (rotated-out) reward contract.
* The legacy reward contract must be allowlisted via setLegacyRewardContract.
*
* @param legacyReward - the legacy reward contract address
* @param account - the account to claim the reward for
* @return reward - the reward claimed
*/
function claimLegacyReward(
address legacyReward,
address account
) public whenNotPaused nonReentrant returns (uint256) {
veLikeStorage storage $ = _getveLikeData();
if (!$.isLegacyRewardContract[legacyReward]) {
revert ErrNotLegacyRewardContract();
}
uint256 reward = IRewardContract(legacyReward).claimReward(
account,
false
);
return reward;
}

/**
* setLockTime function
*
Expand Down Expand Up @@ -236,14 +280,16 @@ contract veLike is
address(this),
assets
);
_mint(receiver, shares);

// Vault specific logic
// Vault specific logic: notify reward contract before mint so that
// _syncStaker reads the pre-deposit balanceOf for correct retroactive rewards.
IRewardContract rewardContract = getCurrentRewardContract();
if (rewardContract != IRewardContract(address(0))) {
rewardContract.deposit(receiver, assets);
}

_mint(receiver, shares);

// Copying from ERC4626 _deposit function Event for clarity
emit Deposit(caller, receiver, assets, shares);
}
Expand Down Expand Up @@ -278,7 +324,7 @@ contract veLike is
// Vault specific logic
IRewardContract rewardContract = getCurrentRewardContract();
if (rewardContract != IRewardContract(address(0))) {
rewardContract.withdraw(owner);
rewardContract.withdraw(owner, assets);
}

// Copying from ERC4626 _withdraw function Event for clarity
Expand Down
12 changes: 6 additions & 6 deletions likecoin3/contracts/veLikeReward.sol
Original file line number Diff line number Diff line change
Expand Up @@ -240,15 +240,15 @@ contract veLikeReward is
$.totalStaked += stakedAmount;
}

function withdraw(address account) public whenNotPaused onlyVault {
function withdraw(
address account,
uint256 amount
) public whenNotPaused onlyVault {
veLikeRewardStorage storage $ = _getveLikeRewardData();
if (_isActive()) {
revert ErrWithdrawLocked();
}
_updateVault();
_claimReward(account, false);
$.totalStaked -= $.stakerInfos[account].stakedAmount;
$.stakerInfos[account].stakedAmount = 0;
$.totalStaked -= amount;
$.stakerInfos[account].stakedAmount -= amount;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check $.totalStaked >= amount;?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should keep track correctly, I updated the op manual. The amount should have sync via _syncStaker in new noLock reward. For the 1st vault, it should no longer call this after the interface update.

hmm, so you are right, this update is not necessary for the first lock, we can keep the old logic.

}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After removing the withdraw-time lock from withdraw(), the ErrWithdrawLocked custom error declared in this contract is no longer referenced anywhere in veLikeReward.sol. Consider removing it to avoid confusion about where the lock is enforced (it now appears to be enforced in veLike).

Copilot uses AI. Check for mistakes.

/**
Expand Down
Loading
Loading