我正在研究一个智能合约,它有一个merkle树函数
基本上,我从firebase函数传递证据,该函数接收用户保留的地址和令牌的n°的输入,并将证据作为输出提供给执行智能合约函数的前端。
我唯一需要弄清楚的是leaf计算,在firebase函数上,它是通过对数组中的字符串keccak256进行编码而组成的,该字符串由eth地址与保留令牌的数量(0x32807d0e84edb04a57482c3769fe192617520373+3(连接而成,而在智能合约中,叶是用keccak256(abi.incodepacked(0x32807d0e84edb04a57482c3769fe1926175203733,3(计算的,它没有通过验证。。。
我认为这两种计算方法在某些方面不同,你能帮我吗?
我将粘贴两个函数的代码:
溶解度
// 1. Address check, if the proof is valid
function isPrivateListed(
uint256 _addressReservedTokens,
bytes32[] memory _proof
) public view returns (bool) {
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _addressReservedTokens);
return MerkleProof.verify(_proof, privateListRoot, leaf);
}
// 2. Mint function called from the front-end
function privateMint(
uint256 _mintAmount,
uint256 _addressReservedTokens,
bytes32[] calldata proof
) public payable {
require(privateOpen, "The private mint is not opened");
require(
isPrivateListed(_addressReservedTokens, proof),
"you are not in the private list"
);
uint256 supply = totalSupply();
require(supply + _mintAmount <= maxSupply, "max NFT limit exceeded");
uint256 owned = addressMintedBalance[msg.sender];
require(
owned + _mintAmount <= _addressReservedTokens,
"You have less nft reserved"
);
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(msg.sender, supply + i);
addressMintedBalance[msg.sender]++;
}
}
防火墙功能
// 1. Get parameters from the function called from client side
const walletAddress = data.walletAddress;
let whitelistAddresses = [
'0x38207d0e84edb04a57482c3769fe1926175203733',
'0x943926a8ff0000350d0b879a658fa52bcd4fca186',
];
// 2. Create a new array of `leafNodes` by hashing all indexes of the `whitelistAddresses`
// using `keccak256`. Then creates a Merkle Tree object using keccak256 as the algorithm.
const leafNodes = whitelistAddresses.map((addr) => keccak256(addr));
const merkleTree = new MerkleTree(leafNodes, keccak256, {
sortPairs: true,
});
// 3. Get root hash of the `merkleeTree` in hexadecimal format (0x)
const rootHash = merkleTree.getRoot();
const rootHashHex = merkleTree.getHexRoot();
// ***** ***** ***** CLIENT-SIDE ***** ***** ***** //
const claimingAddress = keccak256(walletAddress);
const hexProof = merkleTree.getHexProof(claimingAddress);
const verifyProof = merkleTree.verify(hexProof, claimingAddress, rootHash);
在solidity中,您正在散列一个(20+32(字节的元素
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _addressReservedTokens);
由于msg.sender
是20个字节,_addressReservedTokens
是32个字节,因此abi.encodePacked()
的输出大致如下:
0x38207d0e84edb04a57482c3769fe1926175203730000000000000000000000000000000000000000000000000000000000000003
这与firebase使用的0x38207d0e84edb04a57482c3769fe1926175203733
明显不同。
此外,我不确定js-keccak256是将该值解释为字符串还是字节(在solidity中是字节(。
最好的解决方案可能是更改js代码。您可以使用ethers编写正确的whitelistAddresses
,请参阅此处https://ethereum.stackexchange.com/questions/119990/how-to-mimic-abi-encodepacked-in-ethers