# ERC-4337 UserOperation Hash
## How to calculate UserOperationHash
```
UserOperationHash = keccak256(abi.encode(hash(pack(op)), entryPointAddress, chainId))
```
- pack()
- hash()
## UserOperation Struct
```solidity
struct UserOperation {
address sender; // 0x9fd042a18e90ce326073fa70f111dc9d798d9a52
uint256 nonce; // 123
bytes initCode; // hello (0x68656c6c6f)
bytes callData; // world (0x776F726C64)
uint256 callGasLimit; // 1000
uint256 verificationGasLimit; // 2300
uint256 preVerificationGas; // 3100
uint256 maxFeePerGas; // 8500
uint256 maxPriorityFeePerGas; // 1
bytes paymasterAndData; // blocto (0x626c6f63746f)
bytes signature; // clement (0x636c656d656e74)
}
```
## `pack()`
#### Code
```solidity=
// `signature` is not included.
function pack(UserOperation calldata userOp) public pure returns (bytes memory ret) {
address sender = getSender(userOp);
uint256 nonce = userOp.nonce;
bytes32 hashInitCode = calldataKeccak(userOp.initCode);
bytes32 hashCallData = calldataKeccak(userOp.callData);
uint256 callGasLimit = userOp.callGasLimit;
uint256 verificationGasLimit = userOp.verificationGasLimit;
uint256 preVerificationGas = userOp.preVerificationGas;
uint256 maxFeePerGas = userOp.maxFeePerGas;
uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;
bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);
return abi.encode(
sender,
nonce,
hashInitCode,
hashCallData,
callGasLimit,
verificationGasLimit,
preVerificationGas,
maxFeePerGas,
maxPriorityFeePerGas,
hashPaymasterAndData
);
}
```
#### Result
```
0x
sender 0000000000000000000000009fd042a18e90ce326073fa70f111dc9d798d9a52
nonce 000000000000000000000000000000000000000000000000000000000000007b
hashInitCode 1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8
hashCallData 8452c9b9140222b08593a26daa782707297be9f7b3e8281d7b4974769f19afd0
callGasLimit 00000000000000000000000000000000000000000000000000000000000003e8
verificationGasLimit 00000000000000000000000000000000000000000000000000000000000008fc
preVerificationGas 0000000000000000000000000000000000000000000000000000000000000c1c
maxFeePerGas 0000000000000000000000000000000000000000000000000000000000002134
maxPriorityFeePerGas 0000000000000000000000000000000000000000000000000000000000000001
hashPaymasterAndData 87a03e44e7bf9fb10a29733982a339f6a2a22dc7eb1015ae7bb61fc0f710b85d
```
- `hashInitCode`: keccak256(initCode)
- `hashCallData`: keccak256(callData)
- `hashPaymasterAndData`: keccak256(paymasterAndData)
## `hash()`
#### Code
```solidity=
function hash(UserOperation calldata userOp) public pure returns (bytes32) {
return keccak256(pack(userOp));
}
```
#### Result
```
0xf88f954157adc24e05de4962278d73e5e45f8028c85da59cd23c46f2701d82e3
```
## `getUserOpHash()`
- hash(from `hash()`): 0xf88f954157adc24e05de4962278d73e5e45f8028c85da59cd23c46f2701d82e3
- entryPointAddress: 0xaE036c65C649172b43ef7156b009c6221B596B8b
- chainId: 0x1
#### Code
```solidity=
keccak256(abi.encode(hash, entryPointAddress, chainId));
```
#### Result
```
0xe554d0701f7fdc734f84927d109537f1ac4ee4ebfa3670c71d224a4fa15dbcd1
```
```
[
"0x9fd042a18e90ce326073fa70f111dc9d798d9a52",
123,
"0x68656c6c6f",
"0x776f726c64",
1000,
2300,
3100,
8500,
1,
"0x626c6f63746f",
"0x636c656d656e74"
]
```