diff --git a/bun.lockb b/bun.lockb index 412161c..506cd16 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 715b416..c7b2560 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "fork": "bash helpers/fork.sh", "foundry:compile": "forge build --optimize --optimizer-runs 1000", "foundry:coverage": "forge coverage --ir-minimum --report lcov && yarn lcov:clean && yarn lcov:generate-html", - "foundry:script": "forge script -vvvv", + "foundry:script": "forge script Claim --rpc-url celo --sender 0xbDE3b37848dE5d26717fe27b4489E130E8d40e77 -vvvv", + "foundry:broadcast": "forge script CreateCampaigns --rpc-url gnosis --sender 0xa9bbbDDe822789F123667044443dc7001fb43C01 --broadcast --verify -i 1 -vvvv", "foundry:deploy": "source .env && forge script --broadcast --verify -vvvv", "foundry:gas": "forge test --gas-report", "foundry:run": "docker run -it --rm -v $(pwd):/app -w /app ghcr.io/foundry-rs/foundry sh", @@ -30,7 +31,7 @@ "url": "https://github.com/AngleProtocol/merkl-contracts/issues" }, "devDependencies": { - "@angleprotocol/sdk": "2.38.4", + "@angleprotocol/sdk": "2.41.0", "@openzeppelin/contracts": "^4.9.0", "@openzeppelin/contracts-upgradeable": "4.9.0", "prettier": "^2.0.0", @@ -42,4 +43,4 @@ "utils": "github:AngleProtocol/utils" }, "dependencies": {} -} +} \ No newline at end of file diff --git a/scripts/DistributionCreator.s.sol b/scripts/DistributionCreator.s.sol index 69d3259..fb0468f 100644 --- a/scripts/DistributionCreator.s.sol +++ b/scripts/DistributionCreator.s.sol @@ -5,6 +5,7 @@ import { console } from "forge-std/console.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IERC20Metadata } from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol"; import { JsonReader } from "@utils/JsonReader.sol"; import { ContractType } from "@utils/Constants.sol"; @@ -171,8 +172,8 @@ contract RecoverFees is DistributionCreatorScript { contract SetUserFeeRebate is DistributionCreatorScript { function run() external { // MODIFY THESE VALUES TO SET YOUR DESIRED USER AND REBATE - address user = address(0); - uint256 rebate = 0; + address user = address(0x59A1A709c84C125F135C126ac46bE2A11b6f1bA4); + uint256 rebate = 250_000_000; _run(user, rebate); } @@ -198,8 +199,8 @@ contract SetRewardTokenMinAmounts is DistributionCreatorScript { // MODIFY THESE VALUES TO SET YOUR DESIRED TOKENS AND AMOUNTS address[] memory tokens = new address[](1); uint256[] memory amounts = new uint256[](1); - tokens[0] = 0x56fA5F7BF457454Be33D8B978C86A5f5B9DD84C2; - amounts[0] = 3 * 10 ** 17; + tokens[0] = 0x657d9ABA1DBb59e53f9F3eCAA878447dCfC96dCb; + amounts[0] = 0.001 ether; _run(tokens, amounts); } @@ -347,16 +348,108 @@ contract Sign is DistributionCreatorScript { // )" contract CreateCampaign is DistributionCreatorScript { function run() external broadcast { + bytes memory campaignData; // MODIFY THESE VALUES TO SET YOUR DESIRED CAMPAIGN PARAMETERS + // address targetToken = address(0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba); + // uint32 campaignType = 22; + // uint32 subCampaignType = 0; + // uint256 tokenId = 0; + // address[] memory whitelist = new address[](0); + // address[] memory blacklist = new address[](0); + // string memory url = "https://app.hyperdrive.box/market/100/0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba"; + // bytes[] memory hooks = new bytes[](0); + // string memory apr = "1"; + // bool targetTokenPricing = true; + // bool rewardTokenPricing = false; + // bytes memory campaignData = abi.encode( + // targetToken, + // subCampaignType, + // tokenId, + // whitelist, + // blacklist, + // url, + // hooks, + // apr, + // targetTokenPricing, + // rewardTokenPricing + // ); + // // + + // address targetToken = address(0x324395D5d835F84a02A75Aa26814f6fD22F25698); + // uint32 campaignType = 21; + // uint32 subCampaignType = 2; + // uint256 tokenId = 0; + // address[] memory whitelist = new address[](0); + // address[] memory blacklist = new address[](0); + // string memory url = "https://app.hyperdrive.box/market/1/0x324395D5d835F84a02A75Aa26814f6fD22F25698"; + // bytes[] memory hooks = new bytes[](0); + // campaignData = abi.encode(targetToken, subCampaignType, tokenId, whitelist, blacklist, url, hooks); + // address rewardToken = address(0x6B175474E89094C44Da98b954EedeAC495271d0F); + + address targetToken = address(0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba); + uint32 campaignType = 21; + uint32 subCampaignType = 2; + uint256 tokenId = 0; + address[] memory whitelist = new address[](0); + address[] memory blacklist = new address[](0); + string memory url = "https://app.hyperdrive.box/market/100/0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba"; + bytes[] memory hooks = new bytes[](0); + campaignData = abi.encode(targetToken, subCampaignType, tokenId, whitelist, blacklist, url, hooks); + address rewardToken = address(0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d); + + // + + // address targetToken = address(0x004626A008B1aCdC4c74ab51644093b155e59A23); + // uint32 campaignType = 1; + // address[] memory whitelist = new address[](0); + // address[] memory blacklist = new address[](0); + // string memory url = ""; + // bytes[] memory forwarders = new bytes[](0); + // bytes[] memory hooks = new bytes[](0); + // bytes memory campaignData = abi.encode(targetToken, whitelist, blacklist, url, forwarders, hooks, hex""); + + // uint32 campaignType = 26; + // { + // address baseToken = address(0); + // address quoteToken = 0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34; + // uint256 poolIdx = 420; + // bool isOutOfRangeIncentivized = false; + // uint32 weightFees = 2000; + // uint32 weightToken0 = 3000; + // uint32 weightToken1 = 5000; + // address[] memory whitelist = new address[](0); + // address[] memory blacklist = new address[](0); + // string + // memory url = "https://ambient.finance/trade/market/chain=0x783&tokenA=0x0000000000000000000000000000000000000000&tokenB=0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34"; + // bytes[] memory hooks = new bytes[](0); + // bytes[] memory forwarders = new bytes[](0); + // campaignData = abi.encode( + // baseToken, + // quoteToken, + // poolIdx, + // isOutOfRangeIncentivized, + // weightFees, + // weightToken0, + // weightToken1, + // whitelist, + // blacklist, + // url, + // forwarders, + // hooks, + // hex"" + // ); + // } + // END + CampaignParameters memory campaign = CampaignParameters({ campaignId: bytes32(0), creator: address(0), - rewardToken: address(0), - amount: 0, - campaignType: 0, - startTimestamp: uint32(block.timestamp), - duration: 7 days, - campaignData: "" + rewardToken: rewardToken, + amount: 5000 * 10 ** (IERC20Metadata(rewardToken).decimals()), + campaignType: campaignType, + startTimestamp: 1740063600, + duration: 30 days, + campaignData: campaignData }); _run(campaign); } @@ -368,7 +461,7 @@ contract CreateCampaign is DistributionCreatorScript { function _run(CampaignParameters memory campaign) internal { uint256 chainId = block.chainid; address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); - + IERC20(campaign.rewardToken).approve(creatorAddress, campaign.amount); bytes32 campaignId = DistributionCreator(creatorAddress).createCampaign(campaign); console.log("Campaign created with ID:", vm.toString(campaignId)); @@ -389,18 +482,96 @@ contract CreateCampaign is DistributionCreatorScript { // 0x000000000000000000000000ec883424202a963af2a3e59bccaa0219e88ab9db00000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000fa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ // )]" contract CreateCampaigns is DistributionCreatorScript { + // MODIFY THESE VALUES TO SET YOUR DESIRED CAMPAIGN INPUTS + mapping(uint256 => address[]) public targetTokens; + uint256 distributionChain = 100; + uint16[4] public chains = [1, 100, 8453, 59144]; + uint32 public campaignType = 22; + uint32 public subCampaignType = 2; + uint256 public tokenId = 0; + address[] public whitelist = new address[](0); + address[] public blacklist = new address[](0); + bytes[] public hooks = new bytes[](0); + string public apr = "1"; + bool public targetTokenPricing = true; + bool public rewardTokenPricing = false; + string public baseUrl = "https://app.hyperdrive.box/market/"; + address public rewardToken = 0x79385D4B4c531bBbDa25C4cFB749781Bd9E23039; + function run() external broadcast { // MODIFY THESE VALUES TO SET YOUR DESIRED CAMPAIGN INPUTS - CampaignInput[] memory inputs = new CampaignInput[](1); - inputs[0] = CampaignInput({ - creator: address(0), - rewardToken: address(0), - amount: 0, - campaignType: 0, - startTimestamp: uint32(block.timestamp), - duration: 7 days, - campaignData: "" - }); + uint256 amount = 1e5 * 10 ** (IERC20Metadata(rewardToken).decimals()); + targetTokens[1] = [ + 0xd7e470043241C10970953Bd8374ee6238e77D735 + // 0x324395D5d835F84a02A75Aa26814f6fD22F25698 + // 0xca5dB9Bb25D09A9bF3b22360Be3763b5f2d13589, + // 0xd41225855A5c5Ba1C672CcF4d72D1822a5686d30, + // 0xA29A771683b4857bBd16e1e4f27D5B6bfF53209B, + // 0x4c3054e51b46BE3191be9A05e73D73F1a2147854, + // 0x158Ed87D7E529CFE274f3036ade49975Fb10f030, + // 0xc8D47DE20F7053Cc02504600596A647A482Bbc46, + // 0x7548c4F665402BAb3a4298B88527824B7b18Fe27, + // 0xA4090183878d5B7b6Ad104863743dd7E58985321, + // 0x8f2AC104e07d94488a1821E5A393351FCA9239aa, + // 0x05b65FA90AD702e6Fd0C3Bd7c4c9C47BAB2BEa6b, + // 0xf1232Dc21eADAf503D82f1e1361CfF2BBf40394D + ]; + targetTokens[100] = [ + 0x2f840f1575EE77adAa43415Ac5953F7Db9F8C6ba, + 0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba, + 0x9248f874AaA2c53AD9324d7A2D033ea133443874 + ]; + // targetTokens[8453] = [ + // 0x2a1ca35Ded36C531F77c614b5AAA0d4F86edbB06, + // 0xFcdaF9A4A731C24ed2E1BFd6FA918d9CF7F50137, + // 0x1243C06146ACa2D4Aaf8F9860F6D8d59d636d46C, + // 0xceD9F810098f8329472AEFbaa1112534E96A5c7b, + // 0x9bAdB6A21FbA04EE94fde3E85F7d170E90394c89, + // 0xD9b66D9a819B36ECEfC26B043eF3B422d5A6123a, + // 0xdd8E1B14A04cbdD98dfcAF3F0Db84A80Bfb8FC25 + // ]; + // targetTokens[59144] = [0xB56e0Bf37c4747AbbC3aA9B8084B0d9b9A336777, 0x1cB0E96C07910fee9a22607bb9228c73848903a3]; + + CampaignInput[] memory inputs; + uint256 countInputs = 0; + { + uint256 numberCampaigns = 0; + for (uint256 i = 0; i < chains.length; i++) { + numberCampaigns += targetTokens[chains[i]].length; + } + inputs = new CampaignInput[](numberCampaigns); + } + for (uint256 i = 0; i < chains.length; i++) { + uint256 chainId = chains[i]; + string memory baseUrlChain = string.concat(baseUrl, vm.toString(chainId), "/"); + address[] memory tokens = targetTokens[chainId]; + for (uint256 j = 0; j < tokens.length; j++) { + bytes memory campaignData = abi.encode( + tokens[j], + subCampaignType, + tokenId, + whitelist, + blacklist, + string.concat(baseUrlChain, vm.toString(tokens[j])), + hooks, + apr, + targetTokenPricing, + rewardTokenPricing + ); + campaignData = abi.encode(uint32(chainId), campaignData); + campaignData = abi.encodePacked(campaignData, hex"c0c0c0c0"); + inputs[countInputs++] = CampaignInput({ + creator: address(0), + rewardToken: rewardToken, + amount: amount, + campaignType: campaignType, + startTimestamp: 1738368000, + duration: 90 days, + campaignData: campaignData + }); + } + } + _run(inputs); } @@ -409,8 +580,7 @@ contract CreateCampaigns is DistributionCreatorScript { } function _run(CampaignInput[] memory inputs) internal { - uint256 chainId = block.chainid; - address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); + address creatorAddress = readAddress(block.chainid, "Merkl.DistributionCreator"); DistributionCreator creator = DistributionCreator(creatorAddress); uint256 inputsLength = inputs.length; @@ -430,6 +600,7 @@ contract CreateCampaigns is DistributionCreatorScript { }); } + // IERC20(rewardToken).approve(creatorAddress, inputs.length * inputs[0].amount); bytes32[] memory campaignIds = creator.createCampaigns(campaigns); console.log("Created %s campaigns:", inputsLength); @@ -439,6 +610,134 @@ contract CreateCampaigns is DistributionCreatorScript { } } +contract OverrideCampaign is DistributionCreatorScript { + function run() external broadcast { + uint256 chainId = block.chainid; + address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); + // MODIFY THESE VALUES TO SET YOUR DESIRED CAMPAIGN PARAMETERS + bytes32 campaignId = 0xf93a5b762bd5a2a3e6cf6dcb83cb54f70ab2de457e0dc4cbb4da29ba8b54e4ad; + address targetToken = address(0x1337BedC9D22ecbe766dF105c9623922A27963EC); + address[] memory whitelist = new address[](0); + address[] memory blacklist = new address[](0); + string memory url = "https://curve.fi/dex/#/xdai/pools/3pool/deposit"; + bytes[] memory forwarders = new bytes[](0); + bytes[] memory hooks = new bytes[](0); + // END + + CampaignParameters memory campaign = DistributionCreator(creatorAddress).campaign(campaignId); + + CampaignParameters memory overrideCampaign = CampaignParameters({ + campaignId: bytes32(campaign.campaignId), + creator: address(0), + rewardToken: address(0x65A1DfB54CDec9011688b1818A27A8C687e6B1ed), + amount: campaign.amount, + campaignType: 1, + startTimestamp: uint32(campaign.startTimestamp), + duration: 1.5 days, + campaignData: abi.encode(targetToken, whitelist, blacklist, url, forwarders, hooks, hex"") + }); + _run(overrideCampaign); + } + + function run(CampaignParameters calldata campaign) external broadcast { + _run(campaign); + } + + function _run(CampaignParameters memory campaign) internal { + uint256 chainId = block.chainid; + address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); + IERC20(campaign.rewardToken).approve(creatorAddress, campaign.amount); + DistributionCreator(creatorAddress).overrideCampaign(campaign.campaignId, campaign); + + console.log("Campaign created with ID:", vm.toString(campaign.campaignId)); + } +} + +contract ReallocateCampaign is DistributionCreatorScript { + function run() external broadcast { + uint256 chainId = block.chainid; + address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); + // MODIFY THESE VALUES TO SET YOUR DESIRED CAMPAIGN PARAMETERS + bytes32 campaignId = 0x490af89ce201bb272809983117aa95ce4a6cfcbb178343076519fc80ec2ff408; + address[] memory froms = new address[](2); + froms[0] = 0xBA12222222228d8Ba445958a75a0704d566BF2C8; + froms[1] = 0x53C9ACaB7D5f3078141D1178EeA782c7129D92C9; + address to = 0xA9DdD91249DFdd450E81E1c56Ab60E1A62651701; + // END + + _run(campaignId, froms, to); + } + + function run(bytes32 campaignId, address[] memory froms, address to) external broadcast { + _run(campaignId, froms, to); + } + + function _run(bytes32 campaignId, address[] memory froms, address to) internal { + uint256 chainId = block.chainid; + address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); + DistributionCreator(creatorAddress).reallocateCampaignRewards(campaignId, froms, to); + } +} + +contract ReallocateCampaigns is DistributionCreatorScript { + function run() external broadcast { + uint256 chainId = block.chainid; + address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); + // MODIFY THESE VALUES TO SET YOUR DESIRED CAMPAIGN PARAMETERS + + // MAINNET + // now + bytes32[] memory campaignIds = new bytes32[](2); + campaignIds[0] = 0x20cc77d4b6138837753a6f37a6b6c5a7675d1bbf26b3e1f759b437e3bafbc8a5; + campaignIds[1] = 0x552c13b139cb09bb00e486c9ff1b18bf31fa4af94efa92e953a5654922ef50ba; + + // // future + // bytes32[] memory campaignIds = new bytes32[](4); + // campaignIds[0] = 0x31daf1460445bd688f895014ee21d58a41dc31ccb1e3592c7c5af953194625b4; + // campaignIds[1] = 0x989ba1dbf3430e313891984d176ffc79a9aa8410d14a2215156242d981b1dc48; + // campaignIds[2] = 0x5ff68f84ce65b84ef0da170a44716a899e34b79b7d86ef98f4c8495c2b9a715e; + // campaignIds[3] = 0x735de250ce1ca074972d15742fc9367f93f007c057c540d88bd42a6a77b7881c; + + // // BASE + // // now + // bytes32[] memory campaignIds = new bytes32[](4); + // campaignIds[0] = 0x477d78ee82651afdca318485f877ff1923afac46e55a39705665e1da00aa4ab4; + // campaignIds[1] = 0x0de8aad778761479b33f21d81ecffd505c0b3011c66af40fa2ec464e5899b707; + // campaignIds[2] = 0x2340c7c2d3efe6ed0eb6e532f6707b692a58b2340ca31ac426544d5166f4a3d3; + // campaignIds[3] = 0x600d210d7390c8a78dcaeb820e70e16b38c69ef00ca458ccfefe5abd9c9d4d9b; + // campaignIds[4] = 0x18a6be06c3e3f870858ff229f7cb8fa02f9ec8a89586860ed2538bf1cc716a83; + // campaignIds[5] = 0x6fcea5032087c0d5acf11ce21c0a0f9ad1a6532f0323bd8aac390babe40b764e; + // campaignIds[6] = 0xe4c666e923ca13e830ed476f0cded9dd1dd6457c637fbc1ae4b2b473ebe9c211; + + // // future + // bytes32[] memory campaignIds = new bytes32[](4); + // campaignIds[0] = 0xb63933be5065bce6c9b2719f7afa76f3c41a992eddef74b1a321351967313ce7; + // campaignIds[1] = 0x033ed946fb107cf928ffe5d1d4d57c649999769eeb38773443a50eb862caab19; + // campaignIds[2] = 0x5716e04285cf59798cfc1dcc554a07bb2b00031feb9dd7e0fe01ca712fa3ae09; + // campaignIds[3] = 0x0323d17f64608e1f402192ec920b4a9e0203ddfc262fdc4d0a233bc7c64c4f29; + // campaignIds[4] = 0xb32cae66a15634a6b3e65eeb874f1d437288c06ab0604d6e21737e117efdb9bb; + + address[] memory froms = new address[](1); + froms[0] = 0x000000DCeb71f3107909b1b748424349bfde5493; + address to = 0x9a8FEe232DCF73060Af348a1B62Cdb0a19852d13; + // END + + for (uint256 i = 0; i < campaignIds.length; i++) { + _run(campaignIds[i], froms, to); + } + } + + function run(bytes32 campaignId, address[] memory froms, address to) external broadcast { + _run(campaignId, froms, to); + } + + function _run(bytes32 campaignId, address[] memory froms, address to) internal { + uint256 chainId = block.chainid; + address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); + DistributionCreator(creatorAddress).reallocateCampaignRewards(campaignId, froms, to); + } +} + // CreateCampaign script contract CreateCampaignTest is DistributionCreatorScript { function run() external { @@ -555,3 +854,26 @@ contract UpgradeAndBuildUpgradeToPayload is DistributionCreatorScript { return readAddress(chainId, key); } } + +contract SetRewardTokenMinAmountsDistributor is DistributionCreatorScript { + function run() external broadcast { + // MODIFY THESE VALUES TO SET YOUR DESIRED CAMPAIGN PARAMETERS AND SIGNATURE + address[] memory tokens = new address[](1); + uint256[] memory minAmounts = new uint256[](1); + tokens[0] = 0x79385D4B4c531bBbDa25C4cFB749781Bd9E23039; + minAmounts[0] = 1e18; + + _run(tokens, minAmounts); + } + + function run(address[] memory tokens, uint256[] memory minAmounts) external broadcast { + _run(tokens, minAmounts); + } + + function _run(address[] memory tokens, uint256[] memory minAmounts) internal { + uint256 chainId = block.chainid; + address creatorAddress = readAddress(chainId, "Merkl.DistributionCreator"); + + DistributionCreator(creatorAddress).setRewardTokenMinAmounts(tokens, minAmounts); + } +} diff --git a/scripts/Distributor.s.sol b/scripts/Distributor.s.sol index 2f21738..2908c98 100644 --- a/scripts/Distributor.s.sol +++ b/scripts/Distributor.s.sol @@ -266,10 +266,26 @@ contract ToggleTrusted is DistributorScript { contract Claim is DistributorScript { function run() external broadcast { // MODIFY THESE VALUES TO SET YOUR DESIRED CLAIM PARAMETERS - address[] memory users = new address[](0); - address[] memory tokens = new address[](0); - uint256[] memory amounts = new uint256[](0); - bytes32[][] memory proofs = new bytes32[][](0); + address[] memory users = new address[](1); + users[0] = 0xbDE3b37848dE5d26717fe27b4489E130E8d40e77; + address[] memory tokens = new address[](1); + tokens[0] = 0x471EcE3750Da237f93B8E339c536989b8978a438; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 40611295222190597472529; + bytes32[][] memory proofs = new bytes32[][](1); + proofs[0] = new bytes32[](12); + proofs[0][0] = 0xb8bfde09393d772b6c81e62ed70010edc95e5140ab52b7947f1f39caba379082; + proofs[0][1] = 0xb1039b324c1e3616b94f8c0a1d3b41efbac06d59555e9ce5feab5429e4eb4c6e; + proofs[0][2] = 0x20c00ba3347290bca8773e88209097fac1013d8fb2cf848b25f9f9b2a4587983; + proofs[0][3] = 0x29b89499026c037c76d5070cb5adf8398ca2768ef3fb94c7cb666a8c200c91af; + proofs[0][4] = 0x444732d59f5a702718ee03f936a099564ed014f9e448a9dfede9a1cec651c788; + proofs[0][5] = 0xe5f133d0dd210e7f89adf739e87ef7fd5afbcdc230615c6a71c7d2c1a968d383; + proofs[0][6] = 0xca5dc3bfa82c6249507c32080d440c7d34d8ac55dc26c3f28de114548891b0c4; + proofs[0][7] = 0x45d4636913927f6fd6be6bdbfb536b7a37ec1f1efaac8552de1ea8f87da5d939; + proofs[0][8] = 0x166232c805160aea4a86e0f2b32b21781521e7765ab5d13b4ae0b1af2d7ef893; + proofs[0][9] = 0x7b12b41a38a9ad426fcdc06a405bb9fa2d01fbd93922adee141a3978ad28fa38; + proofs[0][10] = 0x55b66cadfa2481cbacc1dd3f4812a1831553efd78ee48eaee75636d78d1c8409; + proofs[0][11] = 0x00bade4967d60b3b661d932ae841a7b49b85f5088a4c7a9381510f2827716779; _run(users, tokens, amounts, proofs); } diff --git a/scripts/Hyperdrive.s.sol b/scripts/Hyperdrive.s.sol new file mode 100644 index 0000000..cae8d17 --- /dev/null +++ b/scripts/Hyperdrive.s.sol @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.17; + +import { console } from "forge-std/console.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { JsonReader } from "@utils/JsonReader.sol"; + +import { BaseScript } from "./utils/Base.s.sol"; +import { MockToken } from "../contracts/mock/MockToken.sol"; + +// Base contract with shared utilities +contract MockTokenScript is BaseScript, JsonReader {} + +// HyperdriveLP script +contract HyperdriveLP is MockTokenScript { + function run() external broadcast { + // MODIFY THESE VALUES TO SET YOUR DESIRED MINT PARAMETERS + address token = 0xD9b66D9a819B36ECEfC26B043eF3B422d5A6123a; + _run(token); + } + + function run(address token) external broadcast { + _run(token); + } + + function _run(address token) internal { + address user = 0x9eB168Ab44B7c479431681558FdF34230c969DE9; + IHyperdrive.PoolInfo memory poolInfo = IHyperdriveLP(token).getPoolInfo(); + uint256 lpBalance = IHyperdriveLP(token).balanceOf(0, user); + console.log("Price LP %s is %s", token, poolInfo.lpSharePrice); + console.log("LP balance %s is %s", user, lpBalance); + } +} + +interface IHyperdrive { + /// Structs /// + + struct MarketState { + /// @dev The pool's share reserves. + uint128 shareReserves; + /// @dev The pool's bond reserves. + uint128 bondReserves; + /// @dev The global exposure of the pool due to open longs + uint128 longExposure; + /// @dev The amount of longs that are still open. + uint128 longsOutstanding; + /// @dev The net amount of shares that have been added and removed from + /// the share reserves due to flat updates. + int128 shareAdjustment; + /// @dev The amount of shorts that are still open. + uint128 shortsOutstanding; + /// @dev The average maturity time of outstanding long positions. + uint128 longAverageMaturityTime; + /// @dev The average maturity time of outstanding short positions. + uint128 shortAverageMaturityTime; + /// @dev A flag indicating whether or not the pool has been initialized. + bool isInitialized; + /// @dev A flag indicating whether or not the pool is paused. + bool isPaused; + /// @dev The proceeds in base of the unredeemed matured positions. + uint112 zombieBaseProceeds; + /// @dev The shares reserved for unredeemed matured positions. + uint128 zombieShareReserves; + } + + struct Checkpoint { + /// @dev The time-weighted average spot price of the checkpoint. This is + /// used to implement circuit-breakers that prevents liquidity from + /// being added when the pool's rate moves too quickly. + uint128 weightedSpotPrice; + /// @dev The last time the weighted spot price was updated. + uint128 lastWeightedSpotPriceUpdateTime; + /// @dev The vault share price during the first transaction in the + /// checkpoint. This is used to track the amount of interest + /// accrued by shorts as well as the vault share price at closing + /// of matured longs and shorts. + uint128 vaultSharePrice; + } + + struct WithdrawPool { + /// @dev The amount of withdrawal shares that are ready to be redeemed. + uint128 readyToWithdraw; + /// @dev The proceeds recovered by the withdrawal pool. + uint128 proceeds; + } + + struct Fees { + /// @dev The LP fee applied to the curve portion of a trade. + uint256 curve; + /// @dev The LP fee applied to the flat portion of a trade. + uint256 flat; + /// @dev The portion of the LP fee that goes to governance. + uint256 governanceLP; + /// @dev The portion of the zombie interest that goes to governance. + uint256 governanceZombie; + } + + struct PoolDeployConfig { + /// @dev The address of the base token. + IERC20 baseToken; + /// @dev The address of the vault shares token. + IERC20 vaultSharesToken; + /// @dev The linker factory used by this Hyperdrive instance. + address linkerFactory; + /// @dev The hash of the ERC20 linker's code. This is used to derive the + /// create2 addresses of the ERC20 linkers used by this instance. + bytes32 linkerCodeHash; + /// @dev The minimum share reserves. + uint256 minimumShareReserves; + /// @dev The minimum amount of tokens that a position can be opened or + /// closed with. + uint256 minimumTransactionAmount; + /// @dev The maximum delta between the last checkpoint's weighted spot + /// APR and the current spot APR for an LP to add liquidity. This + /// protects LPs from sandwich attacks. + uint256 circuitBreakerDelta; + /// @dev The duration of a position prior to maturity. + uint256 positionDuration; + /// @dev The duration of a checkpoint. + uint256 checkpointDuration; + /// @dev A parameter which decreases slippage around a target rate. + uint256 timeStretch; + /// @dev The address of the governance contract. + address governance; + /// @dev The address which collects governance fees + address feeCollector; + /// @dev The address which collects swept tokens. + address sweepCollector; + /// @dev The address that will reward checkpoint minters. + address checkpointRewarder; + /// @dev The fees applied to trades. + IHyperdrive.Fees fees; + } + + struct PoolConfig { + /// @dev The address of the base token. + IERC20 baseToken; + /// @dev The address of the vault shares token. + IERC20 vaultSharesToken; + /// @dev The linker factory used by this Hyperdrive instance. + address linkerFactory; + /// @dev The hash of the ERC20 linker's code. This is used to derive the + /// create2 addresses of the ERC20 linkers used by this instance. + bytes32 linkerCodeHash; + /// @dev The initial vault share price. + uint256 initialVaultSharePrice; + /// @dev The minimum share reserves. + uint256 minimumShareReserves; + /// @dev The minimum amount of tokens that a position can be opened or + /// closed with. + uint256 minimumTransactionAmount; + /// @dev The maximum delta between the last checkpoint's weighted spot + /// APR and the current spot APR for an LP to add liquidity. This + /// protects LPs from sandwich attacks. + uint256 circuitBreakerDelta; + /// @dev The duration of a position prior to maturity. + uint256 positionDuration; + /// @dev The duration of a checkpoint. + uint256 checkpointDuration; + /// @dev A parameter which decreases slippage around a target rate. + uint256 timeStretch; + /// @dev The address of the governance contract. + address governance; + /// @dev The address which collects governance fees + address feeCollector; + /// @dev The address which collects swept tokens. + address sweepCollector; + /// @dev The address that will reward checkpoint minters. + address checkpointRewarder; + /// @dev The fees applied to trades. + IHyperdrive.Fees fees; + } + + struct PoolInfo { + /// @dev The reserves of shares held by the pool. + uint256 shareReserves; + /// @dev The adjustment applied to the share reserves when pricing + /// bonds. This is used to ensure that the pricing mechanism is + /// held invariant under flat updates for security reasons. + int256 shareAdjustment; + /// @dev The proceeds in base of the unredeemed matured positions. + uint256 zombieBaseProceeds; + /// @dev The shares reserved for unredeemed matured positions. + uint256 zombieShareReserves; + /// @dev The reserves of bonds held by the pool. + uint256 bondReserves; + /// @dev The total supply of LP shares. + uint256 lpTotalSupply; + /// @dev The current vault share price. + uint256 vaultSharePrice; + /// @dev An amount of bonds representing outstanding unmatured longs. + uint256 longsOutstanding; + /// @dev The average maturity time of the outstanding longs. + uint256 longAverageMaturityTime; + /// @dev An amount of bonds representing outstanding unmatured shorts. + uint256 shortsOutstanding; + /// @dev The average maturity time of the outstanding shorts. + uint256 shortAverageMaturityTime; + /// @dev The amount of withdrawal shares that are ready to be redeemed. + uint256 withdrawalSharesReadyToWithdraw; + /// @dev The proceeds recovered by the withdrawal pool. + uint256 withdrawalSharesProceeds; + /// @dev The share price of LP shares. This can be used to mark LP + /// shares to market. + uint256 lpSharePrice; + /// @dev The global exposure of the pool due to open positions + uint256 longExposure; + } + + struct Options { + /// @dev The address that receives the proceeds of a trade or LP action. + address destination; + /// @dev A boolean indicating that the trade or LP action should be + /// settled in base if true and in the yield source shares if false. + bool asBase; + /// @dev Additional data that can be used to implement custom logic in + /// implementation contracts. + bytes extraData; + } + + /// Getters /// + + /// @notice Gets the target0 address. + /// @return The target0 address. + function target0() external view returns (address); + + /// @notice Gets the target1 address. + /// @return The target1 address. + function target1() external view returns (address); + + /// @notice Gets the target2 address. + /// @return The target2 address. + function target2() external view returns (address); + + /// @notice Gets the target3 address. + /// @return The target3 address. + function target3() external view returns (address); +} + +interface IHyperdriveLP { + function getPoolInfo() external view returns (IHyperdrive.PoolInfo memory); + + function balanceOf(uint256 id, address account) external view returns (uint256); +} diff --git a/scripts/PointToken.s.sol b/scripts/PointToken.s.sol new file mode 100644 index 0000000..71f5e3d --- /dev/null +++ b/scripts/PointToken.s.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.17; + +import { console } from "forge-std/console.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { JsonReader } from "@utils/JsonReader.sol"; + +import { BaseScript } from "./utils/Base.s.sol"; +import { PointToken } from "../contracts/partners/tokenWrappers/PointToken.sol"; + +// Base contract with shared utilities +contract PointTokenScript is BaseScript, JsonReader {} + +// Deploy script +contract DeployPointToken is PointTokenScript { + function run() external broadcast { + uint256 chainId = block.chainid; + // MODIFY THESE VALUES TO SET YOUR DESIRED TOKEN PARAMETERS + string memory name = "Miles"; + string memory symbol = "Miles"; + address minter = 0xa9bbbDDe822789F123667044443dc7001fb43C01; + uint8 decimals = 18; + address accessControlManager = readAddress(chainId, "Merkl.CoreMerkl"); + _run(name, symbol, minter, accessControlManager); + } + + function _run(string memory name, string memory symbol, address minter, address accessControlManager) internal { + console.log("DEPLOYER_ADDRESS:", broadcaster); + + // Deploy PointToken + PointToken token = new PointToken(name, symbol, minter, accessControlManager); + console.log("Point token deployed at:", address(token)); + console.log("Name:", name); + console.log("Symbol:", symbol); + console.log("Decimals:", token.decimals()); + + // Mint initial supply to deployer + token.mint(minter, 1e6 * 1e18); + console.log("Initial supply minted to deployer"); + } +}