---
tags: ZK,Bundler-Design
---
# Bundler anti-replay attack scheme (researching)
## background
In the account abstraction of 4337, in order to prevent replay attacks, a nonce variable is introduced into the AA wallet contract, which must be updated every time Tx is executed, thereby increasing the Gas overhead
## direction:
- We need to meet our anti-replay attack requirements in a relatively Gas-saving way
- Combining Tx's nonce + chainId two fields
- The nonce in the tx of each account should increase monotonically by +1
- chainId is bound to the corresponding network
- It can be solved by adding chainId to the off-chain signature parameter, and using block.chainId to calculate the hash comparison on the chain
## plan
- The correctness of the nonce of the user Tx is guaranteed by ZKP
- The EP contract does not need to maintain the nonce for each user separately, but maintains two StateHash and RecrusiveStateHash values ββin the Verify contract (great gas savings)
StateHash, RecrusiveStateHash iterative maintenance process

## Questions to be confirmed
- Performance improvement of off-chain ZKP
- Need to choose the appropriate merkel data structure
- Process security audit (not found yet)
- DA problem with user Nonce
- The user's actual nonce is all stored off-chain, and nodes need to ensure data availability
- When the EP contract executes Tx, it needs to log a nonce, which is convenient for users to build the state of the nonce by themselves β by Wen Bo
## Pseudocode description
Prove process circom syntax description:
```
signal input UserAddress[N];
signal input CurUserNonce[N];
signal input CurRecrusiveStateHash;
signal input PreRecrusiveStateHash;
signal input CurStateHash;
signal input NewUserNonce[N];
signal output NewRecrusiveStateHash;
signal output NewStateHash;
signal output PubCurStateHash;
signal output PubCurRecrusiveStateHash;
assert(MerkelHash(CurUserNonce[N]) == CurHash);
assert(Hash(PreRecrusiveStateHash, CurHash) == CurRecrusiveStateHash);
for(var i = 0; i < N;i ++) {
assert(CurUserNonce[i] + 1 == NewUserNonce[i]);
}
NewStateHash <== MerkelHash(NewUserNonce[N]);
NewRecrusiveStateHash <== Hash(CurRecrusiveStateHash, NewStateHash);
PubCurStateHash <== MerkleHash(CurUserNonce[N]);
PubCurRecrusiveStateHash <== CurRecrusiveStateHash;
```
Prove results:
```
ProofData;
PublicInputs:{
NewStateHash,
NewRecrusiveStateHash,
PubCurStateHash,
PubCurRecrusiveStateHash,
}
```
The process of updating the status after Verify (EVM environment):
```
require(Verify(ProofData,PublicInputs)==True);
require(self.CurStateHash == PublicInputs.PubCurStateHash);
require(self.CurRecrusiveStateHash == PublicInputs.PubCurRecrusiveStateHash);
self.CurStateHash = PublicInputs.NewStateHash;
self.CurRecrusiveStateHash = PublicInputs.PubCurRecrusiveStateHash;
```