@@ -11,6 +11,9 @@ contract BatcherPaymentService is
1111 PausableUpgradeable ,
1212 UUPSUpgradeable
1313{
14+ // CONSTANTS
15+ uint256 public constant UNLOCK_BLOCK_COUNT = 100 ;
16+
1417 // EVENTS
1518 event PaymentReceived (address indexed sender , uint256 amount );
1619 event FundsWithdrawn (address indexed recipient , uint256 amount );
@@ -22,14 +25,18 @@ contract BatcherPaymentService is
2225 uint256 nonce;
2326 }
2427
28+ struct UserInfo {
29+ uint256 balance;
30+ uint256 unlockBlock;
31+ uint256 nonce;
32+ }
33+
2534 // STORAGE
2635 address public AlignedLayerServiceManager;
2736 address public BatcherWallet;
2837
29- mapping (address => uint256 ) public UserBalances;
30-
31- // map to check signature is only submitted once
32- mapping (address => uint256 ) public UserNonces;
38+ // map to user data
39+ mapping (address => UserInfo) public UserData;
3340
3441 // storage gap for upgradeability
3542 uint256 [24 ] private __GAP;
@@ -54,7 +61,7 @@ contract BatcherPaymentService is
5461
5562 // PAYABLE FUNCTIONS
5663 receive () external payable {
57- UserBalances [msg .sender ] += msg .value ;
64+ UserData [msg .sender ].balance += msg .value ;
5865 emit PaymentReceived (msg .sender , msg .value );
5966 }
6067
@@ -114,12 +121,30 @@ contract BatcherPaymentService is
114121 );
115122 }
116123
124+ function unlock () external whenNotPaused {
125+ require (
126+ UserData[msg .sender ].balance > 0 ,
127+ "User has no funds to unlock "
128+ );
129+
130+ UserData[msg .sender ].unlockBlock = block .number + UNLOCK_BLOCK_COUNT;
131+ }
132+
133+ function lock () external whenNotPaused {
134+ require (UserData[msg .sender ].balance > 0 , "User has no funds to lock " );
135+ UserData[msg .sender ].unlockBlock = 0 ;
136+ }
137+
117138 function withdraw (uint256 amount ) external whenNotPaused {
139+ UserInfo storage user_data = UserData[msg .sender ];
140+ require (user_data.balance >= amount, "Payer has insufficient balance " );
141+
118142 require (
119- UserBalances[ msg . sender ] >= amount ,
120- "Payer has insufficient balance "
143+ user_data.unlockBlock != 0 && user_data.unlockBlock <= block . number ,
144+ "Funds are locked "
121145 );
122- UserBalances[msg .sender ] -= amount;
146+
147+ user_data.balance -= amount;
123148 payable (msg .sender ).transfer (amount);
124149 emit FundsWithdrawn (msg .sender , amount);
125150 }
@@ -163,12 +188,20 @@ contract BatcherPaymentService is
163188 abi.encodePacked (leaves[2 * i], leaves[2 * i + 1 ])
164189 );
165190
166- verifySignatureAndDecreaseBalance (leaves[i], signatures[i], feePerProof);
191+ verifySignatureAndDecreaseBalance (
192+ leaves[i],
193+ signatures[i],
194+ feePerProof
195+ );
167196 }
168197
169198 // Verify the rest of the signatures
170199 for (; i < signatures.length ; i++ ) {
171- verifySignatureAndDecreaseBalance (leaves[i], signatures[i], feePerProof);
200+ verifySignatureAndDecreaseBalance (
201+ leaves[i],
202+ signatures[i],
203+ feePerProof
204+ );
172205 }
173206
174207 // The next layer above has half as many nodes
@@ -210,13 +243,28 @@ contract BatcherPaymentService is
210243 signatureData.s
211244 );
212245
213- require (UserNonces[signer] == signatureData.nonce, "Invalid Nonce " );
214- UserNonces[signer]++ ;
246+ UserInfo storage user_data = UserData[signer];
247+
248+ require (user_data.nonce == signatureData.nonce, "Invalid Nonce " );
249+ user_data.nonce++ ;
215250
216251 require (
217- UserBalances[signer] >= feePerProof,
252+ user_data.balance >= feePerProof,
218253 "Signer has insufficient balance "
219254 );
220- UserBalances[signer] -= feePerProof;
255+
256+ user_data.balance -= feePerProof;
257+ }
258+
259+ function user_balances (address account ) public view returns (uint256 ) {
260+ return UserData[account].balance;
261+ }
262+
263+ function user_nonces (address account ) public view returns (uint256 ) {
264+ return UserData[account].nonce;
265+ }
266+
267+ function user_unlock_block (address account ) public view returns (uint256 ) {
268+ return UserData[account].unlockBlock;
221269 }
222270}
0 commit comments