Skip to content

Commit

Permalink
deployed contract
Browse files Browse the repository at this point in the history
  • Loading branch information
owanemi committed Dec 5, 2024
1 parent 1869577 commit e756235
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

Expand Down
10 changes: 5 additions & 5 deletions script/DeployMerkleAirdrop.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
44 changes: 36 additions & 8 deletions script/GenerateInput.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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);
Expand All @@ -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;
}
}
}
27 changes: 13 additions & 14 deletions script/MakeMerkle.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,28 @@ 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
*
* Original Work by:
* @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);
Expand All @@ -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)
Expand Down Expand Up @@ -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)));
Expand All @@ -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.
Expand All @@ -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);
}
}
}
6 changes: 2 additions & 4 deletions src/MerkleAirdrop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


}
9 changes: 4 additions & 5 deletions test/MerkleAirdropTest.t.sol
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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;
Expand All @@ -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 {
Expand All @@ -46,4 +45,4 @@ contract MerkleAirdropTest is Test {

assertEq(endingBalance - startingBalance, AMOUNT);
}
}
}

0 comments on commit e756235

Please sign in to comment.