diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a632b75..e14c4a2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,3 +32,5 @@ jobs: run: | forge test -vvv id: test + env: + MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a9cbde5..2c26010 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Compiler files cache/ -out/ +/out/ # Ignores development broadcast logs !/broadcast diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..13f08c7 Binary files /dev/null and b/bun.lockb differ diff --git a/contracts/script/PointTokenVault.s.sol b/contracts/script/PointTokenVault.s.sol index c6f6f8a..8e7fa4f 100644 --- a/contracts/script/PointTokenVault.s.sol +++ b/contracts/script/PointTokenVault.s.sol @@ -4,10 +4,8 @@ pragma solidity =0.8.24; import {BatchScript} from "forge-safe/src/BatchScript.sol"; import {PointTokenVault} from "../PointTokenVault.sol"; -import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; -import {CREATE3} from "solmate/utils/CREATE3.sol"; import {LibString} from "solady/utils/LibString.sol"; import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol"; @@ -97,11 +95,12 @@ contract PointTokenVaultScripts is BatchScript { } function deployPToken() public { - vm.startBroadcast(JIM_PRIVATE_KEY); + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); - PointTokenVault pointTokenVault = PointTokenVault(payable(0xbff7Fb79efC49504afc97e74F83EE618768e63E9)); + PointTokenVault pointTokenVault = PointTokenVault(payable(0xe47F9Dbbfe98d6930562017ee212C1A1Ae45ba61)); - pointTokenVault.deployPToken(LibString.packTwo("ETHERFI Points", "pEF")); + pointTokenVault.deployPToken(LibString.packTwo("Rumpel kPt: ETHERFI S4", "kpEF-4")); vm.stopBroadcast(); } @@ -118,6 +117,25 @@ contract PointTokenVaultScripts is BatchScript { vm.stopBroadcast(); } + function setRedemptionENA4Nov24() public { + // Core contract and token setup + PointTokenVault vaultV0_1_0 = PointTokenVault(payable(0x1EeEBa76f211C4Dce994b9c5A74BDF25DB649Fa1)); + bytes32 pointsId = LibString.packTwo("Rumpel kPoint: Ethena S2", "kpSATS"); + ERC20 senaToken = ERC20(0x8bE3460A480c80728a8C4D7a5D5303c85ba7B3b9); + uint256 rewardsPerPToken = 63381137368827226; + bool usesRedemptionRights = true; + + // Set redemption parameters + vm.startBroadcast(MAINNET_OPERATOR); + vaultV0_1_0.setRedemption(pointsId, senaToken, rewardsPerPToken, usesRedemptionRights); + vm.stopBroadcast(); + + // Update merkle root + vm.startBroadcast(MAINNET_MERKLE_UPDATER); + vaultV0_1_0.updateRoot(0xa1c76e2c6f7ac8300b288ff758b8a83c4a19e12780ca7ac5f61182f64ef8edf6); + 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 { diff --git a/contracts/test/SetRedemptionENA4Nov24.t.sol b/contracts/test/SetRedemptionENA4Nov24.t.sol new file mode 100644 index 0000000..8c0b285 --- /dev/null +++ b/contracts/test/SetRedemptionENA4Nov24.t.sol @@ -0,0 +1,236 @@ +// 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"; +import {PToken} from "../PToken.sol"; + +contract SetRedemptionENA4Nov24Test is Test { + PointTokenVault vaultV0_1_0 = PointTokenVault(payable(0x1EeEBa76f211C4Dce994b9c5A74BDF25DB649Fa1)); + PToken kpSats = PToken(0xdFa21ceC8A46386F5d36F4b07E18BcCcA59f425B); + bytes32 pointsId = LibString.packTwo("Rumpel kPoint: Ethena S2", "kpSATS"); + + mapping(address => bool) userAccountedFor; // pToken holder accounted for + + function setUp() public { + string memory MAINNET_RPC_URL = vm.envString("MAINNET_RPC_URL"); + uint256 forkId = vm.createFork(MAINNET_RPC_URL, 21_112_610); // Block mined at Nov-04-2024 06:51:59 AM +UTC + vm.selectFork(forkId); + + PointTokenVaultScripts scripts = new PointTokenVaultScripts(); + scripts.setRedemptionENA4Nov24(); + } + + function test_RedemptionRights1() public { + bytes32[] memory proof = new bytes32[](5); + proof[0] = 0x4e0230e7a7546148f373efe52256490c04ea0019e199f2256a375e75cf2b6b96; + proof[1] = 0xfaca43636023a73bf06295aa693c262efe0bb3231357a68b8ad7eec7e901c8ef; + proof[2] = 0x03c4c7f992659d2c405eb95248d21dfd7f66c7bdef49d9d33cb97b0b5d35c37a; + proof[3] = 0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51; + proof[4] = 0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41; + + address USER = 0x25E426b153e74Ab36b2685c3A464272De60888Ae; + uint256 AMOUNT = 26396311093240867247; + + vm.prank(USER); + vaultV0_1_0.redeemRewards(PointTokenVault.Claim(pointsId, AMOUNT, AMOUNT, proof), USER); + } + + function test_FailedRedemptionRights1_BadProof() public { + bytes32[] memory proof = new bytes32[](5); + proof[0] = 0x000008976022911aeb40e40bcb5754f9529f2080710f7ec1db8ace85c4f7b7f8; + proof[1] = 0xc6f15a7cbd986873c6b761e81c98ee8ac4afd1c9885b7d8e0ae4de752040ab12; + proof[2] = 0xca808b743099c608cd9b81872c528c521d76505c116bedabfdcc6307c9c92bfb; + proof[3] = 0x703f21e968e8791afb70bcf780821f479ea90632b109016d8b24c8637771383c; + proof[4] = 0x0f76084b6c6777c64b0f591ee64d8c66c54c0bdeb5ce44142823c0f74b856267; + + address USER = 0x25E426b153e74Ab36b2685c3A464272De60888Ae; + uint256 AMOUNT = 52792622186481736164; + + vm.prank(USER); + vm.expectRevert(PointTokenVault.ProofInvalidOrExpired.selector); + vaultV0_1_0.redeemRewards(PointTokenVault.Claim(pointsId, AMOUNT, AMOUNT, proof), USER); + } + + function test_RedemptionRights1_ClaimTooMuch() public { + bytes32[] memory proof = new bytes32[](5); + proof[0] = 0x4e0230e7a7546148f373efe52256490c04ea0019e199f2256a375e75cf2b6b96; + proof[1] = 0xfaca43636023a73bf06295aa693c262efe0bb3231357a68b8ad7eec7e901c8ef; + proof[2] = 0x03c4c7f992659d2c405eb95248d21dfd7f66c7bdef49d9d33cb97b0b5d35c37a; + proof[3] = 0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51; + proof[4] = 0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41; + + address USER = 0x25E426b153e74Ab36b2685c3A464272De60888Ae; + uint256 TOTAL_CLAIMABLE = 26396311093240867247; + uint256 CLAIM_AMOUNT = 26396311093240867247 + 10; + + vm.prank(USER); + vm.expectRevert(PointTokenVault.ClaimTooLarge.selector); + vaultV0_1_0.redeemRewards(PointTokenVault.Claim(pointsId, TOTAL_CLAIMABLE, CLAIM_AMOUNT, proof), USER); + } + + struct RedemptionData { + uint256 pTokenBalance; + uint256 claimedPoints; + uint256 totalClaimablePoints; + uint256 unclaimedPoints; + uint256 totalRedeemableBalance; + uint256 currentRedeemableBalance; + } + + struct RedemptionFiles { + string root; + string path; + string alphaDistribution; + string merged; + string balances; + } + + function test_RedemptionRightsCalculatedAmount() public { + uint256 rewardsPerPToken = 63381137368827226; + + uint256 expectedRedemptionRights; + uint256 redemptionRightAmount; + + RedemptionFiles memory rf; + rf.root = vm.projectRoot(); + rf.path = string.concat(rf.root, "/js-scripts/generateRedemptionRights/last-alpha-distribution.json"); + rf.alphaDistribution = vm.readFile(rf.path); + rf.path = string.concat(rf.root, "/js-scripts/generateRedemptionRights/out/merged-distribution.json"); + rf.merged = vm.readFile(rf.path); + rf.path = string.concat(rf.root, "/js-scripts/generateRedemptionRights/out/ptoken-snapshot-kpsats.json"); + rf.balances = vm.readFile(rf.path); + + string[] memory users = vm.parseJsonKeys(rf.alphaDistribution,string.concat(".pTokens")); + for(uint256 i=0; i < users.length; i++) { + RedemptionData memory rd; + address user = stringToAddress(users[i]); + userAccountedFor[user] = true; + + rd.pTokenBalance = kpSats.balanceOf(user); + rd.claimedPoints = vaultV0_1_0.claimedPTokens(user, pointsId); + rd.totalClaimablePoints = vm.parseJsonUint( + rf.alphaDistribution, + string.concat(".pTokens.", vm.toString(user), ".", vm.toString(pointsId), ".accumulatingPoints") + ); + + rd.unclaimedPoints = rd. totalClaimablePoints - rd.claimedPoints; + rd.totalRedeemableBalance = rd.pTokenBalance + rd.unclaimedPoints; + + // uni overrides + if(user == 0x24C694d193B19119bcDea9D40a3b0bfaFb281E6D){ + rd.totalRedeemableBalance += 6487631537430741114; + } + if(user == 0x44Cb2d713BDa3858001f038645fD05E23E5DE03D){ + rd.totalRedeemableBalance += 27597767454066598826095; + } + + expectedRedemptionRights = rd.totalRedeemableBalance * rewardsPerPToken / 2e18; + try vm.parseJsonUint( + rf.merged, + string.concat(".redemptionRights.", vm.toString(user), ".", vm.toString(pointsId), ".amount") + ) returns (uint256 amount) { + redemptionRightAmount = amount; + } + catch { + redemptionRightAmount = 0; + } + + assertLe(redemptionRightAmount, expectedRedemptionRights); + assertApproxEqAbs(redemptionRightAmount, expectedRedemptionRights, 1e10); + + expectedRedemptionRights = 0; + redemptionRightAmount = 0; + } + + // account for users with pToken balances, but no claimable tokens + string[] memory balanceUsers = vm.parseJsonKeys(rf.balances,string.concat(".balances")); + for(uint256 i=0; i < balanceUsers.length; i++) { + address user = stringToAddress(balanceUsers[i]); + if(!userAccountedFor[user]){ + RedemptionData memory rd; + userAccountedFor[user] = true; + + rd.pTokenBalance = kpSats.balanceOf(user); + rd.totalRedeemableBalance = rd.pTokenBalance; + + // uni overrides + if(user == 0x24C694d193B19119bcDea9D40a3b0bfaFb281E6D){ + rd.totalRedeemableBalance += 6487631537430741114; + } + if(user == 0x44Cb2d713BDa3858001f038645fD05E23E5DE03D){ + rd.totalRedeemableBalance += 27597767454066598826095; + } + + expectedRedemptionRights = rd.totalRedeemableBalance * rewardsPerPToken / 2e18; + + redemptionRightAmount; + try vm.parseJsonUint( + rf.merged, + string.concat(".redemptionRights.", vm.toString(user), ".", vm.toString(pointsId), ".amount") + ) returns (uint256 amount) { + redemptionRightAmount = amount; + } + catch { + redemptionRightAmount = 0; + } + + assertLe(redemptionRightAmount, expectedRedemptionRights); + assertApproxEqAbs(redemptionRightAmount, expectedRedemptionRights, 1e10); + + expectedRedemptionRights = 0; + redemptionRightAmount = 0; + } + } + } + + function stringToAddress(string memory _address) internal returns (address) { + // Remove "0x" prefix if present + bytes memory _addressBytes = bytes(_address); + if (_addressBytes.length >= 2 && _addressBytes[0] == "0" && (_addressBytes[1] == "x" || _addressBytes[1] == "X")) { + string memory _cleanAddress = new string(_addressBytes.length - 2); + for(uint i = 0; i < _addressBytes.length - 2; i++) { + bytes(_cleanAddress)[i] = _addressBytes[i + 2]; + } + _address = _cleanAddress; + } + + // Check if the string length is correct (40 characters for address without 0x) + require(bytes(_address).length == 40, "Invalid address length"); + + // Convert string to bytes + bytes memory _hexBytes = bytes(_address); + uint160 _parsedAddress = 0; + + // Convert each character to its hex value + for(uint i = 0; i < 40; i++) { + bytes1 char = _hexBytes[i]; + uint8 digit; + + if (uint8(char) >= 48 && uint8(char) <= 57) { + // 0-9 + digit = uint8(char) - 48; + } else if (uint8(char) >= 65 && uint8(char) <= 70) { + // A-F + digit = uint8(char) - 55; + } else if (uint8(char) >= 97 && uint8(char) <= 102) { + // a-f + digit = uint8(char) - 87; + } else { + revert("Invalid character in address string"); + } + + _parsedAddress = _parsedAddress * 16 + digit; + } + + return address(_parsedAddress); + } +} + +interface OldVault { + function claimPTokens(PointTokenVault.Claim calldata claim, address account) external; +} diff --git a/foundry.toml b/foundry.toml index 6d69766..797fa61 100644 --- a/foundry.toml +++ b/foundry.toml @@ -10,6 +10,10 @@ ffi = true ast = true build_info = true extra_output = ["storageLayout"] +fs_permissions = [{ access = "read", path = "./js-scripts/generateRedemptionRights/last-alpha-distribution.json" }, +{ access = "read", path = "./js-scripts/generateRedemptionRights/out/merged-distribution.json" }, +{ access = "read", path = "./js-scripts/generateRedemptionRights/out/ptoken-snapshot-kpsats.json" }, +{ access = "read", path = "./out/PointTokenVault.sol/PointTokenVault.json" }] [rpc_endpoints] sepolia = "${SEPOLIA_RPC_URL}" diff --git a/js-scripts/generateRedemptionRights/abis/point-token-vault.ts b/js-scripts/generateRedemptionRights/abis/point-token-vault.ts new file mode 100644 index 0000000..197a192 --- /dev/null +++ b/js-scripts/generateRedemptionRights/abis/point-token-vault.ts @@ -0,0 +1,914 @@ +export const pointTokenVaultABI = [ + { type: "constructor", inputs: [], stateMutability: "nonpayable" }, + { type: "receive", stateMutability: "payable" }, + { + type: "function", + name: "DEFAULT_ADMIN_ROLE", + inputs: [], + outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + stateMutability: "view", + }, + { + type: "function", + name: "MERKLE_UPDATER_ROLE", + inputs: [], + outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + stateMutability: "view", + }, + { + type: "function", + name: "OPERATOR_ROLE", + inputs: [], + outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + stateMutability: "view", + }, + { + type: "function", + name: "REDEMPTION_RIGHTS_PREFIX", + inputs: [], + outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + stateMutability: "view", + }, + { + type: "function", + name: "UPGRADE_INTERFACE_VERSION", + inputs: [], + outputs: [{ name: "", type: "string", internalType: "string" }], + stateMutability: "view", + }, + { + type: "function", + name: "balances", + inputs: [ + { name: "", type: "address", internalType: "address" }, + { name: "", type: "address", internalType: "contract ERC20" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "caps", + inputs: [{ name: "", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "claimPTokens", + inputs: [ + { + name: "_claim", + type: "tuple", + internalType: "struct PointTokenVault.Claim", + components: [ + { name: "pointsId", type: "bytes32", internalType: "bytes32" }, + { name: "totalClaimable", type: "uint256", internalType: "uint256" }, + { name: "amountToClaim", type: "uint256", internalType: "uint256" }, + { name: "proof", type: "bytes32[]", internalType: "bytes32[]" }, + ], + }, + { name: "_account", type: "address", internalType: "address" }, + { name: "_receiver", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "claimedPTokens", + inputs: [ + { name: "", type: "address", internalType: "address" }, + { name: "", type: "bytes32", internalType: "bytes32" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "claimedRedemptionRights", + inputs: [ + { name: "", type: "address", internalType: "address" }, + { name: "", type: "bytes32", internalType: "bytes32" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "collectFees", + inputs: [{ name: "_pointsId", type: "bytes32", internalType: "bytes32" }], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "convertRewardsToPTokens", + inputs: [ + { name: "_receiver", type: "address", internalType: "address" }, + { name: "_pointsId", type: "bytes32", internalType: "bytes32" }, + { name: "_amountToConvert", type: "uint256", internalType: "uint256" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "currRoot", + inputs: [], + outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + stateMutability: "view", + }, + { + type: "function", + name: "deployPToken", + inputs: [{ name: "_pointsId", type: "bytes32", internalType: "bytes32" }], + outputs: [ + { name: "pToken", type: "address", internalType: "contract PToken" }, + ], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "deposit", + inputs: [ + { name: "_token", type: "address", internalType: "contract ERC20" }, + { name: "_amount", type: "uint256", internalType: "uint256" }, + { name: "_receiver", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "execute", + inputs: [ + { name: "_to", type: "address", internalType: "address" }, + { name: "_data", type: "bytes", internalType: "bytes" }, + { name: "_txGas", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "success", type: "bool", internalType: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "feeCollector", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "feelesslyRedeemedPTokens", + inputs: [ + { name: "", type: "address", internalType: "address" }, + { name: "", type: "bytes32", internalType: "bytes32" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "getRoleAdmin", + inputs: [{ name: "role", type: "bytes32", internalType: "bytes32" }], + outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + stateMutability: "view", + }, + { + type: "function", + name: "grantRole", + inputs: [ + { name: "role", type: "bytes32", internalType: "bytes32" }, + { name: "account", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "hasRole", + inputs: [ + { name: "role", type: "bytes32", internalType: "bytes32" }, + { name: "account", type: "address", internalType: "address" }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "initialize", + inputs: [ + { name: "_admin", type: "address", internalType: "address" }, + { name: "_feeCollector", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "mintFee", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "multicall", + inputs: [{ name: "data", type: "bytes[]", internalType: "bytes[]" }], + outputs: [{ name: "results", type: "bytes[]", internalType: "bytes[]" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "pTokenFeeAcc", + inputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "pTokens", + inputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + outputs: [{ name: "", type: "address", internalType: "contract PToken" }], + stateMutability: "view", + }, + { + type: "function", + name: "pausePToken", + inputs: [{ name: "_pointsId", type: "bytes32", internalType: "bytes32" }], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "prevRoot", + inputs: [], + outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + stateMutability: "view", + }, + { + type: "function", + name: "proxiableUUID", + inputs: [], + outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + stateMutability: "view", + }, + { + type: "function", + name: "redeemRewards", + inputs: [ + { + name: "_claim", + type: "tuple", + internalType: "struct PointTokenVault.Claim", + components: [ + { name: "pointsId", type: "bytes32", internalType: "bytes32" }, + { name: "totalClaimable", type: "uint256", internalType: "uint256" }, + { name: "amountToClaim", type: "uint256", internalType: "uint256" }, + { name: "proof", type: "bytes32[]", internalType: "bytes32[]" }, + ], + }, + { name: "_receiver", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "redemptionFee", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "redemptions", + inputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + outputs: [ + { name: "rewardToken", type: "address", internalType: "contract ERC20" }, + { name: "rewardsPerPToken", type: "uint256", internalType: "uint256" }, + { name: "isMerkleBased", type: "bool", internalType: "bool" }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "renouncePauseRole", + inputs: [{ name: "_pointsId", type: "bytes32", internalType: "bytes32" }], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "renounceRole", + inputs: [ + { name: "role", type: "bytes32", internalType: "bytes32" }, + { name: "callerConfirmation", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "revokeRole", + inputs: [ + { name: "role", type: "bytes32", internalType: "bytes32" }, + { name: "account", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "rewardTokenFeeAcc", + inputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "setCap", + inputs: [ + { name: "_token", type: "address", internalType: "address" }, + { name: "_cap", type: "uint256", internalType: "uint256" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setFeeCollector", + inputs: [ + { name: "_feeCollector", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setMintFee", + inputs: [{ name: "_mintFee", type: "uint256", internalType: "uint256" }], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setRedemption", + inputs: [ + { name: "_pointsId", type: "bytes32", internalType: "bytes32" }, + { name: "_rewardToken", type: "address", internalType: "contract ERC20" }, + { name: "_rewardsPerPToken", type: "uint256", internalType: "uint256" }, + { name: "_isMerkleBased", type: "bool", internalType: "bool" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setRedemptionFee", + inputs: [ + { name: "_redemptionFee", type: "uint256", internalType: "uint256" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "supportsInterface", + inputs: [{ name: "interfaceId", type: "bytes4", internalType: "bytes4" }], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "totalDeposited", + inputs: [{ name: "", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "trustReceiver", + inputs: [ + { name: "_account", type: "address", internalType: "address" }, + { name: "_isTrusted", type: "bool", internalType: "bool" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "trustedReceivers", + inputs: [ + { name: "", type: "address", internalType: "address" }, + { name: "", type: "address", internalType: "address" }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "unpausePToken", + inputs: [{ name: "_pointsId", type: "bytes32", internalType: "bytes32" }], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "updateRoot", + inputs: [{ name: "_newRoot", type: "bytes32", internalType: "bytes32" }], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "upgradeToAndCall", + inputs: [ + { name: "newImplementation", type: "address", internalType: "address" }, + { name: "data", type: "bytes", internalType: "bytes" }, + ], + outputs: [], + stateMutability: "payable", + }, + { + type: "function", + name: "withdraw", + inputs: [ + { name: "_token", type: "address", internalType: "contract ERC20" }, + { name: "_amount", type: "uint256", internalType: "uint256" }, + { name: "_receiver", type: "address", internalType: "address" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "event", + name: "CapSet", + inputs: [ + { + name: "token", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "prevCap", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { name: "cap", type: "uint256", indexed: false, internalType: "uint256" }, + ], + anonymous: false, + }, + { + type: "event", + name: "Deposit", + inputs: [ + { + name: "depositor", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "receiver", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "token", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "FeeCollectorSet", + inputs: [ + { + name: "feeCollector", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "FeesCollected", + inputs: [ + { + name: "pointsId", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "feeCollector", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "pTokenFee", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "rewardTokenFee", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Initialized", + inputs: [ + { + name: "version", + type: "uint64", + indexed: false, + internalType: "uint64", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "MintFeeSet", + inputs: [ + { + name: "mintFee", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "PTokenDeployed", + inputs: [ + { + name: "pointsId", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "pToken", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "PTokensClaimed", + inputs: [ + { + name: "account", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "receiver", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "pointsId", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { name: "fee", type: "uint256", indexed: false, internalType: "uint256" }, + ], + anonymous: false, + }, + { + type: "event", + name: "RedemptionFeeSet", + inputs: [ + { + name: "redemptionFee", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "RewardRedemptionSet", + inputs: [ + { + name: "pointsId", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "rewardToken", + type: "address", + indexed: false, + internalType: "contract ERC20", + }, + { + name: "rewardsPerPToken", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "isMerkleBased", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "RewardsClaimed", + inputs: [ + { + name: "owner", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "receiver", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "pointsId", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { name: "fee", type: "uint256", indexed: false, internalType: "uint256" }, + ], + anonymous: false, + }, + { + type: "event", + name: "RewardsConverted", + inputs: [ + { + name: "owner", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "receiver", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "pointsId", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "RoleAdminChanged", + inputs: [ + { name: "role", type: "bytes32", indexed: true, internalType: "bytes32" }, + { + name: "previousAdminRole", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "newAdminRole", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "RoleGranted", + inputs: [ + { name: "role", type: "bytes32", indexed: true, internalType: "bytes32" }, + { + name: "account", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "sender", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "RoleRevoked", + inputs: [ + { name: "role", type: "bytes32", indexed: true, internalType: "bytes32" }, + { + name: "account", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "sender", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "RootUpdated", + inputs: [ + { + name: "prevRoot", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + { + name: "newRoot", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "TrustReceiver", + inputs: [ + { + name: "owner", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "delegate", + type: "address", + indexed: true, + internalType: "address", + }, + { name: "isTrusted", type: "bool", indexed: false, internalType: "bool" }, + ], + anonymous: false, + }, + { + type: "event", + name: "Upgraded", + inputs: [ + { + name: "implementation", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Withdraw", + inputs: [ + { + name: "withdrawer", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "receiver", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "token", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { type: "error", name: "AccessControlBadConfirmation", inputs: [] }, + { + type: "error", + name: "AccessControlUnauthorizedAccount", + inputs: [ + { name: "account", type: "address", internalType: "address" }, + { name: "neededRole", type: "bytes32", internalType: "bytes32" }, + ], + }, + { + type: "error", + name: "AddressEmptyCode", + inputs: [{ name: "target", type: "address", internalType: "address" }], + }, + { type: "error", name: "AmountTooSmall", inputs: [] }, + { type: "error", name: "CantConvertMerkleRedemption", inputs: [] }, + { type: "error", name: "ClaimTooLarge", inputs: [] }, + { type: "error", name: "DepositExceedsCap", inputs: [] }, + { + type: "error", + name: "ERC1967InvalidImplementation", + inputs: [ + { name: "implementation", type: "address", internalType: "address" }, + ], + }, + { type: "error", name: "ERC1967NonPayable", inputs: [] }, + { + type: "error", + name: "ExecutionFailed", + inputs: [ + { name: "to", type: "address", internalType: "address" }, + { name: "data", type: "bytes", internalType: "bytes" }, + ], + }, + { type: "error", name: "FailedCall", inputs: [] }, + { type: "error", name: "InvalidInitialization", inputs: [] }, + { type: "error", name: "NotInitializing", inputs: [] }, + { type: "error", name: "NotTrustedReceiver", inputs: [] }, + { type: "error", name: "PTokenAlreadyDeployed", inputs: [] }, + { type: "error", name: "PTokenNotDeployed", inputs: [] }, + { type: "error", name: "ProofInvalidOrExpired", inputs: [] }, + { type: "error", name: "RewardsNotLive", inputs: [] }, + { type: "error", name: "UUPSUnauthorizedCallContext", inputs: [] }, + { + type: "error", + name: "UUPSUnsupportedProxiableUUID", + inputs: [{ name: "slot", type: "bytes32", internalType: "bytes32" }], + }, +]; diff --git a/js-scripts/generateRedemptionRights/countpoints.js b/js-scripts/generateRedemptionRights/countpoints.js new file mode 100644 index 0000000..772ba72 --- /dev/null +++ b/js-scripts/generateRedemptionRights/countpoints.js @@ -0,0 +1,24 @@ +import { readFileSync } from "fs"; + +const rewards = 132431200000000000000000 / 1e18; + +const data = JSON.parse( + readFileSync( + `${process.cwd()}/js-scripts/generateRedemptionRights/last-alpha-distribution.json` + ) +); + +const kpSatId = + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453"; + +const pTokens = data.pTokens; + +let total = 0; +for (const user in pTokens) { + console.log(pTokens[user][kpSatId]); + total += pTokens[user][kpSatId].accumulatingPoints; +} +console.log(total); +const totalPTokens = total / 1e18; +const rewardsPerPToken = rewards / totalPTokens; +console.log(rewardsPerPToken * 2); diff --git a/js-scripts/generateRedemptionRights/index.ts b/js-scripts/generateRedemptionRights/index.ts new file mode 100644 index 0000000..2ff8d10 --- /dev/null +++ b/js-scripts/generateRedemptionRights/index.ts @@ -0,0 +1,396 @@ +import * as fs from "fs"; +import * as dotenv from "dotenv"; +import { + keccak256, + encodePacked, + createPublicClient, + http, + parseAbiItem, + Address, + zeroAddress, + PublicClient, + getContract, + erc20Abi, +} from "viem"; +import { mainnet } from "viem/chains"; +import { MerkleTree } from "merkletreejs"; +import { pointTokenVaultABI } from "./abis/point-token-vault.ts"; +import { LosslessNumber, parse, stringify } from "lossless-json"; + +// Types +type PointsBalance = Map<`0x${string}`, bigint>; +type RedemptionRightsMap = Map; + +interface AlphaDistributionData { + pTokens: { + [address: Address]: { + [pointsId: `0x${string}`]: { + accumulatingPoints: LosslessNumber; + }; + }; + }; +} + +interface MerklizedData { + root: `0x${string}`; + redemptionRights: { + [address: Address]: { + [pointsId: `0x${string}`]: { + amount: string; + proof: `0x${string}`[]; + }; + }; + }; + pTokens: { + [address: Address]: { + [pointsId: `0x${string}`]: { + amount: string; + proof: `0x${string}`[]; + }; + }; + }; +} + +interface PTokenSnapshot { + address: Address; + blockNumber: string; + balances: { + [address: string]: string; + }; +} + +// Overrides +const UNI_POOL_OVERRIDES = { + "0x597a1b0515bbeEe6796B89a6f403c3fD41BB626C": { + "0x24C694d193B19119bcDea9D40a3b0bfaFb281E6D": "6487631537430741114", + "0x44Cb2d713BDa3858001f038645fD05E23E5DE03D": "27597767454066598826095", + }, +}; + +// Config +dotenv.config({ path: "./js-scripts/generateRedemptionRights/.env" }); +const config = { + rpcUrl: process.env.MAINNET_RPC_URL, + pTokenAddresses: (process.env.PTOKEN_ADDRESSES as string)?.split( + "," + ) as Address[], + pointsIds: (process.env.POINTS_IDS as string)?.split(",") as `0x${string}`[], + rewardsPerPToken: (process.env.REWARDS_PER_P_TOKEN as string)?.split( + "," + ) as string[], + vestSizes: (process.env.VEST_SIZE as string)?.split(",") as string[], + pointTokenVaultAddress: process.env.POINT_TOKEN_VAULT_ADDRESS as Address, +}; + +// Core functions +async function calculateRedemptionRights( + client: PublicClient, + iteration: number, + previousDistribution: AlphaDistributionData +): Promise<[Map, PTokenSnapshot]> { + const pTokenAddress = config.pTokenAddresses[iteration]; + const rewardsMultiplier = config.rewardsPerPToken[iteration]; + const pointsId = config.pointsIds[iteration]; + const vestSize = config.vestSizes[iteration]; + + const redemptionRights = new Map(); + const rewardsMultiplierBigInt = BigInt( + Number(rewardsMultiplier) * Number(vestSize) + ); + const blockNumber = await client.getBlockNumber(); + + const logs = await client.getLogs({ + address: pTokenAddress, + event: parseAbiItem( + "event Transfer(address indexed from, address indexed to, uint256)" + ), + fromBlock: 0n, + toBlock: "latest", + }); + + // Track raw pToken balances separately + const pTokenBalances = new Map(); + + for (const log of logs) { + const [from, to, value] = log.args as [Address, Address, bigint]; + + // Update redemption rights + if (from !== zeroAddress) { + redemptionRights.set( + from, + (redemptionRights.get(from) || 0n) - + (value * rewardsMultiplierBigInt) / BigInt(1e18) + ); + pTokenBalances.set(from, (pTokenBalances.get(from) || 0n) - value); + } + if (to !== zeroAddress) { + redemptionRights.set( + to, + (redemptionRights.get(to) || 0n) + + (value * rewardsMultiplierBigInt) / BigInt(1e18) + ); + pTokenBalances.set(to, (pTokenBalances.get(to) || 0n) + value); + } + } + + // Apply UNI pool overrides after processing all transfers + for (const [poolAddress, redistributions] of Object.entries( + UNI_POOL_OVERRIDES + )) { + const poolBalance = pTokenBalances.get(poolAddress as Address) || 0n; + if (poolBalance > 0n) { + // Remove balance from pool + pTokenBalances.set(poolAddress as Address, 0n); + redemptionRights.set(poolAddress as Address, 0n); + + // Redistribute to specified addresses + for (const [recipient, amount] of Object.entries(redistributions)) { + const recipientAddress = recipient as Address; + const overrideAmount = BigInt(amount); + + pTokenBalances.set( + recipientAddress, + (pTokenBalances.get(recipientAddress) || 0n) + overrideAmount + ); + + redemptionRights.set( + recipientAddress, + (redemptionRights.get(recipientAddress) || 0n) + + (overrideAmount * rewardsMultiplierBigInt) / BigInt(1e18) + ); + } + } + } + + // Add unclaimed pToken balances + const pointTokenVault = getContract({ + address: config.pointTokenVaultAddress, + abi: pointTokenVaultABI, + client, + }); + for (const [userAddress, addressPointsData] of Object.entries( + previousDistribution.pTokens + )) { + const { accumulatingPoints } = addressPointsData[pointsId]; + + const claimedPtokens = (await pointTokenVault.read.claimedPTokens([ + userAddress, + pointsId, + ])) as bigint; + + const unclaimedPtokens = + BigInt(accumulatingPoints.toString()) - claimedPtokens; + + if (unclaimedPtokens > 0n) { + pTokenBalances.set( + userAddress as Address, + (pTokenBalances.get(userAddress as Address) || 0n) + unclaimedPtokens + ); + + redemptionRights.set( + userAddress as Address, + (redemptionRights.get(userAddress as Address) || 0n) + + (unclaimedPtokens * rewardsMultiplierBigInt) / BigInt(1e18) + ); + } + } + + // Create snapshot object + const snapshot: PTokenSnapshot = { + address: pTokenAddress, + blockNumber: blockNumber.toString(), + balances: Object.fromEntries( + Array.from(pTokenBalances.entries()) + .filter(([_, balance]) => balance > 0n) + .map(([addr, balance]) => [addr, balance.toString()]) + ), + }; + + return [ + new Map( + Array.from(redemptionRights.entries()).filter( + ([_, balance]) => balance > 0n + ) + ), + snapshot, + ]; +} + +function generateMerkleData( + allRedemptionRights: RedemptionRightsMap, + previousDistribution: AlphaDistributionData +): MerklizedData { + const prefix = keccak256(encodePacked(["string"], ["REDEMPTION_RIGHTS"])); + + // Generate redemption rights leaves + const rightsLeaves = Array.from(allRedemptionRights.entries()).flatMap( + ([address, balances]) => + Array.from(balances.entries()).map(([pointsId, balance]) => + keccak256( + encodePacked( + ["bytes32", "address", "bytes32", "uint256"], + [prefix, address, pointsId, balance] + ) + ) + ) + ); + + // Generate pTokens leaves + const pTokenLeaves = Object.entries(previousDistribution.pTokens).flatMap( + ([address, pointsData]) => + Object.entries(pointsData).map(([pointsId, data]) => + keccak256( + encodePacked( + ["address", "bytes32", "uint256"], + [ + address as Address, + pointsId as `0x${string}`, + BigInt(data.accumulatingPoints.toString()), + ] + ) + ) + ) + ); + + // Build tree + const tree = new MerkleTree( + [...rightsLeaves, ...pTokenLeaves].sort(), + keccak256, + { sortPairs: true } + ); + + return { + root: tree.getHexRoot() as `0x${string}`, + redemptionRights: Object.fromEntries( + Array.from(allRedemptionRights.entries()).map(([address, balances]) => [ + address, + Object.fromEntries( + Array.from(balances.entries()).map(([pointsId, balance]) => [ + pointsId, + { + amount: balance.toString(), + proof: tree.getHexProof( + keccak256( + encodePacked( + ["bytes32", "address", "bytes32", "uint256"], + [prefix, address, pointsId, balance] + ) + ) + ) as `0x${string}`[], + }, + ]) + ), + ]) + ), + pTokens: Object.fromEntries( + Object.entries(previousDistribution.pTokens).map( + ([address, pointsData]) => [ + address, + Object.fromEntries( + Object.entries(pointsData).map(([pointsId, data]) => [ + pointsId, + { + amount: data.accumulatingPoints.toString(), + proof: tree.getHexProof( + keccak256( + encodePacked( + ["address", "bytes32", "uint256"], + [ + address as Address, + pointsId as `0x${string}`, + BigInt(data.accumulatingPoints.toString()), + ] + ) + ) + ) as `0x${string}`[], + }, + ]) + ), + ] + ) + ), + }; +} + +// Main execution +async function generateMerkleTree(): Promise { + const client = createPublicClient({ + chain: mainnet, + transport: http(config.rpcUrl), + }); + + // Validate config + if ( + !config.rpcUrl || + !config.pTokenAddresses.length || + !config.pointsIds.length || + config.pTokenAddresses.length !== config.pointsIds.length + ) { + throw new Error("Invalid configuration"); + } + + console.log(`Processing at block #${await client.getBlockNumber()}`); + + const previousDistribution = parse( + fs.readFileSync( + "js-scripts/generateRedemptionRights/last-alpha-distribution.json", + "utf8" + ) + ) as AlphaDistributionData; + + // Calculate rights for each token + const allRedemptionRights: RedemptionRightsMap = new Map(); + const snapshots: { [address: string]: PTokenSnapshot } = {}; + + for (let i = 0; i < config.pTokenAddresses.length; i++) { + const [rights, snapshot] = await calculateRedemptionRights( + client, + i, + previousDistribution + ); + snapshots[config.pTokenAddresses[i]] = snapshot; + + for (const [addr, balance] of rights.entries()) { + if (!allRedemptionRights.has(addr)) + allRedemptionRights.set(addr, new Map()); + allRedemptionRights.get(addr)!.set(config.pointsIds[i], balance); + } + } + + // Save individual snapshots for each pToken + for (const [pTokenAddress, snapshot] of Object.entries(snapshots)) { + const pTokenContract = getContract({ + address: pTokenAddress as Address, + abi: erc20Abi, + client, + }); + + const symbol = await pTokenContract.read.symbol(); + const fileName = `ptoken-snapshot-${symbol.toLowerCase()}.json`; + + // Add address to the snapshot data + const snapshotWithAddress: PTokenSnapshot = { + ...snapshot, + address: pTokenAddress as Address, + }; + + fs.writeFileSync( + `js-scripts/generateRedemptionRights/out/${fileName}`, + JSON.stringify(snapshotWithAddress, null, 2) + ); + } + + // Generate merkle data + const merklizedData = generateMerkleData( + allRedemptionRights, + previousDistribution + ); + + console.log("Merkle root:", merklizedData.root); + fs.writeFileSync( + "js-scripts/generateRedemptionRights/out/merged-distribution.json", + JSON.stringify(merklizedData, null, 2) + ); +} + +generateMerkleTree().catch(console.error); diff --git a/js-scripts/generateRedemptionRights/last-alpha-distribution.json b/js-scripts/generateRedemptionRights/last-alpha-distribution.json new file mode 100644 index 0000000..d136d98 --- /dev/null +++ b/js-scripts/generateRedemptionRights/last-alpha-distribution.json @@ -0,0 +1,201 @@ +{ + "root": "0x97f82b0ee5efab39ef6c19fe98d952ec782980ac43ded92eb91e2faa3aeaa401", + "pTokens": { + "0x25E426b153e74Ab36b2685c3A464272De60888Ae": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 66498274627767680425, + "accumulatingPoints": 833020026897918484874, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 232746777808705188, + "accumulatingPoints": 4426555656895776038 + }, + "0x40357b9f22B4DfF0Bf56A90661b8eC106C259d29": { + "newPoints": 66265527849958975237, + "accumulatingPoints": 828593471241022708836 + } + }, + "proof": [ + "0x991fd8976022911aeb40e40bcb5754f9529f2080710f7ec1db8ace85c4f7b7f8", + "0x5e6196d0d89859247b3b230f0e6dab21f74e08cf42053a8c1e0543830ebc546c", + "0x20271d72a5dba7cd6a536181de172105226f3cff0a42bc7a2dc91d8a902baae5", + "0x9fd5c3acd497da629b3a4513eb0924ebb12244b90781194c0f1d092777f14bc3" + ] + }, + "0x1552756d70656c20506f696e743a205a69726375697408705a49524355495400": { + "newPoints": 0, + "accumulatingPoints": 335440188667996950000, + "breakdown": { + "0x40357b9f22B4DfF0Bf56A90661b8eC106C259d29": { + "newPoints": 0, + "accumulatingPoints": 335440188667996950000 + } + }, + "proof": [ + "0xa11fb0c1a4d796bcb6fa408ad7fead1f27c139ee194686098410c137f2d5d224", + "0x5e6196d0d89859247b3b230f0e6dab21f74e08cf42053a8c1e0543830ebc546c", + "0x20271d72a5dba7cd6a536181de172105226f3cff0a42bc7a2dc91d8a902baae5", + "0x9fd5c3acd497da629b3a4513eb0924ebb12244b90781194c0f1d092777f14bc3" + ] + } + }, + "0x24C694d193B19119bcDea9D40a3b0bfaFb281E6D": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 7930031840109298837, + "accumulatingPoints": 152407798291890457882, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 7930031840109298837, + "accumulatingPoints": 152407798291890457882 + } + }, + "proof": [ + "0x22bd0a3dd00ce6d39746f618e1314a076f69dc34b7f13b915a642b5600e25305", + "0xec7d2e07249c1b63f1cbafebe4b19b2a4aede14f630e574c65700ea8211055d9", + "0x20271d72a5dba7cd6a536181de172105226f3cff0a42bc7a2dc91d8a902baae5", + "0x9fd5c3acd497da629b3a4513eb0924ebb12244b90781194c0f1d092777f14bc3" + ] + } + }, + "0xe2C3445a84de723Ef4425922165a58D22AD06e33": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 6827238815722018869, + "accumulatingPoints": 131187337543613434191, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 6827238815722018869, + "accumulatingPoints": 131187337543613434191 + } + }, + "proof": [ + "0x7c1140f479d8f8e1295f0da50f5554de0c77b7b73783022f63b840e186a69c3d", + "0xec7d2e07249c1b63f1cbafebe4b19b2a4aede14f630e574c65700ea8211055d9", + "0x20271d72a5dba7cd6a536181de172105226f3cff0a42bc7a2dc91d8a902baae5", + "0x9fd5c3acd497da629b3a4513eb0924ebb12244b90781194c0f1d092777f14bc3" + ] + } + }, + "0xD6633c1382896079D3576eC43519d844a8C80B56": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 3879112963478419812, + "accumulatingPoints": 73286503362495655536, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 3879112963478419812, + "accumulatingPoints": 73286503362495655536 + } + }, + "proof": [ + "0xb605c6d24f4591b726ca75a2244f789388c19ffebedd76217fe0eda994f0a8a4", + "0x743739b6e27a07d7a5886e91fa6165fa506e429f2835baf69d8460908941415a", + "0x5cfaa3d3f456943535a68a9513a8cf801c67279e8ac417ba63e383e4611adc57", + "0x9fd5c3acd497da629b3a4513eb0924ebb12244b90781194c0f1d092777f14bc3" + ] + } + }, + "0x028CC8E3Ff248Dc59052eaAD2a1e749F3B835B99": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 0, + "accumulatingPoints": 4977606283426392328730, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 0, + "accumulatingPoints": 4977606283426392328730 + } + }, + "proof": [ + "0xdc6743cb29d00ac8467f33ac244256f40e5d7fc8e8813cfc8d3c0ab87f1df4d2", + "0x743739b6e27a07d7a5886e91fa6165fa506e429f2835baf69d8460908941415a", + "0x5cfaa3d3f456943535a68a9513a8cf801c67279e8ac417ba63e383e4611adc57", + "0x9fd5c3acd497da629b3a4513eb0924ebb12244b90781194c0f1d092777f14bc3" + ] + } + }, + "0x6CD72B1E6E300340A48943d6aF34EF5AE07D3577": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 155164518539136792484, + "accumulatingPoints": 2830357527081490335359, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 155164518539136792484, + "accumulatingPoints": 2830357527081490335359 + } + }, + "proof": [ + "0x191a3f5a1c7f9b1657f56cf44eb79a72b47ad4be40fae5ced80af9e38731e10c", + "0x2edc92e0f7721f84ac287a3d576011980a1c14d2055e9471d23704d678db8f27", + "0x5cfaa3d3f456943535a68a9513a8cf801c67279e8ac417ba63e383e4611adc57", + "0x9fd5c3acd497da629b3a4513eb0924ebb12244b90781194c0f1d092777f14bc3" + ] + } + }, + "0xAF9e4E01525C4856E00Cb0F363AFc34E7decD6a7": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 28652027175284595239052, + "accumulatingPoints": 522530241238727636619443, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 28652027175284595239052, + "accumulatingPoints": 522530241238727636619443 + } + }, + "proof": [ + "0x6a69b863aea1e9a735f460a6fb449a28b7398f958c4792872d7764700936b79d", + "0x2edc92e0f7721f84ac287a3d576011980a1c14d2055e9471d23704d678db8f27", + "0x5cfaa3d3f456943535a68a9513a8cf801c67279e8ac417ba63e383e4611adc57", + "0x9fd5c3acd497da629b3a4513eb0924ebb12244b90781194c0f1d092777f14bc3" + ] + } + }, + "0x0e7518B332F469a6A2F59E690F225cef5157cca9": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 15878352062127404025676, + "accumulatingPoints": 262106044120029423561824, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 15878352062127404025676, + "accumulatingPoints": 262106044120029423561824 + } + }, + "proof": [ + "0x8b788cab342842ae529d8efac9659e1af9367270c13caaf4c8b5ef4c67a51402", + "0x6258fb3ee01fe8edb76a1ee2cb317cd32b8464c63e31903826acd02863982f31", + "0x13b53859bd6223b750a1ee9cd1c58ef7dad44cf4c74daee9c688e5fa65e5fca3" + ] + } + }, + "0x347ab2e403710583Ade28Ef0871e73581599C8C8": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 89545954046664994040243, + "accumulatingPoints": 988835303595225079157382, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 89545954046664994040243, + "accumulatingPoints": 988835303595225079157382 + } + }, + "proof": [ + "0x4e0230e7a7546148f373efe52256490c04ea0019e199f2256a375e75cf2b6b96", + "0x6258fb3ee01fe8edb76a1ee2cb317cd32b8464c63e31903826acd02863982f31", + "0x13b53859bd6223b750a1ee9cd1c58ef7dad44cf4c74daee9c688e5fa65e5fca3" + ] + } + }, + "0x1d848bf0dcF1b48f5621c37d062f2696D9d71AC4": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "newPoints": 155164518539136792484597, + "accumulatingPoints": 2396414216569414059964695, + "breakdown": { + "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07": { + "newPoints": 155164518539136792484597, + "accumulatingPoints": 2396414216569414059964695 + } + }, + "proof": [ + "0x55efa11ff2efbae089ab7fa8e3cd7080098947f5727af0e0c2b4d4de47467a4a", + "0x13b53859bd6223b750a1ee9cd1c58ef7dad44cf4c74daee9c688e5fa65e5fca3" + ] + } + } + } +} diff --git a/js-scripts/generateRedemptionRights/out/merged-distribution.json b/js-scripts/generateRedemptionRights/out/merged-distribution.json new file mode 100644 index 0000000..5fc2bce --- /dev/null +++ b/js-scripts/generateRedemptionRights/out/merged-distribution.json @@ -0,0 +1,261 @@ +{ + "root": "0xa1c76e2c6f7ac8300b288ff758b8a83c4a19e12780ca7ac5f61182f64ef8edf6", + "redemptionRights": { + "0x25E426b153e74Ab36b2685c3A464272De60888Ae": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "26396311093240867247", + "proof": [ + "0x4e0230e7a7546148f373efe52256490c04ea0019e199f2256a375e75cf2b6b96", + "0xfaca43636023a73bf06295aa693c262efe0bb3231357a68b8ad7eec7e901c8ef", + "0x03c4c7f992659d2c405eb95248d21dfd7f66c7bdef49d9d33cb97b0b5d35c37a", + "0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0xAF9e4E01525C4856E00Cb0F363AFc34E7decD6a7": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "38340222707708650495326", + "proof": [ + "0x217b3e35b22b6bd3732704009f72c0e75d295787739b31e22f4eceb2aadb3b37", + "0x25adc46cf5c2f7012dc1c4e2f45ed46fe6b0937d4f45b69007541a847eac9dd4", + "0x4439e29397d45eb830afb7d52dfc37d8972adbe4eefd9df3c64126153422857d", + "0x185833bfc67ae1d1e405a88dfe822e59dcaec373305b2e76c80db6a7091905d7", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0x028CC8E3Ff248Dc59052eaAD2a1e749F3B835B99": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "14223655008932463486", + "proof": [ + "0x22bd0a3dd00ce6d39746f618e1314a076f69dc34b7f13b915a642b5600e25305", + "0xeda910c5f504e63aafb87a8104f5af92636f2c57e1061ff3e9b4aa12a5544172", + "0x0a0e4a23e7565c93ebd635c41c01005c5bf44908500e9820600784a695ad7768", + "0x185833bfc67ae1d1e405a88dfe822e59dcaec373305b2e76c80db6a7091905d7", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0x6CD72B1E6E300340A48943d6aF34EF5AE07D3577": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "89695639613423029375", + "proof": [ + "0xea937ecfc7483e67cfddb5b77c31285fbb7a1b617b616b0bfa2bc10ecf2632dd", + "0x61be1ce59f6e838eae374c35dc5a4d0d596bd8a909863cc6a052608df95bd026", + "0x68ab2a2acfc0717fe2f1a2d72d08932d87ba90aa7c673fc5f7f3d24a75cfa445" + ] + } + }, + "0x1d848bf0dcF1b48f5621c37d062f2696D9d71AC4": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "72553382607912658280333", + "proof": [ + "0xdc6743cb29d00ac8467f33ac244256f40e5d7fc8e8813cfc8d3c0ab87f1df4d2", + "0xc6f15a7cbd986873c6b761e81c98ee8ac4afd1c9885b7d8e0ae4de752040ab12", + "0x9b0c4a7e606c4fd8857fd20d901299bfc87aad79ceaaef4ec5961f5c943e92c1", + "0x68ab2a2acfc0717fe2f1a2d72d08932d87ba90aa7c673fc5f7f3d24a75cfa445" + ] + } + }, + "0x76DB9edf1451933711fc0A0c622E013ebD229EaB": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "14324115790279497348417", + "proof": [ + "0x4bf5c095f95a6461e2f3eb39058850cd65b02d1014ee5a1a12f85d088b5f0e80", + "0xca9b6a744ecb364652014258339103f4e460257a674bf19262c9f824dd17d86e", + "0x0a0e4a23e7565c93ebd635c41c01005c5bf44908500e9820600784a695ad7768", + "0x185833bfc67ae1d1e405a88dfe822e59dcaec373305b2e76c80db6a7091905d7", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0xB6462B67fe692223DFFb61C8DC8Ad080CBa180Cc": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "6197058964511974341082", + "proof": [ + "0x4bfe5e81e4d249db669aeb65109e2409cad5d9d0e4ebf9e58765b431d601b4b2", + "0xca9b6a744ecb364652014258339103f4e460257a674bf19262c9f824dd17d86e", + "0x0a0e4a23e7565c93ebd635c41c01005c5bf44908500e9820600784a695ad7768", + "0x185833bfc67ae1d1e405a88dfe822e59dcaec373305b2e76c80db6a7091905d7", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0x24C694d193B19119bcDea9D40a3b0bfaFb281E6D": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "5035486532645526909", + "proof": [ + "0x191a3f5a1c7f9b1657f56cf44eb79a72b47ad4be40fae5ced80af9e38731e10c", + "0x72173d6e267f2a29d16a34509f44aac2ad022a7f60873b53300a93802c340804", + "0x4439e29397d45eb830afb7d52dfc37d8972adbe4eefd9df3c64126153422857d", + "0x185833bfc67ae1d1e405a88dfe822e59dcaec373305b2e76c80db6a7091905d7", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0x44Cb2d713BDa3858001f038645fD05E23E5DE03D": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "874588945039572133000", + "proof": [ + "0x204bc5b06a6b2d4f2756538646d437d08bd90b5261d351bbdb3f1a7b8e4257c3", + "0x25adc46cf5c2f7012dc1c4e2f45ed46fe6b0937d4f45b69007541a847eac9dd4", + "0x4439e29397d45eb830afb7d52dfc37d8972adbe4eefd9df3c64126153422857d", + "0x185833bfc67ae1d1e405a88dfe822e59dcaec373305b2e76c80db6a7091905d7", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0xe2C3445a84de723Ef4425922165a58D22AD06e33": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "4157401330951234038", + "proof": [ + "0xf32553bd8ea432642fd95f93d04661d727c3495c97e1ea55841dda3ea97bf75d", + "0x61be1ce59f6e838eae374c35dc5a4d0d596bd8a909863cc6a052608df95bd026", + "0x68ab2a2acfc0717fe2f1a2d72d08932d87ba90aa7c673fc5f7f3d24a75cfa445" + ] + } + }, + "0xD6633c1382896079D3576eC43519d844a8C80B56": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "2322490968449677698", + "proof": [ + "0x7c1140f479d8f8e1295f0da50f5554de0c77b7b73783022f63b840e186a69c3d", + "0x7633b40f0b9d031a2504b9bd6e72e8a6d60f27109c35e8e3a1e5a9588b288124", + "0x1825942bcf756f17362686c29e669214db7df52b3c86e78654592b95c5b3a76e", + "0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + } + }, + "pTokens": { + "0x25E426b153e74Ab36b2685c3A464272De60888Ae": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "833020026897918484874", + "proof": [ + "0xb605c6d24f4591b726ca75a2244f789388c19ffebedd76217fe0eda994f0a8a4", + "0x6357299d7699ba4e80f928ce033e518301b337cced573cc09f09339befc0c120", + "0x9b0c4a7e606c4fd8857fd20d901299bfc87aad79ceaaef4ec5961f5c943e92c1", + "0x68ab2a2acfc0717fe2f1a2d72d08932d87ba90aa7c673fc5f7f3d24a75cfa445" + ] + }, + "0x1552756d70656c20506f696e743a205a69726375697408705a49524355495400": { + "amount": "335440188667996950000", + "proof": [ + "0x8b788cab342842ae529d8efac9659e1af9367270c13caaf4c8b5ef4c67a51402", + "0x9ae95d5e291ec3487c512e2d0067797e0f1b6a1965fcea0e0b75065d8b869d14", + "0x1825942bcf756f17362686c29e669214db7df52b3c86e78654592b95c5b3a76e", + "0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0x24C694d193B19119bcDea9D40a3b0bfaFb281E6D": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "152407798291890457882", + "proof": [ + "0x7b50ab37696a9b8976ea0f3028d4d126c49cf1b24c3721446bd284664c4c17be", + "0x7633b40f0b9d031a2504b9bd6e72e8a6d60f27109c35e8e3a1e5a9588b288124", + "0x1825942bcf756f17362686c29e669214db7df52b3c86e78654592b95c5b3a76e", + "0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0xe2C3445a84de723Ef4425922165a58D22AD06e33": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "131187337543613434191", + "proof": [ + "0x2b472340f06e2903f4bad87569e59ad8c2748f37d874e860182a7b23b63bf187", + "0xeda910c5f504e63aafb87a8104f5af92636f2c57e1061ff3e9b4aa12a5544172", + "0x0a0e4a23e7565c93ebd635c41c01005c5bf44908500e9820600784a695ad7768", + "0x185833bfc67ae1d1e405a88dfe822e59dcaec373305b2e76c80db6a7091905d7", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0xD6633c1382896079D3576eC43519d844a8C80B56": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "73286503362495655536", + "proof": [ + "0xc5a3de3c602ab30847fc470e18dc68519e5d2139992db65ec4dd75e0146df4c8", + "0xc6f15a7cbd986873c6b761e81c98ee8ac4afd1c9885b7d8e0ae4de752040ab12", + "0x9b0c4a7e606c4fd8857fd20d901299bfc87aad79ceaaef4ec5961f5c943e92c1", + "0x68ab2a2acfc0717fe2f1a2d72d08932d87ba90aa7c673fc5f7f3d24a75cfa445" + ] + } + }, + "0x028CC8E3Ff248Dc59052eaAD2a1e749F3B835B99": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "4977606283426392328730", + "proof": [ + "0xa11fb0c1a4d796bcb6fa408ad7fead1f27c139ee194686098410c137f2d5d224", + "0x6357299d7699ba4e80f928ce033e518301b337cced573cc09f09339befc0c120", + "0x9b0c4a7e606c4fd8857fd20d901299bfc87aad79ceaaef4ec5961f5c943e92c1", + "0x68ab2a2acfc0717fe2f1a2d72d08932d87ba90aa7c673fc5f7f3d24a75cfa445" + ] + } + }, + "0x6CD72B1E6E300340A48943d6aF34EF5AE07D3577": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "2830357527081490335359", + "proof": [ + "0x6258fb3ee01fe8edb76a1ee2cb317cd32b8464c63e31903826acd02863982f31", + "0x6f209cf7bc61e5a8fcb44d39ea95351ae3989caaa2178e74ce62330ea0151fe2", + "0x03c4c7f992659d2c405eb95248d21dfd7f66c7bdef49d9d33cb97b0b5d35c37a", + "0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0xAF9e4E01525C4856E00Cb0F363AFc34E7decD6a7": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "522530241238727636619443", + "proof": [ + "0x05b5632fa9188d3d57e26410c16ba2974649803ace78e06da3f50ec9d64ebbb2", + "0x72173d6e267f2a29d16a34509f44aac2ad022a7f60873b53300a93802c340804", + "0x4439e29397d45eb830afb7d52dfc37d8972adbe4eefd9df3c64126153422857d", + "0x185833bfc67ae1d1e405a88dfe822e59dcaec373305b2e76c80db6a7091905d7", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0x0e7518B332F469a6A2F59E690F225cef5157cca9": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "262106044120029423561824", + "proof": [ + "0x50aaf318ad53de9f666ad28cfe0153009fc3a94e2fa40f6ae674f9e6fd3e878c", + "0xfaca43636023a73bf06295aa693c262efe0bb3231357a68b8ad7eec7e901c8ef", + "0x03c4c7f992659d2c405eb95248d21dfd7f66c7bdef49d9d33cb97b0b5d35c37a", + "0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0x347ab2e403710583Ade28Ef0871e73581599C8C8": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "988835303595225079157382", + "proof": [ + "0x991fd8976022911aeb40e40bcb5754f9529f2080710f7ec1db8ace85c4f7b7f8", + "0x9ae95d5e291ec3487c512e2d0067797e0f1b6a1965fcea0e0b75065d8b869d14", + "0x1825942bcf756f17362686c29e669214db7df52b3c86e78654592b95c5b3a76e", + "0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + }, + "0x1d848bf0dcF1b48f5621c37d062f2696D9d71AC4": { + "0x1852756d70656c206b506f696e743a20457468656e61205332066b7053415453": { + "amount": "2396414216569414059964695", + "proof": [ + "0x6a69b863aea1e9a735f460a6fb449a28b7398f958c4792872d7764700936b79d", + "0x6f209cf7bc61e5a8fcb44d39ea95351ae3989caaa2178e74ce62330ea0151fe2", + "0x03c4c7f992659d2c405eb95248d21dfd7f66c7bdef49d9d33cb97b0b5d35c37a", + "0x617d803c581341b5720c7932932ca45ebfb90e87a122f801b0d5fe53b747db51", + "0x620f05d3b25d35da47076de4dceb31f95567ff863138ae7d1fe416ea0bc2ff41" + ] + } + } + } +} \ No newline at end of file diff --git a/js-scripts/generateRedemptionRights/out/ptoken-snapshot-kpsats.json b/js-scripts/generateRedemptionRights/out/ptoken-snapshot-kpsats.json new file mode 100644 index 0000000..a7d9c46 --- /dev/null +++ b/js-scripts/generateRedemptionRights/out/ptoken-snapshot-kpsats.json @@ -0,0 +1,17 @@ +{ + "address": "0xdFa21ceC8A46386F5d36F4b07E18BcCcA59f425B", + "blockNumber": "21149351", + "balances": { + "0x25E426b153e74Ab36b2685c3A464272De60888Ae": "832939015897918484874", + "0xAF9e4E01525C4856E00Cb0F363AFc34E7decD6a7": "1209830694094345523934847", + "0x028CC8E3Ff248Dc59052eaAD2a1e749F3B835B99": "448829276324349797275", + "0x6CD72B1E6E300340A48943d6aF34EF5AE07D3577": "2830357527081490335359", + "0x1d848bf0dcF1b48f5621c37d062f2696D9d71AC4": "2289431386682455596719703", + "0x76DB9edf1451933711fc0A0c622E013ebD229EaB": "451999329293340648396874", + "0xB6462B67fe692223DFFb61C8DC8Ad080CBa180Cc": "195548998385752443216151", + "0x24C694d193B19119bcDea9D40a3b0bfaFb281E6D": "158895429829321198996", + "0x44Cb2d713BDa3858001f038645fD05E23E5DE03D": "27597767454066598826095", + "0xe2C3445a84de723Ef4425922165a58D22AD06e33": "131187337543613434191", + "0xD6633c1382896079D3576eC43519d844a8C80B56": "73286503362495655536" + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..d13c087 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "point-tokenization-vault-scripts", + "module": "index.ts", + "type": "module", + "scripts": { + "generate-merkle-tree": "bun run js-scripts/generateRedemptionRights/index.ts" + }, + "devDependencies": { + "bun-types": "latest" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "dotenv": "^16.3.1", + "lossless-json": "^4.0.2", + "merkletreejs": "^0.4.0", + "viem": "^2.21.25" + } +}