I have a function in Solidity that is supposed to check if the recovery hash
committed by the Email recovery service matches the hash generated through the token and nonce sent by the user (He receives this from his email). Here's how the code looks:
///@dev Called by the email service which commits the recovery hash
function commitRecoveryHash(bytes32 recoveryHash) external onlyEmailVerificationService {
emailVerificationHash = recoveryHash;
}
Here's how the email recovery service generates the recovery hash
address emailService = address(0xa0Ee7A142d267C1f36714E4a8F75612F20a79720);
string userEmail = "[email protected]";
uint64 nonce = 38;
vm.startPrank(emailService);
bytes memory recoveryToken = (abi.encodePacked(userEmail, emailService));
emit EmailServiceGeneratingHashUsing(recoveryToken, nonce);
bytes32 emailVerificationHash = keccak256(abi.encodePacked(recoveryToken, nonce));
accountRecovery.commitRecoveryHash(emailVerificationHash);
vm.stopPrank();
Now I have a test that calls the function to check if the recovery hashes match.
address emailService = address(0xa0Ee7A142d267C1f36714E4a8F75612F20a79720); // TODO: To be updated with the wallet address of the actual email
string userEmail = "[email protected]";
uint64 nonce = 38;
function testUserVerification() external {
bytes memory recoveryToken = abi.encodePacked(userEmail, emailService);
// creating a new Embedded wallet for the user
address newWallet = makeAddr("newWallet");
// Act/ Assert
vm.prank(newWallet); // using the new wallet to send recovery req.
vm.expectEmit();
emit AccountRecoveryRequestCreated();
accountRecovery.verifyUserAsOwnerOfTheAccount(userEmail, recoveryToken, nonce);
}
Here's the test calling the verifyUserAsOwnerOfTheAccount()
using the same recovery token, email, and nonce:
function verifyUserAsOwnerOfTheAccount(
string memory email,
bytes calldata token,
uint256 nonce
) internal returns (bool) {
///@dev Hashing strings to compare them.
emit AboutToGenerateHashUsing(token, nonce);
bytes32 generatedEmailVerificationHash = keccak256(abi.encodePacked(token, nonce));
emit RecoveryHash(emailVerificationHash);
emit GeneratedHash(generatedEmailVerificationHash);
console.log("Do the email hash match:", (generatedEmailVerificationHash == emailVerificationHash));
if (generatedEmailVerificationHash != emailVerificationHash) {
revert EmailVerificationFailed();
}
return true;
}
Please note the events EmailServiceGeneratingHashUsing
& AboutToGenerateHashUsing
prove that the same params went into creating the hashes and the same keccak256(abi.encodePacked(recoveryToken, nonce))
method was used to create the hashes, but still the hashes don't match. Here are the logs:
VM::stopPrank()
│ └─ ← ()
├─ [0] VM::startPrank(0xa0Ee7A142d267C1f36714E4a8F75612F20a79720)
│ └─ ← ()
├─ emit EmailServiceGeneratingHashUsing(token: 0x73686976656e40676d61696c2e636f6da0ee7a142d267c1f36714e4a8f75612f20a79720, nonce: 38)
├─ [22408] AccountRecovery::commitRecoveryHash(0x271f87acd2085f2e203d8d983e89f336274e0c2028ebc7340703b3b141b0b6dc)
│ └─ ← ()
├─ [0] VM::stopPrank()
│ └─ ← ()
└─ ← ()
[32967] AccountRecoveryTest::testRecoveryRequestGeneration()
├─ [0] VM::addr(<pk>) [staticcall]
│ └─ ← newWallet: [0xBc1Ce00634302d0DfDF22B8C2b8Dc81011bCA560]
├─ [0] VM::label(newWallet: [0xBc1Ce00634302d0DfDF22B8C2b8Dc81011bCA560], newWallet)
│ └─ ← ()
├─ [0] VM::prank(newWallet: [0xBc1Ce00634302d0DfDF22B8C2b8Dc81011bCA560])
│ └─ ← ()
├─ [0] VM::expectEmit()
│ └─ ← ()
├─ emit AccountRecoveryRequestCreated()
├─ [14330] AccountRecovery::verifyUserAsOwnerOfTheAccount([email protected], 0x73686976656e40676d61696c2e636f6da0ee7a142d267c1f36714e4a8f75612f20a79720, 38)
│ ├─ emit AboutToGenerateHashUsing(receivedToken: 0x73686976656e40676d61696c2e636f6da0ee7a142d267c1f36714e4a8f75612f20a79720, nonce: 38)
│ ├─ emit RecoveryHash(recoveryHash: 0x271f87acd2085f2e203d8d983e89f336274e0c2028ebc7340703b3b141b0b6dc)
│ ├─ emit GeneratedHash(generatedHash: 0x7c3438dd181130e624805b50265942f829f784fc1720b189431743713d7e826c)
│ ├─ [0] console::log(Do the email hash match:, false) [staticcall]
│ │ └─ ← ()
│ └─ ← "EmailVerificationFailed()"
└─ ← "Log != expected log"
I'm not able to figure out why the emailVerificationHash
& generatedEmailVerificationHash
don't match.
emit RecoveryHash(recoveryHash: 0x271f87acd2085f2e203d8d983e89f336274e0c2028ebc7340703b3b141b0b6dc)
emit GeneratedHash(generatedHash: 0x7c3438dd181130e624805b50265942f829f784fc1720b189431743713d7e826c)
Need help.