From e7562351cb07c4f84bd4402c5202e43b59d3bea3 Mon Sep 17 00:00:00 2001 From: owanemi Date: Thu, 5 Dec 2024 14:13:41 +0100 Subject: [PATCH] deployed contract --- .gitignore | 2 +- script/DeployMerkleAirdrop.s.sol | 10 ++++---- script/GenerateInput.s.sol | 44 ++++++++++++++++++++++++++------ script/MakeMerkle.s.sol | 27 ++++++++++---------- src/MerkleAirdrop.sol | 6 ++--- test/MerkleAirdropTest.t.sol | 9 +++---- 6 files changed, 61 insertions(+), 37 deletions(-) diff --git a/.gitignore b/.gitignore index 85198aa..c524b01 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ cache/ out/ # Ignores development broadcast logs -!/broadcast +/broadcast /broadcast/*/31337/ /broadcast/**/dry-run/ diff --git a/script/DeployMerkleAirdrop.s.sol b/script/DeployMerkleAirdrop.s.sol index 2e85d1a..08d87c4 100644 --- a/script/DeployMerkleAirdrop.s.sol +++ b/script/DeployMerkleAirdrop.s.sol @@ -2,23 +2,23 @@ pragma solidity ^0.8.24; import {Script} from "forge-std/Script.sol"; -import { MerkleAirdrop } from "../src/MerkleAirdrop.sol"; -import {IERC20, SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import {MerkleAirdrop} from "../src/MerkleAirdrop.sol"; +import {IERC20, SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; contract DeployMerkleAirdrop is Script { using SafeERC20 for IERC20; + address public constant TOKEN = 0xBF68a24e5Be60B0c07247f054bb1564E7DC554F8; bytes32 public constant s_merkleRootHash = 0x0f6c57ab57c9e81c1bc0c199923fb0eb300c775e342f11eb2764de29b995e509; - function deployMerkleAirdrop() public returns (MerkleAirdrop) { vm.startBroadcast(); MerkleAirdrop airdrop = new MerkleAirdrop(s_merkleRootHash, IERC20(TOKEN)); - return airdrop; vm.stopBroadcast(); + return airdrop; } function run() external returns (MerkleAirdrop) { return deployMerkleAirdrop(); } -} \ No newline at end of file +} diff --git a/script/GenerateInput.s.sol b/script/GenerateInput.s.sol index 36fbbd4..8ce7745 100644 --- a/script/GenerateInput.s.sol +++ b/script/GenerateInput.s.sol @@ -11,8 +11,8 @@ contract GenerateInput is Script { string[] types = new string[](2); uint256 count; string[] whitelist = new string[](4); - string private constant INPUT_PATH = "/script/target/input.json"; - + string private constant INPUT_PATH = "/script/target/input.json"; + function run() public { types[0] = "address"; types[1] = "uint"; @@ -22,7 +22,7 @@ contract GenerateInput is Script { whitelist[3] = "0xf6dBa02C01AF48Cf926579F77C9f874Ca640D91D"; count = whitelist.length; string memory input = _createJSON(); - // write to the output file the stringified output json tree dumpus + // write to the output file the stringified output json tree dumpus vm.writeFile(string.concat(vm.projectRoot(), INPUT_PATH), input); console.log("DONE: The output is found at %s", INPUT_PATH); @@ -34,13 +34,41 @@ contract GenerateInput is Script { string memory json = string.concat('{ "types": ["address", "uint"], "count":', countString, ',"values": {'); for (uint256 i = 0; i < whitelist.length; i++) { if (i == whitelist.length - 1) { - json = string.concat(json, '"', vm.toString(i), '"', ': { "0":', '"',whitelist[i],'"',', "1":', '"',amountString,'"', ' }'); + json = string.concat( + json, + '"', + vm.toString(i), + '"', + ': { "0":', + '"', + whitelist[i], + '"', + ', "1":', + '"', + amountString, + '"', + " }" + ); } else { - json = string.concat(json, '"', vm.toString(i), '"', ': { "0":', '"',whitelist[i],'"',', "1":', '"',amountString,'"', ' },'); + json = string.concat( + json, + '"', + vm.toString(i), + '"', + ': { "0":', + '"', + whitelist[i], + '"', + ', "1":', + '"', + amountString, + '"', + " }," + ); } } - json = string.concat(json, '} }'); - + json = string.concat(json, "} }"); + return json; } -} \ No newline at end of file +} diff --git a/script/MakeMerkle.s.sol b/script/MakeMerkle.s.sol index 0c3364b..f67abd1 100644 --- a/script/MakeMerkle.s.sol +++ b/script/MakeMerkle.s.sol @@ -13,7 +13,7 @@ import {ScriptHelper} from "murky/script/common/ScriptHelper.sol"; // 2. Run `forge script script/Merkle.s.sol` // 3. The output file will be generated in /script/target/output.json -/** +/** * @title MakeMerkle * @author Owanemi * @@ -21,21 +21,20 @@ import {ScriptHelper} from "murky/script/common/ScriptHelper.sol"; * @author kootsZhin * @notice https://github.com/dmfxyz/murky */ - contract MakeMerkle is Script, ScriptHelper { using stdJson for string; // enables us to use the json cheatcodes for strings - Merkle private m = new Merkle(); // instance of the merkle contract from Murky to do shit + Merkle private m = new Merkle(); // instance of the merkle contract from Murky to do shit string private inputPath = "/script/target/input.json"; string private outputPath = "/script/target/output.json"; - string private elements = vm.readFile(string.concat(vm.projectRoot(), inputPath)); // get the absolute path - string[] private types = elements.readStringArray(".types"); // gets the merkle tree leaf types from json using forge standard lib cheatcode + string private elements = vm.readFile(string.concat(vm.projectRoot(), inputPath)); // get the absolute path + string[] private types = elements.readStringArray(".types"); // gets the merkle tree leaf types from json using forge standard lib cheatcode uint256 private count = elements.readUint(".count"); // get the number of leaf nodes // make three arrays the same size as the number of leaf nodes - bytes32[] private leafs = new bytes32[](count); + bytes32[] private leafs = new bytes32[](count); string[] private inputs = new string[](count); string[] private outputs = new string[](count); @@ -46,7 +45,7 @@ contract MakeMerkle is Script, ScriptHelper { // output file output ".values.some-address.some-amount" function getValuesByIndex(uint256 i, uint256 j) internal pure returns (string memory) { return string.concat(".values.", vm.toString(i), ".", vm.toString(j)); - } + } /// @dev Generate the JSON entries for the output file function generateJsonEntries(string memory _inputs, string memory _proof, string memory _root, string memory _leaf) @@ -86,7 +85,7 @@ contract MakeMerkle is Script, ScriptHelper { if (compareStrings(types[j], "address")) { address value = elements.readAddress(getValuesByIndex(i, j)); // you can't immediately cast straight to 32 bytes as an address is 20 bytes so first cast to uint160 (20 bytes) cast up to uint256 which is 32 bytes and finally to bytes32 - data[j] = bytes32(uint256(uint160(value))); + data[j] = bytes32(uint256(uint160(value))); input[j] = vm.toString(value); } else if (compareStrings(types[j], "uint")) { uint256 value = vm.parseUint(elements.readString(getValuesByIndex(i, j))); @@ -96,11 +95,11 @@ contract MakeMerkle is Script, ScriptHelper { } // Create the hash for the merkle tree leaf node // abi encode the data array (each element is a bytes32 representation for the address and the amount) - // Helper from Murky (ltrim64) Returns the bytes with the first 64 bytes removed + // Helper from Murky (ltrim64) Returns the bytes with the first 64 bytes removed // ltrim64 removes the offset and length from the encoded bytes. There is an offset because the array - // is declared in memory - // hash the encoded address and amount - // bytes.concat turns from bytes32 to bytes + // is declared in memory + // hash the encoded address and amount + // bytes.concat turns from bytes32 to bytes // hash again because preimage attack leafs[i] = keccak256(bytes.concat(keccak256(ltrim64(abi.encode(data))))); // Converts a string array into a JSON array string. @@ -124,9 +123,9 @@ contract MakeMerkle is Script, ScriptHelper { // stringify the array of strings to a single string output = stringArrayToArrayString(outputs); - // write to the output file the stringified output json tree dumpus + // write to the output file the stringified output json tree dumpus vm.writeFile(string.concat(vm.projectRoot(), outputPath), output); console.log("DONE: The output is found at %s", outputPath); } -} \ No newline at end of file +} diff --git a/src/MerkleAirdrop.sol b/src/MerkleAirdrop.sol index 85b0995..b4592b0 100644 --- a/src/MerkleAirdrop.sol +++ b/src/MerkleAirdrop.sol @@ -60,13 +60,11 @@ contract MerkleAirdrop { /*////////////////////////////////////////////////////////////// GETTER FUNCTIONS //////////////////////////////////////////////////////////////*/ - function getMerkleRoot() external view returns(bytes32) { + function getMerkleRoot() external view returns (bytes32) { return i_merkleRoot; } - function getAirdropToken() external view returns(IERC20) { + function getAirdropToken() external view returns (IERC20) { return i_tokenToAirdrop; } - - } diff --git a/test/MerkleAirdropTest.t.sol b/test/MerkleAirdropTest.t.sol index 6a2f92f..adbbd97 100644 --- a/test/MerkleAirdropTest.t.sol +++ b/test/MerkleAirdropTest.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import { Test, console } from "lib/forge-std/src/Test.sol"; -import { MerkleAirdrop } from "../src/MerkleAirdrop.sol"; +import {Test, console} from "lib/forge-std/src/Test.sol"; +import {MerkleAirdrop} from "../src/MerkleAirdrop.sol"; import {IERC20, SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; contract MerkleAirdropTest is Test { @@ -17,7 +17,7 @@ contract MerkleAirdropTest is Test { address constant NEMI_TOKEN_OWNER = 0x48CeF35f4aB78D3f24d73E2B158762aCc671302E; uint256 userPrivKey; uint256 AMOUNT = 25 * 1e18; - uint256 AMOUNT_TO_SEND = (25 * 1e18) *4; + uint256 AMOUNT_TO_SEND = (25 * 1e18) * 4; bytes32 proof1 = 0x0fd7c981d39bece61f7499702bf59b3114a90e66b51ba2c53abdf7b62986c00a; bytes32 proof2 = 0xe5ebd1e1b5a5478a944ecab36a9a954ac3b6b8216875f6524caa7a1d87096576; @@ -28,7 +28,6 @@ contract MerkleAirdropTest is Test { airdrop = new MerkleAirdrop(ROOT, TOKEN); (user, userPrivKey) = makeAddrAndKey("user"); // TOKEN.transfer(address(airdrop), AMOUNT_TO_SEND); - } function testUsersCanClaim() public { @@ -46,4 +45,4 @@ contract MerkleAirdropTest is Test { assertEq(endingBalance - startingBalance, AMOUNT); } -} \ No newline at end of file +}