@@ -200,147 +200,149 @@ describe('Delegated user decryption', function () {
200200 expect ( Number ( decryptedBalanceBefore ) - Number ( decryptedBalanceAfter ) ) . to . equal ( Number ( transferAmount ) ) ;
201201 } ) ;
202202
203- it ( 'test delegated user decryption - smartWallet revokes the delegation of user decryption to an EOA' , async function ( ) {
204- // First, ensure Bob has delegation.
205- const expirationTimestamp = Math . floor ( Date . now ( ) / 1000 ) + 86400 ;
206- const delegateTx = await this . smartWallet
207- . connect ( this . signers . bob )
208- . delegateUserDecryption (
209- this . signers . bob . address ,
210- this . tokenAddress ,
211- expirationTimestamp ,
212- ) ;
213- await delegateTx . wait ( ) ;
214-
215- // Wait for 15 blocks to ensure delegation is propagated by the coprocessor.
216- const currentBlock1 = await ethers . provider . getBlockNumber ( ) ;
217- await waitForBlock ( currentBlock1 + 15 ) ;
218-
219- // Revoke the delegation for Bob's EOA.
220- const revokeTx = await this . smartWallet
221- . connect ( this . signers . bob )
222- . revokeUserDecryptionDelegation (
223- this . signers . bob . address ,
224- this . tokenAddress ,
225- ) ;
226- await revokeTx . wait ( ) ;
227-
228- // Wait for 15 blocks to ensure revocation is propagated by the coprocessor.
229- const currentBlock2 = await ethers . provider . getBlockNumber ( ) ;
230- await waitForBlock ( currentBlock2 + 15 ) ;
231-
232- // Try to decrypt the smartWallet balance with Bob's EOA, which should now fail.
233- const balanceHandle = await this . token . balanceOf ( this . smartWalletAddress ) ;
234- const { publicKey, privateKey } = this . instances . bob . generateKeypair ( ) ;
235-
236- try {
237- await delegatedUserDecryptSingleHandle (
238- this . instances . bob ,
239- balanceHandle ,
240- this . tokenAddress ,
241- this . smartWalletAddress ,
242- this . signers . bob . address ,
243- this . signers . bob ,
244- privateKey ,
245- publicKey ,
246- ) ;
247- expect . fail ( 'Expected delegated user decrypt to be rejected after revocation' ) ;
248- } catch ( err : any ) {
249- expect ( err . relayerApiError ?. label ) . to . equal ( NOT_ALLOWED_ON_HOST_ACL ) ;
250- }
251- } ) ;
252-
253- it ( 'test delegated user decryption should fail when no delegation exists' , async function ( ) {
254- const balanceHandle = await this . token . balanceOf ( this . smartWalletAddress ) ;
255- const { publicKey, privateKey } = this . instances . dave . generateKeypair ( ) ;
256-
257- try {
258- await delegatedUserDecryptSingleHandle (
259- this . instances . dave ,
260- balanceHandle ,
261- this . tokenAddress ,
262- this . smartWalletAddress ,
263- this . signers . dave . address ,
264- this . signers . dave ,
265- privateKey ,
266- publicKey ,
267- ) ;
268- expect . fail ( 'Expected delegated user decrypt to be rejected without delegation' ) ;
269- } catch ( err : any ) {
270- expect ( err . relayerApiError ?. label ) . to . equal ( NOT_ALLOWED_ON_HOST_ACL ) ;
271- }
272- } ) ;
273-
274- it ( 'test delegated user decryption should fail when delegation is for wrong contract' , async function ( ) {
275- const dummyFactory = await ethers . getContractFactory ( 'UserDecrypt' ) ;
276- const dummy = await dummyFactory . connect ( this . signers . alice ) . deploy ( ) ;
277- await dummy . waitForDeployment ( ) ;
278- const wrongAddress = await dummy . getAddress ( ) ;
279-
280- const expirationTimestamp = Math . floor ( Date . now ( ) / 1000 ) + 86400 ;
281- const tx = await this . smartWallet
282- . connect ( this . signers . bob )
283- . delegateUserDecryption ( this . signers . eve . address , wrongAddress , expirationTimestamp ) ;
284- await tx . wait ( ) ;
285- const currentBlock = await ethers . provider . getBlockNumber ( ) ;
286- await waitForBlock ( currentBlock + 15 ) ;
287-
288- const balanceHandle = await this . token . balanceOf ( this . smartWalletAddress ) ;
289- const { publicKey, privateKey } = this . instances . eve . generateKeypair ( ) ;
290-
291- try {
292- await delegatedUserDecryptSingleHandle (
293- this . instances . eve ,
294- balanceHandle ,
295- this . tokenAddress ,
296- this . smartWalletAddress ,
297- this . signers . eve . address ,
298- this . signers . eve ,
299- privateKey ,
300- publicKey ,
301- ) ;
302- expect . fail ( 'Expected delegated user decrypt to be rejected for wrong contract' ) ;
303- } catch ( err : any ) {
304- expect ( err . relayerApiError ?. label ) . to . equal ( NOT_ALLOWED_ON_HOST_ACL ) ;
305- }
306- } ) ;
307-
308- it ( 'test delegated user decryption should fail when delegation has expired' , async function ( ) {
309- // Expiration must be >1h from chain time (FHE library constraint).
310- // Use block timestamp, not Date.now(), since evm_increaseTime shifts chain clock.
311- const oneHour = 3600 ;
312- const buffer = 60 ;
313- const latestBlock = await ethers . provider . getBlock ( 'latest' ) ;
314- const expirationTimestamp = latestBlock ! . timestamp + oneHour + buffer ;
315- const tx = await this . smartWallet
316- . connect ( this . signers . bob )
317- . delegateUserDecryption ( this . signers . eve . address , this . tokenAddress , expirationTimestamp ) ;
318- await tx . wait ( ) ;
319-
320- // Fast-forward time past the expiration.
321- await ethers . provider . send ( 'evm_increaseTime' , [ oneHour + buffer + 1 ] ) ;
322- await ethers . provider . send ( 'evm_mine' , [ ] ) ;
323-
324- const currentBlock = await ethers . provider . getBlockNumber ( ) ;
325- await waitForBlock ( currentBlock + 15 ) ;
326-
327- const balanceHandle = await this . token . balanceOf ( this . smartWalletAddress ) ;
328- const { publicKey, privateKey } = this . instances . eve . generateKeypair ( ) ;
329-
330- try {
331- await delegatedUserDecryptSingleHandle (
332- this . instances . eve ,
333- balanceHandle ,
334- this . tokenAddress ,
335- this . smartWalletAddress ,
336- this . signers . eve . address ,
337- this . signers . eve ,
338- privateKey ,
339- publicKey ,
340- ) ;
341- expect . fail ( 'Expected delegated user decrypt to be rejected for expired delegation' ) ;
342- } catch ( err : any ) {
343- expect ( err . relayerApiError ?. label ) . to . equal ( NOT_ALLOWED_ON_HOST_ACL ) ;
344- }
203+ describe ( 'negative-acl' , function ( ) {
204+ it ( 'should reject when delegation has been revoked' , async function ( ) {
205+ // First, ensure Bob has delegation.
206+ const expirationTimestamp = Math . floor ( Date . now ( ) / 1000 ) + 86400 ;
207+ const delegateTx = await this . smartWallet
208+ . connect ( this . signers . bob )
209+ . delegateUserDecryption (
210+ this . signers . bob . address ,
211+ this . tokenAddress ,
212+ expirationTimestamp ,
213+ ) ;
214+ await delegateTx . wait ( ) ;
215+
216+ // Wait for 15 blocks to ensure delegation is propagated by the coprocessor.
217+ const currentBlock1 = await ethers . provider . getBlockNumber ( ) ;
218+ await waitForBlock ( currentBlock1 + 15 ) ;
219+
220+ // Revoke the delegation for Bob's EOA.
221+ const revokeTx = await this . smartWallet
222+ . connect ( this . signers . bob )
223+ . revokeUserDecryptionDelegation (
224+ this . signers . bob . address ,
225+ this . tokenAddress ,
226+ ) ;
227+ await revokeTx . wait ( ) ;
228+
229+ // Wait for 15 blocks to ensure revocation is propagated by the coprocessor.
230+ const currentBlock2 = await ethers . provider . getBlockNumber ( ) ;
231+ await waitForBlock ( currentBlock2 + 15 ) ;
232+
233+ // Try to decrypt the smartWallet balance with Bob's EOA, which should now fail.
234+ const balanceHandle = await this . token . balanceOf ( this . smartWalletAddress ) ;
235+ const { publicKey, privateKey } = this . instances . bob . generateKeypair ( ) ;
236+
237+ try {
238+ await delegatedUserDecryptSingleHandle (
239+ this . instances . bob ,
240+ balanceHandle ,
241+ this . tokenAddress ,
242+ this . smartWalletAddress ,
243+ this . signers . bob . address ,
244+ this . signers . bob ,
245+ privateKey ,
246+ publicKey ,
247+ ) ;
248+ expect . fail ( 'Expected delegated user decrypt to be rejected after revocation' ) ;
249+ } catch ( err : any ) {
250+ expect ( err . relayerApiError ?. label ) . to . equal ( NOT_ALLOWED_ON_HOST_ACL ) ;
251+ }
252+ } ) ;
253+
254+ it ( 'should reject when no delegation exists' , async function ( ) {
255+ const balanceHandle = await this . token . balanceOf ( this . smartWalletAddress ) ;
256+ const { publicKey, privateKey } = this . instances . dave . generateKeypair ( ) ;
257+
258+ try {
259+ await delegatedUserDecryptSingleHandle (
260+ this . instances . dave ,
261+ balanceHandle ,
262+ this . tokenAddress ,
263+ this . smartWalletAddress ,
264+ this . signers . dave . address ,
265+ this . signers . dave ,
266+ privateKey ,
267+ publicKey ,
268+ ) ;
269+ expect . fail ( 'Expected delegated user decrypt to be rejected without delegation' ) ;
270+ } catch ( err : any ) {
271+ expect ( err . relayerApiError ?. label ) . to . equal ( NOT_ALLOWED_ON_HOST_ACL ) ;
272+ }
273+ } ) ;
274+
275+ it ( 'should reject when delegation is for wrong contract' , async function ( ) {
276+ const dummyFactory = await ethers . getContractFactory ( 'UserDecrypt' ) ;
277+ const dummy = await dummyFactory . connect ( this . signers . alice ) . deploy ( ) ;
278+ await dummy . waitForDeployment ( ) ;
279+ const wrongAddress = await dummy . getAddress ( ) ;
280+
281+ const expirationTimestamp = Math . floor ( Date . now ( ) / 1000 ) + 86400 ;
282+ const tx = await this . smartWallet
283+ . connect ( this . signers . bob )
284+ . delegateUserDecryption ( this . signers . eve . address , wrongAddress , expirationTimestamp ) ;
285+ await tx . wait ( ) ;
286+ const currentBlock = await ethers . provider . getBlockNumber ( ) ;
287+ await waitForBlock ( currentBlock + 15 ) ;
288+
289+ const balanceHandle = await this . token . balanceOf ( this . smartWalletAddress ) ;
290+ const { publicKey, privateKey } = this . instances . eve . generateKeypair ( ) ;
291+
292+ try {
293+ await delegatedUserDecryptSingleHandle (
294+ this . instances . eve ,
295+ balanceHandle ,
296+ this . tokenAddress ,
297+ this . smartWalletAddress ,
298+ this . signers . eve . address ,
299+ this . signers . eve ,
300+ privateKey ,
301+ publicKey ,
302+ ) ;
303+ expect . fail ( 'Expected delegated user decrypt to be rejected for wrong contract' ) ;
304+ } catch ( err : any ) {
305+ expect ( err . relayerApiError ?. label ) . to . equal ( NOT_ALLOWED_ON_HOST_ACL ) ;
306+ }
307+ } ) ;
308+
309+ it ( 'should reject when delegation has expired' , async function ( ) {
310+ // Expiration must be >1h from chain time (FHE library constraint).
311+ // Use block timestamp, not Date.now(), since evm_increaseTime shifts chain clock.
312+ const oneHour = 3600 ;
313+ const buffer = 60 ;
314+ const latestBlock = await ethers . provider . getBlock ( 'latest' ) ;
315+ const expirationTimestamp = latestBlock ! . timestamp + oneHour + buffer ;
316+ const tx = await this . smartWallet
317+ . connect ( this . signers . bob )
318+ . delegateUserDecryption ( this . signers . eve . address , this . tokenAddress , expirationTimestamp ) ;
319+ await tx . wait ( ) ;
320+
321+ // Fast-forward time past the expiration.
322+ await ethers . provider . send ( 'evm_increaseTime' , [ oneHour + buffer + 1 ] ) ;
323+ await ethers . provider . send ( 'evm_mine' , [ ] ) ;
324+
325+ const currentBlock = await ethers . provider . getBlockNumber ( ) ;
326+ await waitForBlock ( currentBlock + 15 ) ;
327+
328+ const balanceHandle = await this . token . balanceOf ( this . smartWalletAddress ) ;
329+ const { publicKey, privateKey } = this . instances . eve . generateKeypair ( ) ;
330+
331+ try {
332+ await delegatedUserDecryptSingleHandle (
333+ this . instances . eve ,
334+ balanceHandle ,
335+ this . tokenAddress ,
336+ this . smartWalletAddress ,
337+ this . signers . eve . address ,
338+ this . signers . eve ,
339+ privateKey ,
340+ publicKey ,
341+ ) ;
342+ expect . fail ( 'Expected delegated user decrypt to be rejected for expired delegation' ) ;
343+ } catch ( err : any ) {
344+ expect ( err . relayerApiError ?. label ) . to . equal ( NOT_ALLOWED_ON_HOST_ACL ) ;
345+ }
346+ } ) ;
345347 } ) ;
346348} ) ;
0 commit comments