Skip to content

Commit 856234c

Browse files
committed
feat: integrated new mee version and refactored tests, docs, etc..
1 parent 12e4e55 commit 856234c

15 files changed

Lines changed: 218 additions & 268 deletions

README.md

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,8 @@ Two patterns exist:
486486

487487
| Pattern | How the value gets into storage | How it is read back |
488488
|---|---|---|
489-
| **Capture** | The composability module writes the return value of a call automatically | `storage.runtimeValue()` injects it; `storage.check()` asserts it; `storage.read()` reads it off-chain |
490-
| **Explicit write** | `storage.write()` — you supply the value at signing time | Same — `storage.runtimeValue()`, `storage.check()`, `storage.read()` |
489+
| **Capture** | The composability module writes the return value of a call automatically | `storage.runtimeValue()` injects it; `storage.check()` asserts it |
490+
| **Explicit write** | `storage.write()` — you supply the value at signing time | Same — `storage.runtimeValue()`, `storage.check()` |
491491

492492
---
493493

@@ -556,11 +556,6 @@ batch.add([
556556
await storage.check({ storageKey, slotIndex: 1, constraints: [{ eq: 21n }] }),
557557
await storage.check({ storageKey, slotIndex: 2, constraints: [{ eq: 1n }] }),
558558
]);
559-
560-
// Off-chain reads after settlement
561-
const sum = await storage.read({ storageKey, slotIndex: 0 });
562-
const product = await storage.read({ storageKey, slotIndex: 1 });
563-
const greater = await storage.read({ storageKey, slotIndex: 2 });
564559
```
565560

566561
#### staticCall capture
@@ -593,10 +588,6 @@ batch.add([
593588
constraints: [{ eq: 12n }],
594589
}),
595590
]);
596-
597-
// Off-chain read after settlement
598-
const captured = await storage.read({ storageKey });
599-
// captured === toBytes32(12n)
600591
```
601592

602593
> **Constraint**: all captured return types must be static ABI types. Dynamic types (`bytes`, `string`, `T[]`) are not supported in captures.
@@ -640,13 +631,6 @@ batch.add([
640631
]);
641632
```
642633

643-
**Off-chain verification** — after the transaction settles, read the slot directly to confirm what was stored:
644-
645-
```ts
646-
const stored = await storage.read({ storageKey });
647-
// stored === toBytes32(amount)
648-
```
649-
650634
`storage.getStorageKey()` returns a unique `bigint` key each time it is called, so multiple storage slots within the same batch never collide.
651635

652636
---
@@ -660,4 +644,4 @@ Detailed SDK reference for each module — all parameters, return types, and foc
660644
| [Batch](./docs/batch.md) | `createComposableBatch` — the entry point. Building, assembling, and serialising a composable batch. |
661645
| [Token](./docs/token.md) | `ERC20TokenInstance` and `NativeTokenInstance` — reads, writes, runtime balances, and allowances. |
662646
| [Contract](./docs/contract.md) | `ContractInstance` — generic contract reads, composable writes, runtime values, captures, and checks. |
663-
| [Storage](./docs/storage.md) | `StorageInstance` — namespace storage reads, writes, runtime values, checks, and slot indexing. |
647+
| [Storage](./docs/storage.md) | `StorageInstance` — namespace storage writes, runtime values, checks, and slot indexing. |

bun.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/storage.md

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -84,40 +84,6 @@ await storage.write({ storageKey, value: 100 }); // numbe
8484

8585
---
8686

87-
### read
88-
89-
Reads the value stored in a slot off-chain. Returns the raw `bytes32` hex value. Use this after the transaction settles to verify what was stored.
90-
91-
```ts
92-
read(params?: {
93-
storageKey?: bigint;
94-
slotIndex?: number; // defaults to 0
95-
accountAddress?: Address;
96-
callerAddress?: Address;
97-
}): Promise<Hex>
98-
```
99-
100-
```ts
101-
const stored = await storage.read({ storageKey });
102-
// stored: '0x000000000000000000000000000000000000000000000000000000003b9aca00'
103-
104-
// Read a specific slot index (for multi-output captures)
105-
const slot0 = await storage.read({ storageKey, slotIndex: 0 });
106-
const slot1 = await storage.read({ storageKey, slotIndex: 1 });
107-
const slot2 = await storage.read({ storageKey, slotIndex: 2 });
108-
```
109-
110-
Use `toBytes32` from the SDK to convert a known value for comparison:
111-
112-
```ts
113-
import { toBytes32 } from 'smart-batching';
114-
115-
const stored = await storage.read({ storageKey });
116-
console.log(stored === toBytes32(parseUnits('10', 6))); // true
117-
```
118-
119-
---
120-
12187
### runtimeValue
12288

12389
Returns a `RuntimeValue` that resolves to the value in a storage slot at execution time. Pass it as an argument to any `write` call that follows the slot being populated.
@@ -281,9 +247,4 @@ myContract.write({
281247
await storage.check({ storageKey, slotIndex: 0, constraints: [{ eq: 10n }] }),
282248
await storage.check({ storageKey, slotIndex: 1, constraints: [{ eq: 21n }] }),
283249
await storage.check({ storageKey, slotIndex: 2, constraints: [{ eq: 1n }] }),
284-
285-
// Off-chain verification
286-
const sum = await storage.read({ storageKey, slotIndex: 0 });
287-
const product = await storage.read({ storageKey, slotIndex: 1 });
288-
const greater = await storage.read({ storageKey, slotIndex: 2 });
289250
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"version": "changeset version"
3939
},
4040
"devDependencies": {
41-
"@biconomy/abstractjs": "^1.2.3",
41+
"@biconomy/abstractjs": "^1.2.4",
4242
"@biomejs/biome": "2.4.9",
4343
"@changesets/cli": "2.30.0",
4444
"@commitlint/cli": "^20.5.0",

src/core/encoding/encoding.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { encodeAbiParameters, getAddress } from 'viem';
1+
import { encodeAbiParameters, getAddress, parseUnits } from 'viem';
22
import { describe, expect, it } from 'vitest';
33
import {
44
equalTo,
@@ -560,4 +560,21 @@ describe('validateAndProcessConstraints — OR', () => {
560560
validateAndProcessConstraints([orConstraint([greaterThanOrEqualTo(-1n)])]),
561561
).toThrow('Invalid constraint value');
562562
});
563+
564+
it("OR with two signed subs preserves two's-complement encoding for negative values", () => {
565+
const ONE_USDC = parseUnits('1', 6);
566+
567+
const [c] = validateAndProcessConstraints([
568+
orConstraint([greaterThanOrEqualToSigned(-1n), lessThanOrEqualToSigned(ONE_USDC)]),
569+
]);
570+
571+
expect(c.constraintType).toBe(ConstraintType.OR);
572+
expect(c.referenceData).toMatch(/^0x[0-9a-f]+$/i);
573+
574+
// int256(-1) in two's complement = 0xffff...ff (32 bytes all set).
575+
// Verifies the referenceData contains these bytes — unsigned arithmetic would
576+
// encode -1 as a very different positive value.
577+
const negOneHex = 'f'.repeat(64);
578+
expect(c.referenceData.toLowerCase()).toContain(negOneHex);
579+
});
563580
});

src/core/storage/abi.ts

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,56 @@
11
import type { Abi } from 'viem';
22

33
export const NAMESPACE_STORAGE_ABI: Abi = [
4+
{ inputs: [], name: 'SlotNotInitialized', type: 'error' },
45
{
56
inputs: [
6-
{
7-
internalType: 'bytes32',
8-
name: 'slot',
9-
type: 'bytes32',
10-
},
11-
{
12-
internalType: 'bytes32',
13-
name: 'value',
14-
type: 'bytes32',
15-
},
16-
{
17-
internalType: 'address',
18-
name: 'account',
19-
type: 'address',
20-
},
7+
{ internalType: 'address', name: 'account', type: 'address' },
8+
{ internalType: 'address', name: 'caller', type: 'address' },
219
],
22-
name: 'writeStorage',
23-
outputs: [],
24-
stateMutability: 'nonpayable',
10+
name: 'getNamespace',
11+
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
12+
stateMutability: 'pure',
2513
type: 'function',
2614
},
2715
{
2816
inputs: [
29-
{
30-
internalType: 'bytes32',
31-
name: 'namespace',
32-
type: 'bytes32',
33-
},
34-
{
35-
internalType: 'bytes32',
36-
name: 'slot',
37-
type: 'bytes32',
38-
},
17+
{ internalType: 'bytes32', name: 'namespace', type: 'bytes32' },
18+
{ internalType: 'bytes32', name: 'slot', type: 'bytes32' },
3919
],
40-
name: 'readStorage',
41-
outputs: [
42-
{
43-
internalType: 'bytes32',
44-
name: '',
45-
type: 'bytes32',
46-
},
20+
name: 'getNamespacedSlot',
21+
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
22+
stateMutability: 'pure',
23+
type: 'function',
24+
},
25+
{
26+
inputs: [
27+
{ internalType: 'bytes32', name: 'namespace', type: 'bytes32' },
28+
{ internalType: 'bytes32', name: 'slot', type: 'bytes32' },
4729
],
30+
name: 'isSlotInitialized',
31+
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
4832
stateMutability: 'view',
4933
type: 'function',
5034
},
35+
{
36+
inputs: [
37+
{ internalType: 'bytes32', name: 'namespace', type: 'bytes32' },
38+
{ internalType: 'bytes32', name: 'slot', type: 'bytes32' },
39+
],
40+
name: 'readStorage',
41+
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
42+
stateMutability: 'view',
43+
type: 'function',
44+
},
45+
{
46+
inputs: [
47+
{ internalType: 'bytes32', name: 'slot', type: 'bytes32' },
48+
{ internalType: 'bytes32', name: 'value', type: 'bytes32' },
49+
{ internalType: 'address', name: 'account', type: 'address' },
50+
],
51+
name: 'writeStorage',
52+
outputs: [],
53+
stateMutability: 'nonpayable',
54+
type: 'function',
55+
},
5156
];

src/core/storage/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import type { Address } from 'viem';
22

33
// Storage contract
44
export const NAMESPACE_STORAGE_CONTRACT_ADDRESS =
5-
'0x0000000671eb337E12fe5dB0e788F32e1D71B183' as Address;
5+
'0x00008211dea1Aca67ac55fc44AE3bF88CF41281d' as Address;

src/core/storage/storage.test.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -198,22 +198,6 @@ describe('storage — write', () => {
198198
});
199199
});
200200

201-
// ---------------------------------------------------------------------------
202-
// storage — read
203-
// ---------------------------------------------------------------------------
204-
// readStorage is publicly readable by anyone — only writes are access-guarded.
205-
// The contract reverts when reading a slot that has never been written to.
206-
// Live read of an initialized slot is covered by the integration test.
207-
208-
describe('storage — read', () => {
209-
const instance = createStorage(publicClient, ACCOUNT);
210-
211-
it('rejects for an uninitialized slot', async () => {
212-
// The contract reverts when the slot has no data written to it yet
213-
await expect(instance.read({ storageKey: 999999999999999n })).rejects.toThrow();
214-
});
215-
});
216-
217201
// ---------------------------------------------------------------------------
218202
// storage — runtimeValue
219203
// ---------------------------------------------------------------------------

src/core/storage/storage.ts

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { getStorageNamespace, getStorageSlot, getStorageSlotKey } from './slot';
77
import type {
88
CheckStorageParams,
99
GetStorageKeyParams,
10-
ReadStorageParams,
1110
RuntimeValueStorageParams,
1211
StorageInstance,
1312
WriteStorageParams,
@@ -40,29 +39,6 @@ export function createStorage<
4039
return getStorageSlotKey(resolvedAccountAddress, resolvedCallerAddress);
4140
},
4241

43-
async read({
44-
storageKey,
45-
slotIndex = 0,
46-
accountAddress: accountAddressOverride,
47-
callerAddress: callerAddressOverride,
48-
}: ReadStorageParams = {}) {
49-
const resolvedAccountAddress = accountAddressOverride ?? accountAddress;
50-
const resolvedCallerAddress = callerAddressOverride ?? resolvedAccountAddress;
51-
52-
const slot = await getStorageSlot(
53-
resolvedAccountAddress,
54-
resolvedCallerAddress,
55-
storageKey,
56-
slotIndex,
57-
);
58-
const namespace = getStorageNamespace(resolvedAccountAddress, resolvedCallerAddress);
59-
60-
return contractInstance.read({
61-
functionName: 'readStorage',
62-
args: [namespace, slot],
63-
}) as Promise<`0x${string}`>;
64-
},
65-
6642
async write({
6743
value,
6844
storageKey,

src/core/storage/types.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Address, Hex } from 'viem';
1+
import type { Address } from 'viem';
22
import type { ComposableCall, RuntimeConstraint, RuntimeValue } from '../encoding';
33
import type { Bytes32SupportedType } from '../encoding/utils';
44

@@ -26,13 +26,6 @@ export interface CheckStorageParams {
2626
callerAddress?: Address;
2727
}
2828

29-
export interface ReadStorageParams {
30-
storageKey?: bigint;
31-
slotIndex?: number;
32-
accountAddress?: Address;
33-
callerAddress?: Address;
34-
}
35-
3629
export interface GetStorageKeyParams {
3730
accountAddress?: Address;
3831
callerAddress?: Address;
@@ -41,7 +34,6 @@ export interface GetStorageKeyParams {
4134
export interface StorageInstance {
4235
readonly accountAddress: Address;
4336
getStorageKey(params?: GetStorageKeyParams): Promise<bigint>;
44-
read(params?: ReadStorageParams): Promise<Hex>;
4537
write(params: WriteStorageParams): Promise<ComposableCall>;
4638
runtimeValue(params?: RuntimeValueStorageParams): Promise<RuntimeValue>;
4739
check(params: CheckStorageParams): Promise<ComposableCall>;

0 commit comments

Comments
 (0)