Skip to content

Commit

Permalink
Merge pull request #52 from sense-finance/etherfi-king-set-redemption
Browse files Browse the repository at this point in the history
feat: add calc for etherfiS4 rewards per ptoken, add test
  • Loading branch information
jparklev authored Feb 20, 2025
2 parents 389083c + f73f5fe commit 43875da
Show file tree
Hide file tree
Showing 4 changed files with 2,512 additions and 0 deletions.
14 changes: 14 additions & 0 deletions contracts/script/PointTokenVault.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ contract PointTokenVaultScripts is BatchScript {
vm.stopBroadcast();
}

function setRedemptionEtherFi19Feb25() public {
// Core contract and token setup
PointTokenVault vaultV1_0_0 = PointTokenVault(payable(0xe47F9Dbbfe98d6930562017ee212C1A1Ae45ba61));
bytes32 pointsId = LibString.packTwo("Rumpel kPt: ETHERFI S4", "kpEF-4");
ERC20 kingToken = ERC20(0x8F08B70456eb22f6109F57b8fafE862ED28E6040);
uint256 rewardsPerPToken = 895065548932;
bool usesRedemptionRights = false;

// Set redemption parameters
vm.startBroadcast(MAINNET_OPERATOR);
vaultV1_0_0.setRedemption(pointsId, kingToken, rewardsPerPToken, usesRedemptionRights);
vm.stopBroadcast();
}

// Useful for emergencies, where we need to override both the current and previous root at once
// For example, if minting for a specific pToken needs to be stopped, a root without any claim rights for the pToken would need to be pushed twice
function doublePushRoot(address pointTokenVaultAddress, bytes32 newRoot, address merkleUpdaterSafe) public {
Expand Down
49 changes: 49 additions & 0 deletions contracts/test/SetRedemptionEtherFiS4Feb25.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity =0.8.24;

import {Test} from "forge-std/Test.sol";
import {LibString} from "solady/utils/LibString.sol";
import {ERC20} from "solmate/test/utils/mocks/MockERC20.sol";

import {PointTokenVault} from "../PointTokenVault.sol";
import {PointTokenVaultScripts} from "../script/PointTokenVault.s.sol";

contract SetRedemptionEtherFiS4Feb25 is Test {
PointTokenVault vaultV1_0_0 = PointTokenVault(payable(0xe47F9Dbbfe98d6930562017ee212C1A1Ae45ba61));
bytes32 pointsId = LibString.packTwo("Rumpel kPt: ETHERFI S4", "kpEF-4");
ERC20 kingToken = ERC20(0x8F08B70456eb22f6109F57b8fafE862ED28E6040);

function setUp() public {
string memory MAINNET_RPC_URL = vm.envString("MAINNET_RPC_URL");
uint256 forkId = vm.createFork(MAINNET_RPC_URL, 21_882_150); // Block mined at Feb-19-2025 06:16:59 PM +UTC
vm.selectFork(forkId);

PointTokenVaultScripts scripts = new PointTokenVaultScripts();
scripts.setRedemptionEtherFi19Feb25();
}

event RewardsClaimed(
address indexed owner, address indexed receiver, bytes32 indexed pointsId, uint256 amount, uint256 fee
);

function test_RedeemRewards1() public {
bytes32[] memory empty = new bytes32[](0);
address USER = 0x2E11E6ac295249642253FA47419849153BD8EFC1;
uint256 AMOUNT = 93053350810428;

vm.prank(USER);
vm.expectEmit(true, true, true, true);
emit RewardsClaimed(USER, USER, pointsId, AMOUNT, 0);
vaultV1_0_0.redeemRewards(PointTokenVault.Claim(pointsId, AMOUNT, AMOUNT, empty), USER);
}

function test_FailedRedeemRewards_ClaimTooMuch() public {
bytes32[] memory empty = new bytes32[](0);
address USER = 0x2E11E6ac295249642253FA47419849153BD8EFC1;
uint256 AMOUNT = 93053350810428 + 2;

vm.prank(USER);
vm.expectRevert();
vaultV1_0_0.redeemRewards(PointTokenVault.Claim(pointsId, AMOUNT, AMOUNT, empty), USER);
}
}
57 changes: 57 additions & 0 deletions js-scripts/generateRedemptionRights/countpoints-etherfiS4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { readFileSync } from "fs";

// received transaction
// https://etherscan.io/tx/0x8ca29113461d936c01b7f34a9f4d8649d0e271cbe1b89ddcd0798210b2466c6d
const rewards = 25299464779708667665;

// copy and paste from: https://oracle.rumpel.xyz/
// Date Queued: 2/18/2025
const data = JSON.parse(
readFileSync(
`${process.cwd()}/js-scripts/generateRedemptionRights/etherfi-s4-distribution.json`
)
);

// deployment tx of 0xd0b520304dC2dF26c8C73294901220D549217aAc:
// https://etherscan.io/tx/0x856c39ebd8fe3b3cc7c5ad5e21b4d3954caa8c763a915e73b64aa9af3ab9bba1
const etherFi4PointToken = "0xd0b520304dC2dF26c8C73294901220D549217aAc";

const etherFi4Point =
"0x1652756d70656c206b50743a2045544845524649205334066b7045462d340000";

const pTokens = data.balances;

let total = 0;
for (const user in pTokens) {
total += parseInt(pTokens[user][etherFi4Point]);
}

const totalPTokens = total;
const rewardsPerPToken = (rewards * 1e18) / totalPTokens;

console.log();
console.log(rewards.toLocaleString("fullwide", { useGrouping: false }));

console.log();
console.log("Total pTokens - claimed and unclaimed:");
console.log(totalPTokens.toLocaleString("fullwide", { useGrouping: false }));

console.log();
console.log("rewards per ptoken");
console.log(
rewardsPerPToken.toLocaleString("fullwide", { useGrouping: false })
);
console.log((rewardsPerPToken / 1e18).toFixed(18));

console.log();
console.log(
`rewardsPerToken is rounded down: ${
rewards >= (rewardsPerPToken * totalPTokens) / 1e18
}`
);
console.log(
((rewardsPerPToken * totalPTokens) / 1e18).toLocaleString("fullwide", {
useGrouping: false,
})
);
console.log(rewards.toLocaleString("fullwide", { useGrouping: false }));
Loading

0 comments on commit 43875da

Please sign in to comment.