CRYPTO NEWS

Binance crypto exchange outage sparks outrage as traders lose millions

Binance’s policy allows investors to get compensation on trading losses due to system or internal issues but does not cover the “what could have been” situations.

How do I make keccak256 hashes from merkletreejs and those encoded with abi.encodePacked() match?

My overall goal is to create a Merkle tree with the contents of a JSON file and then verify that the Merkle tree contains a certain data element. I have a smart contract in Solidity written as follows: contract SimpleRewardDistributor { event Claimed(uint256 index, address account, uint256 amount); address public immutable token; bytes32 public immutable::Listen

My overall goal is to create a Merkle tree with the contents of a JSON file and then verify that the Merkle tree contains a certain data element.

I have a smart contract in Solidity written as follows:

contract SimpleRewardDistributor {     event Claimed(uint256 index, address account, uint256 amount);      address public immutable token;     bytes32 public immutable merkleRoot;      // This is a packed array of booleans.     mapping(uint256 => bool) private claimedMap;      constructor(address token_, bytes32 merkleRoot_) public {         token = token_;         merkleRoot = merkleRoot_;     }      function isClaimed(uint256 index) public view returns (bool) {         return claimedMap[index];     }      function _setClaimed(uint256 index) private {         claimedMap[index] = true;     }      function claim(uint256 index, address account, uint256 amount, bytes32[] calldata merkleProof) external {         require(!isClaimed(index), 'MerkleDistributor: Drop already claimed.');          // Verify the merkle proof.         bytes32 node = keccak256(abi.encodePacked(index, account, amount));         console.log("Keccak256 of abi.encodePacked(index, account, amount) (variable node) is: ");         console.logBytes32(node);         require(MerkleProof.verify(merkleProof, merkleRoot, node), 'MerkleDistributor: Invalid proof.');          // Mark it claimed and send the token.         _setClaimed(index);         require(IERC20(token).transfer(account, amount), 'MerkleDistributor: Transfer failed.');          emit Claimed(index, account, amount);     } } 

The MerkleProof library is the one from OpenZeppelin:

library MerkleProof {     /**      * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree      * defined by `root`. For this, a `proof` must be provided, containing      * sibling hashes on the branch from the leaf to the root of the tree. Each      * pair of leaves and each pair of pre-images are assumed to be sorted.      */     function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {         bytes32 computedHash = leaf;          for (uint256 i = 0; i < proof.length; i++) {             bytes32 proofElement = proof[i];              if (computedHash <= proofElement) {                 // Hash(current computed hash + current element of the proof)                 computedHash = keccak256(abi.encodePacked(computedHash, proofElement));             } else {                 // Hash(current element of the proof + current computed hash)                 computedHash = keccak256(abi.encodePacked(proofElement, computedHash));             }         }          // Check if the computed hash (root) is equal to the provided root         return computedHash == root;     } } 

The JSON file looks like this:

{"distribution":[{"index":0,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x1eca955e9b65e00000"}},{"index":1,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x100bd33fb98ba00000"}},{"index":2,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x19196a6eebbddc0000"}},{"index":3,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x218e59c465becc0000"}},{"index":4,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x28fb9b8a8a53500000"}},{"index":5,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x0a922b2ad8812c0000"}},{"index":6,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x2723c346ae18080000"}},{"index":7,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x2288269d0783d40000"}},{"index":8,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x204148a38e0d6c0000"}},{"index":9,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x0b6255df5f50080000"}},{"index":10,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x26d07efe782bb00000"}},{"index":11,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x02df85d331a7b40000"}},{"index":12,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x2f000ac26fe7ac0000"}},{"index":13,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x212d34c57c2b100000"}},{"index":14,"address":"0xcf","amount":{"type":"BigNumber","hex":"0x2c65e880c084ec0000"}}],"privateKeys":[{"index":0,"address":"0xcf","privateKey":"0xcf"},{"index":1,"address":"0xcf","privateKey":"0xcf"},{"index":2,"address":"0xcf","privateKey":"0xcf"},{"index":3,"address":"0xcf","privateKey":"0xcf"},{"index":4,"address":"0xcf","privateKey":"0xcf"},{"index":5,"address":"0xcf","privateKey":"0xcf"},{"index":6,"address":"0xcf","privateKey":"0xcf"},{"index":7,"address":"0xcf","privateKey":"0xcf"},{"index":8,"address":"0xcf","privateKey":"0xcf"},{"index":9,"address":"0xcf","privateKey":"0xcf"},{"index":10,"address":"0xcf","privateKey":"0xcf"},{"index":11,"address":"0xcf","privateKey":"0xcf"},{"index":12,"address":"0xcf","privateKey":"0xcf"},{"index":13,"address":"0xcf","privateKey":"0xcf"},{"index":14,"address":"0xcf","privateKey":"0xcf"}]} 

Here’s how my code for deploying the contracts and creating the Merkle tree looks like (I use merkletreejs for creating the Merkle tree).

const { MerkleTree } = require('merkletreejs'); const keccak256 = require('keccak256') const fs = require('fs'); // for loading the reward distribution JSON  async function main() {   const [deployer] = await ethers.getSigners();    console.log("Deploying contracts with the account:", deployer.address);   console.log("Account balance:", (await deployer.getBalance()).toString());    const TestTokenWithNameAndSymbolFlat = await ethers.getContractFactory("TestTokenWithNameAndSymbol");   const testTokenWithNameAndSymbolFlatInstance = await TestTokenWithNameAndSymbolFlat.deploy(1000000, "TestToken", "TT");    // construct a Merkle tree   const data = require('./rewardDistribution2.json')   const distribution = data["distribution"]   const leaves = distribution.map(element => keccak256(JSON.stringify(element)))   const tree = new MerkleTree(leaves, keccak256)   const root = tree.getRoot()   const leaf = keccak256(JSON.stringify(distribution[0]))    console.log("leaf:")   console.log(leaf)   const proof = tree.getProof(leaf)   console.log(tree.verify(proof, leaf, root))     const SimpleRewardDistributorFlat = await ethers.getContractFactory("SimpleRewardDistributor");   const simpleRewardDistributorFlatInstance = await SimpleRewardDistributorFlat.deploy(testTokenWithNameAndSymbolFlatInstance.address, root);    const proof_data = proof.map(element => element["data"])   const result = await simpleRewardDistributorFlatInstance.claim(distribution[0]["index"], distribution[0]["address"], distribution[0]["amount"], proof_data)    const result2 = await simpleRewardDistributorFlatInstance.claim(1, "0x1b324A4Ea3545d774b4c40A77ddf5F22370DE0a1", 5680, proof_data) }  main()   .then(() => process.exit(0))   .catch((error) => {     console.error(error);     process.exit(1);   }); 

Now, here’s the output I get when I run this code:

leaf: <Buffer 2c c5 b5 d0 59 d4 a9 54 cc d1 7f 2a e0 c3 3c 18 c3 d1 ce cf fc 97 b9 d1 4c e7 88 b1 8a 2a 2b 11> true Keccak256 of abi.encodePacked(index, account, amount) (variable node) is:  0x02135992641ca05b450e870c14db6a9018c845ce059fd064196be330c21cb7d5 Error: VM Exception while processing transaction: reverted with reason string 'MerkleDistributor: Invalid proof.'     at SimpleRewardDistributor.claim (contracts/SimpleRewardDistributorFlat.sol:152)     at HardhatNode._mineBlockWithPendingTxs (/home/john/Documents/test/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1650:23)     at HardhatNode.mineBlock (/home/john/Documents/test/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:459:16)     at EthModule._sendTransactionAndReturnHash (/home/john/Documents/test/node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1496:18)     at HardhatNetworkProvider.request (/home/john/Documents/test/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:117:18)     at EthersProviderWrapper.send (/home/john/Documents/test/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20) 

I get the invalid proof exception, but notice that the hashes are different (the keccak256 hash in the JavaScript script is 2c c5 b5 d0 59 d4 a9 54 cc d1 7f 2a e0 c3 3c 18 c3 d1 ce cf fc 97 b9 d1 4c e7 88 b1 8a 2a 2b 11 (or, equivalently, 0x2cc5b5d059d4a954ccd17f2ae0c33c18c3d1cecffc97b9d14ce788b18a2a2b11), while in the Solidity contract it’s 0x02135992641ca05b450e870c14db6a9018c845ce059fd064196be330c21cb7d5.

Now I figure this has to do with me calling JSON.stringify() on distribution[0], but passing raw parameters to the smart contract method call. I’m not sure however, and that’s why I’m asking this question.

Maybe there’s additional problems with this code, if there is, please feel free to elaborate on them as well.

Thanks in advance!

Binance crypto exchange outage sparks outrage as traders lose millions

Shopping cart
There are no products in the cart!
Continue shopping
0