diff --git a/package.json b/package.json index 715b416..c62680c 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 CreateCampaigns --rpc-url gnosis --sender 0xa9bbbDDe822789F123667044443dc7001fb43C01 -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", @@ -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..3aa79cc 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"; @@ -348,15 +349,50 @@ contract Sign is DistributionCreatorScript { contract CreateCampaign is DistributionCreatorScript { function run() external broadcast { // 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(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""); + // 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: address(0x65A1DfB54CDec9011688b1818A27A8C687e6B1ed), + amount: 1e4 * 1e8, + campaignType: campaignType, + startTimestamp: uint32(block.timestamp - 5 hours), + duration: 1 days, + campaignData: campaignData }); _run(campaign); } @@ -368,7 +404,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 +425,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 = 0; + 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 = 1e6 * 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: 1738195200, + duration: 30 days, + campaignData: campaignData + }); + } + } + _run(inputs); } @@ -409,8 +523,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 +543,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 +553,75 @@ 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); + } +} + // CreateCampaign script contract CreateCampaignTest is DistributionCreatorScript { function run() external { @@ -555,3 +738,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/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"); + } +}