|
2 | 2 | createMeeClient, |
3 | 3 | getMEEVersion, |
4 | 4 | MEEVersion, |
| 5 | + toBytes32, |
5 | 6 | toMultichainNexusAccount, |
6 | 7 | } from '@biconomy/abstractjs'; |
7 | 8 | import { erc20Abi, getAddress, http } from 'viem'; |
@@ -167,4 +168,61 @@ describe('Integration — Biconomy abstractjs composable execution', () => { |
167 | 168 | 'UserOp [1] simulation failed. Revert reason: Execution reverted at contract 0x0000000020fe2f30453074ad916edeb653ec7e9d and reverted with error selector 0xa31844b0', |
168 | 169 | ); |
169 | 170 | }); |
| 171 | + |
| 172 | + it('write value to namespace storage → use as runtime transfer amount → sweep remainder', async () => { |
| 173 | + // 1. Init Nexus SCA on Base Sepolia and resolve its address + MEE client |
| 174 | + const { scaAddress, meeClient } = await initNexus(); |
| 175 | + |
| 176 | + // 2. Fund SCA: EOA transfers mock USDC to the SCA and waits for 2 confirmations |
| 177 | + const fundTxHash = await _walletClient.writeContract({ |
| 178 | + abi: erc20Abi, |
| 179 | + address: USDC, |
| 180 | + functionName: 'transfer', |
| 181 | + args: [scaAddress, FUND_AMOUNT], |
| 182 | + }); |
| 183 | + |
| 184 | + await publicClient.waitForTransactionReceipt({ |
| 185 | + hash: fundTxHash, |
| 186 | + confirmations: 2, |
| 187 | + }); |
| 188 | + |
| 189 | + // 3. Build composable batch: write storage → check storage → partial transfer → sweep remainder |
| 190 | + const batch = ComposableBatch(publicClient, scaAddress); |
| 191 | + const usdc = batch.erc20Token(USDC); |
| 192 | + const storage = batch.storage(); |
| 193 | + |
| 194 | + // Pre-generate a storage key so all storage operations share the same slot |
| 195 | + const storageValue = FUND_AMOUNT / 2n; |
| 196 | + const storageKey = await storage.getStorageKey(); |
| 197 | + |
| 198 | + batch.add([ |
| 199 | + // Step A: write FUND_AMOUNT/2 into the shared namespace storage slot |
| 200 | + await storage.write({ value: storageValue, storageKey }), |
| 201 | + // Step B: assert the stored value equals what was just written before proceeding |
| 202 | + await storage.check({ storageKey, constraints: [{ eq: storageValue }] }), |
| 203 | + // Step C: transfer the runtime-resolved storage value (FUND_AMOUNT/2) from SCA to EOA |
| 204 | + usdc.write({ |
| 205 | + functionName: 'transfer', |
| 206 | + args: [_account.address, await storage.runtimeValue({ storageKey })], |
| 207 | + }), |
| 208 | + // Step D: sweep any remaining SCA balance (the other half) to the EOA |
| 209 | + usdc.write({ functionName: 'transfer', args: [_account.address, usdc.runtimeBalance()] }), |
| 210 | + ]); |
| 211 | + |
| 212 | + expect(batch.length).toBe(4); |
| 213 | + |
| 214 | + // 4. Get a quote for the composable instruction, then sign and submit it via MEE |
| 215 | + const quote = await meeClient.getQuote({ |
| 216 | + instructions: [{ calls: batch.calls, chainId: baseSepolia.id, isComposable: true }], |
| 217 | + simulation: { simulate: true }, |
| 218 | + feeToken: { address: USDC, chainId: baseSepolia.id }, |
| 219 | + }); |
| 220 | + |
| 221 | + // 5. Execute the signed quote and wait for the supertransaction to settle |
| 222 | + const { hash } = await meeClient.executeQuote({ quote }); |
| 223 | + await meeClient.waitForSupertransactionReceipt({ hash }); |
| 224 | + |
| 225 | + // 6. Assert the on-chain storage slot holds the value that was written in step A |
| 226 | + expect(await storage.read({ storageKey })).to.eq(toBytes32(storageValue)); |
| 227 | + }); |
170 | 228 | }); |
0 commit comments