Skip to content

Commit

Permalink
refactor: disable reward -> ptoken conversion if merkle-based (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
jparklev authored May 3, 2024
1 parent 43c2a2d commit c5b2aaf
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
10 changes: 8 additions & 2 deletions contracts/PointTokenVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract PointTokenVault is UUPSUpgradeable, AccessControlUpgradeable, Multicall
bytes32 public constant MERKLE_UPDATER_ROLE = keccak256("MERKLE_UPDATER_ROLE");
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");

// Deposit asset balancess.
// Deposit asset balances.
mapping(address => mapping(ERC20 => uint256)) public balances; // user => point-earning token => balance

// Merkle root distribution.
Expand Down Expand Up @@ -69,6 +69,7 @@ contract PointTokenVault is UUPSUpgradeable, AccessControlUpgradeable, Multicall
error ProofInvalidOrExpired();
error ClaimTooLarge();
error RewardsNotReleased();
error CantConvertMerkleRedemption();
error PTokenAlreadyDeployed();
error DepositExceedsCap();
error PTokenNotDeployed();
Expand Down Expand Up @@ -156,12 +157,17 @@ contract PointTokenVault is UUPSUpgradeable, AccessControlUpgradeable, Multicall
/// @notice Mints point tokens for rewards after redemption has been enabled
function convertRewardsToPTokens(address _receiver, bytes32 _pointsId, uint256 _amountToConvert) public {
RedemptionParams memory params = redemptions[_pointsId];
(ERC20 rewardToken, uint256 rewardsPerPToken) = (params.rewardToken, params.rewardsPerPToken);
(ERC20 rewardToken, uint256 rewardsPerPToken, bool isMerkleBased) =
(params.rewardToken, params.rewardsPerPToken, params.isMerkleBased);

if (address(rewardToken) == address(0)) {
revert RewardsNotReleased();
}

if (isMerkleBased) {
revert CantConvertMerkleRedemption();
}

rewardToken.safeTransferFrom(msg.sender, address(this), _amountToConvert);
pTokens[_pointsId].mint(_receiver, FixedPointMathLib.divWadDown(_amountToConvert, rewardsPerPToken)); // Round down for mint.
}
Expand Down
36 changes: 36 additions & 0 deletions contracts/test/PointTokenVault.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,42 @@ contract PointTokenVaultTest is Test {
assertEq(pointTokenVault.pTokens(eigenPointsId).balanceOf(vitalik), 0);
}

function test_CantMintPTokensForRewardsMerkleBased() public {
bool IS_MERKLE_BASED = true;

bytes32 root = 0x409fd0e46d8453765fb513ae35a1899d667478c40233b67360023c86927eb802;

bytes32[] memory proof = new bytes32[](2);
proof[0] = 0x6d0fcb8de12b1f57f81e49fa18b641487b932cdba4f064409fde3b05d3824ca2;
proof[1] = 0xae126f1299213c869259b52ab24f7270f3cce1de54c187271c52373d8947c2fe;

vm.prank(merkleUpdater);
pointTokenVault.updateRoot(root);

vm.prank(vitalik);
pointTokenVault.claimPTokens(PointTokenVault.Claim(eigenPointsId, 1e18, 1e18, proof), vitalik);

rewardToken.mint(address(pointTokenVault), 3e18);

vm.prank(operator);
pointTokenVault.setRedemption(eigenPointsId, rewardToken, 2e18, IS_MERKLE_BASED);

bytes32[] memory redemptionProof = new bytes32[](1);
redemptionProof[0] = 0x4e40a10ce33f33a4786960a8bb843fe0e170b651acd83da27abc97176c4bed3c;
vm.prank(vitalik);
pointTokenVault.redeemRewards(PointTokenVault.Claim(eigenPointsId, 2e18, 2e18, redemptionProof), vitalik);

assertEq(rewardToken.balanceOf(vitalik), 2e18);
assertEq(pointTokenVault.pTokens(eigenPointsId).balanceOf(vitalik), 0);

// Can't mint ptokens if it's a merkle-based redemption
vm.prank(vitalik);
rewardToken.approve(address(pointTokenVault), 1e18);
vm.prank(vitalik);
vm.expectRevert(PointTokenVault.CantConvertMerkleRedemption.selector);
pointTokenVault.convertRewardsToPTokens(vitalik, eigenPointsId, 1e18);
}

function test_ReceiveETH() public payable {
// Amount of ETH to send
uint256 amountToSend = 1 ether;
Expand Down

0 comments on commit c5b2aaf

Please sign in to comment.