@0xmonaco/contracts 1.0.47 → 1.0.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/sweeper.d.ts +56 -6
- package/dist/sweeper.js +43 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type Hex, predictSweeperAddress, type SweeperAddressInput, sweeperCloneInitCode, sweeperImmutableArgs } from "./sweeper";
|
|
1
|
+
export { type DepositTarget, encodeDepositApplicationData, type Hex, predictSweeperAddress, type SweeperAddressInput, sweeperCloneInitCode, sweeperImmutableArgs, } from "./sweeper";
|
|
2
2
|
/**
|
|
3
3
|
* Contract ABIs for all protocol contracts.
|
|
4
4
|
* These ABIs are used to interact with the deployed contracts.
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* for all Monaco protocol contracts.
|
|
7
7
|
*/
|
|
8
8
|
import { SWEEPER_ABI, SWEEPER_FACTORY_ABI, VAULT_ABI } from "./abis";
|
|
9
|
-
export { predictSweeperAddress, sweeperCloneInitCode, sweeperImmutableArgs } from "./sweeper";
|
|
9
|
+
export { encodeDepositApplicationData, predictSweeperAddress, sweeperCloneInitCode, sweeperImmutableArgs, } from "./sweeper";
|
|
10
10
|
/**
|
|
11
11
|
* Contract ABIs for all protocol contracts.
|
|
12
12
|
* These ABIs are used to interact with the deployed contracts.
|
package/dist/sweeper.d.ts
CHANGED
|
@@ -2,17 +2,56 @@
|
|
|
2
2
|
* Off-chain derivation of Monaco sweeper deposit addresses.
|
|
3
3
|
*
|
|
4
4
|
* A sweeper is an EIP-1167 clone deployed by `SweeperFactory` at a CREATE2
|
|
5
|
-
* address determined by the (clientId, user)
|
|
6
|
-
* can therefore be shown to a user — and funded — before
|
|
7
|
-
* there, without an RPC round trip.
|
|
5
|
+
* address determined by the (clientId, user, deposit target) triple it is
|
|
6
|
+
* bound to. The address can therefore be shown to a user — and funded — before
|
|
7
|
+
* any contract exists there, without an RPC round trip.
|
|
8
8
|
*
|
|
9
9
|
* The client id is the application's identifier as used for rollup deposits
|
|
10
10
|
* (the string `sdk.login` takes). It is hashed **byte-for-byte**: two
|
|
11
11
|
* spellings derive two different, both-valid addresses, so the exact string
|
|
12
12
|
* of the registered application must be used — the backend rejects unknown
|
|
13
13
|
* spellings at registration because the lookup is an exact match.
|
|
14
|
+
*
|
|
15
|
+
* The deposit target is hashed the same way, through the encoding in
|
|
16
|
+
* {@link encodeDepositApplicationData}, so `"spot"` and `"margin"` are two
|
|
17
|
+
* different addresses for one application and user, each carrying its own
|
|
18
|
+
* target. A `"spot"` address is never credited to margin.
|
|
19
|
+
*
|
|
20
|
+
* The reverse is not absolute: `"margin"` is a routing *request*. A deposit the
|
|
21
|
+
* backend cannot route to collateral — an unsupported collateral asset, or a
|
|
22
|
+
* margin account that fails validation — is credited to the spot wallet
|
|
23
|
+
* instead, so funds are never stranded. Derivation fixes which request the
|
|
24
|
+
* address carries, not which ledger the credit ultimately lands in.
|
|
14
25
|
*/
|
|
15
26
|
export type Hex = `0x${string}`;
|
|
27
|
+
/**
|
|
28
|
+
* Which ledger a deposit asks to be credited to.
|
|
29
|
+
*
|
|
30
|
+
* `"spot"` credits the spot wallet; `"margin"` asks for the parent margin
|
|
31
|
+
* account's collateral. The target is part of the sweeper address derivation,
|
|
32
|
+
* so the same pair has one deposit address per target.
|
|
33
|
+
*
|
|
34
|
+
* `"margin"` is a request: a deposit the backend cannot route to collateral
|
|
35
|
+
* falls back to the spot wallet rather than being stranded.
|
|
36
|
+
*/
|
|
37
|
+
export type DepositTarget = "spot" | "margin";
|
|
38
|
+
/**
|
|
39
|
+
* Encodes the on-chain `applicationData` a deposit carries.
|
|
40
|
+
*
|
|
41
|
+
* Spot is the identity encoding — the bare client id, byte for byte. Not a
|
|
42
|
+
* shortcut but a compatibility requirement: the deposit address is a hash of
|
|
43
|
+
* this string, so encoding spot any other way would move every address already
|
|
44
|
+
* published to a user.
|
|
45
|
+
*
|
|
46
|
+
* Margin emits the canonical routing payload the backend decodes. It is built
|
|
47
|
+
* with `JSON.stringify` rather than string concatenation so a client id
|
|
48
|
+
* containing a quote, a backslash, or a brace is escaped instead of breaking
|
|
49
|
+
* out of the object. Key order is fixed and part of the derivation.
|
|
50
|
+
*
|
|
51
|
+
* The byte-for-byte counterpart of `encode_application_data` in
|
|
52
|
+
* `utils/src/deposit_routing.rs`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function encodeDepositApplicationData(clientId: string, target: DepositTarget): string;
|
|
16
55
|
export interface SweeperAddressInput {
|
|
17
56
|
/** Address of the deployed `SweeperFactory`. */
|
|
18
57
|
factory: string;
|
|
@@ -25,14 +64,25 @@ export interface SweeperAddressInput {
|
|
|
25
64
|
clientId: string;
|
|
26
65
|
/** Address credited on the rollup when the sweeper sweeps. */
|
|
27
66
|
user: string;
|
|
67
|
+
/**
|
|
68
|
+
* Which ledger swept deposits ask to be credited to. Defaults to `"spot"`,
|
|
69
|
+
* which reproduces the derivation from before deposit targets existed.
|
|
70
|
+
*
|
|
71
|
+
* Must match the `depositTarget` the pair was registered with: the target is
|
|
72
|
+
* inside the derivation, so a mismatch derives a real, fundable address that
|
|
73
|
+
* nothing is monitoring. Anything but `"spot"` or `"margin"` throws rather
|
|
74
|
+
* than defaulting, for the same reason.
|
|
75
|
+
*/
|
|
76
|
+
depositTarget?: DepositTarget;
|
|
28
77
|
}
|
|
29
78
|
/**
|
|
30
|
-
* Derives the deposit address for a (clientId, user)
|
|
79
|
+
* Derives the deposit address for a (clientId, user, deposit target) triple.
|
|
31
80
|
*
|
|
32
81
|
* @returns The EIP-55 checksummed sweeper address, deployed or not.
|
|
33
|
-
* @throws If any address is malformed
|
|
82
|
+
* @throws If any address is malformed, the client id is empty, or the deposit
|
|
83
|
+
* target is not exactly `"spot"` or `"margin"`.
|
|
34
84
|
*/
|
|
35
|
-
export declare function predictSweeperAddress({ factory, implementation, clientId, user }: SweeperAddressInput): Hex;
|
|
85
|
+
export declare function predictSweeperAddress({ factory, implementation, clientId, user, depositTarget }: SweeperAddressInput): Hex;
|
|
36
86
|
/**
|
|
37
87
|
* The clone's immutable args: `abi.encode(address user, string clientId)`
|
|
38
88
|
* (the contract calls the string `applicationId`, matching the rollup's
|
package/dist/sweeper.js
CHANGED
|
@@ -14,17 +14,56 @@ const CLONE_RUNTIME_LENGTH = 45;
|
|
|
14
14
|
*/
|
|
15
15
|
const SALT = new Uint8Array(32);
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Encodes the on-chain `applicationData` a deposit carries.
|
|
18
|
+
*
|
|
19
|
+
* Spot is the identity encoding — the bare client id, byte for byte. Not a
|
|
20
|
+
* shortcut but a compatibility requirement: the deposit address is a hash of
|
|
21
|
+
* this string, so encoding spot any other way would move every address already
|
|
22
|
+
* published to a user.
|
|
23
|
+
*
|
|
24
|
+
* Margin emits the canonical routing payload the backend decodes. It is built
|
|
25
|
+
* with `JSON.stringify` rather than string concatenation so a client id
|
|
26
|
+
* containing a quote, a backslash, or a brace is escaped instead of breaking
|
|
27
|
+
* out of the object. Key order is fixed and part of the derivation.
|
|
28
|
+
*
|
|
29
|
+
* The byte-for-byte counterpart of `encode_application_data` in
|
|
30
|
+
* `utils/src/deposit_routing.rs`.
|
|
31
|
+
*/
|
|
32
|
+
export function encodeDepositApplicationData(clientId, target) {
|
|
33
|
+
assertDepositTarget(target);
|
|
34
|
+
return target === "margin" ? JSON.stringify({ clientId, depositTarget: "MARGIN" }) : clientId;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Rejects anything that is not exactly `"spot"` or `"margin"`.
|
|
38
|
+
*
|
|
39
|
+
* Without this, `target === "margin" ? … : …` sends every other value down the
|
|
40
|
+
* spot branch, so an untyped JavaScript caller — or one who passed the wire
|
|
41
|
+
* form `"MARGIN"` copied from the API reference — silently derives a real,
|
|
42
|
+
* fundable **spot** address while believing it is a margin one. That is the
|
|
43
|
+
* same failure the backend refuses with a 400 rather than defaulting, and it is
|
|
44
|
+
* worse here: nothing round-trips through a server to reveal the mistake.
|
|
45
|
+
*/
|
|
46
|
+
function assertDepositTarget(value) {
|
|
47
|
+
if (value !== "spot" && value !== "margin") {
|
|
48
|
+
throw new Error(`Invalid deposit target: ${JSON.stringify(value)}. ` + 'Expected "spot" or "margin" — lowercase, not the wire form "SPOT"/"MARGIN".');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Derives the deposit address for a (clientId, user, deposit target) triple.
|
|
18
53
|
*
|
|
19
54
|
* @returns The EIP-55 checksummed sweeper address, deployed or not.
|
|
20
|
-
* @throws If any address is malformed
|
|
55
|
+
* @throws If any address is malformed, the client id is empty, or the deposit
|
|
56
|
+
* target is not exactly `"spot"` or `"margin"`.
|
|
21
57
|
*/
|
|
22
|
-
export function predictSweeperAddress({ factory, implementation, clientId, user }) {
|
|
58
|
+
export function predictSweeperAddress({ factory, implementation, clientId, user, depositTarget = "spot" }) {
|
|
23
59
|
const factoryAddress = assertAddress(factory, "factory");
|
|
24
60
|
const implementationAddress = assertAddress(implementation, "implementation");
|
|
25
61
|
const userAddress = assertNonZeroUser(assertAddress(user, "user"));
|
|
26
62
|
assertClientId(clientId);
|
|
27
|
-
|
|
63
|
+
// The bound string is the encoded application data, not the bare client id:
|
|
64
|
+
// it is what the clone carries and what a sweep puts on-chain.
|
|
65
|
+
const boundClientId = encodeDepositApplicationData(clientId, depositTarget);
|
|
66
|
+
const initCode = sweeperCloneInitCode(implementationAddress, sweeperImmutableArgs(userAddress, boundClientId));
|
|
28
67
|
const preimage = concatBytes(Uint8Array.of(0xff), hexToBytes(factoryAddress), SALT, keccak_256(hexToBytes(initCode)));
|
|
29
68
|
return toChecksumAddress(`0x${bytesToHex(keccak_256(preimage).slice(12))}`);
|
|
30
69
|
}
|