@rabby-wallet/rabby-bridge 0.0.13 → 0.0.14-alpha.0
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/README.md +163 -1
- package/dist/calldata/abi.d.ts +29 -0
- package/dist/calldata/abi.js +160 -0
- package/dist/calldata/across/deposit.d.ts +2 -0
- package/dist/calldata/across/deposit.js +36 -0
- package/dist/calldata/across/depositNative.d.ts +2 -0
- package/dist/calldata/across/depositNative.js +45 -0
- package/dist/calldata/across/depositNow.d.ts +2 -0
- package/dist/calldata/across/depositNow.js +35 -0
- package/dist/calldata/across/depositV3.d.ts +2 -0
- package/dist/calldata/across/depositV3.js +35 -0
- package/dist/calldata/across/depositV3Now.d.ts +2 -0
- package/dist/calldata/across/depositV3Now.js +34 -0
- package/dist/calldata/across/index.d.ts +4 -0
- package/dist/calldata/across/index.js +31 -0
- package/dist/calldata/across/swapAndBridge.d.ts +2 -0
- package/dist/calldata/across/swapAndBridge.js +70 -0
- package/dist/calldata/across/validate.d.ts +3 -0
- package/dist/calldata/across/validate.js +34 -0
- package/dist/calldata/chains.d.ts +2 -0
- package/dist/calldata/chains.js +36 -0
- package/dist/calldata/destination.d.ts +6 -0
- package/dist/calldata/destination.js +227 -0
- package/dist/calldata/destinationSwap.d.ts +14 -0
- package/dist/calldata/destinationSwap.js +83 -0
- package/dist/calldata/destinationUniswap.d.ts +7 -0
- package/dist/calldata/destinationUniswap.js +57 -0
- package/dist/calldata/diagnostics.d.ts +4 -0
- package/dist/calldata/diagnostics.js +18 -0
- package/dist/calldata/expect.d.ts +29 -0
- package/dist/calldata/expect.js +157 -0
- package/dist/calldata/hex.d.ts +6 -0
- package/dist/calldata/hex.js +46 -0
- package/dist/calldata/index.d.ts +20 -0
- package/dist/calldata/index.js +88 -0
- package/dist/calldata/lifi/across/acrossV4Erc20Min.d.ts +2 -0
- package/dist/calldata/lifi/across/acrossV4Erc20Min.js +27 -0
- package/dist/calldata/lifi/across/acrossV4NativeMin.d.ts +2 -0
- package/dist/calldata/lifi/across/acrossV4NativeMin.js +23 -0
- package/dist/calldata/lifi/across/index.d.ts +6 -0
- package/dist/calldata/lifi/across/index.js +19 -0
- package/dist/calldata/lifi/allbridge/index.d.ts +3 -0
- package/dist/calldata/lifi/allbridge/index.js +26 -0
- package/dist/calldata/lifi/celer/index.d.ts +4 -0
- package/dist/calldata/lifi/celer/index.js +10 -0
- package/dist/calldata/lifi/centrifuge/index.d.ts +3 -0
- package/dist/calldata/lifi/centrifuge/index.js +22 -0
- package/dist/calldata/lifi/destination.d.ts +5 -0
- package/dist/calldata/lifi/destination.js +40 -0
- package/dist/calldata/lifi/frax/index.d.ts +4 -0
- package/dist/calldata/lifi/frax/index.js +29 -0
- package/dist/calldata/lifi/garden/index.d.ts +3 -0
- package/dist/calldata/lifi/garden/index.js +22 -0
- package/dist/calldata/lifi/gaszip/index.d.ts +6 -0
- package/dist/calldata/lifi/gaszip/index.js +15 -0
- package/dist/calldata/lifi/index.d.ts +4 -0
- package/dist/calldata/lifi/index.js +62 -0
- package/dist/calldata/lifi/intents/index.d.ts +4 -0
- package/dist/calldata/lifi/intents/index.js +10 -0
- package/dist/calldata/lifi/layerswap/index.d.ts +4 -0
- package/dist/calldata/lifi/layerswap/index.js +10 -0
- package/dist/calldata/lifi/m0/index.d.ts +3 -0
- package/dist/calldata/lifi/m0/index.js +33 -0
- package/dist/calldata/lifi/mayan/index.d.ts +4 -0
- package/dist/calldata/lifi/mayan/index.js +10 -0
- package/dist/calldata/lifi/method.d.ts +6 -0
- package/dist/calldata/lifi/method.js +16 -0
- package/dist/calldata/lifi/native/index.d.ts +4 -0
- package/dist/calldata/lifi/native/index.js +80 -0
- package/dist/calldata/lifi/params.d.ts +28 -0
- package/dist/calldata/lifi/params.js +349 -0
- package/dist/calldata/lifi/paxos/index.d.ts +4 -0
- package/dist/calldata/lifi/paxos/index.js +10 -0
- package/dist/calldata/lifi/polymer/index.d.ts +4 -0
- package/dist/calldata/lifi/polymer/index.js +10 -0
- package/dist/calldata/lifi/relay/index.d.ts +6 -0
- package/dist/calldata/lifi/relay/index.js +15 -0
- package/dist/calldata/lifi/shape.d.ts +4 -0
- package/dist/calldata/lifi/shape.js +31 -0
- package/dist/calldata/lifi/squid/index.d.ts +6 -0
- package/dist/calldata/lifi/squid/index.js +15 -0
- package/dist/calldata/lifi/stargate/index.d.ts +5 -0
- package/dist/calldata/lifi/stargate/index.js +15 -0
- package/dist/calldata/lifi/swap/index.d.ts +5 -0
- package/dist/calldata/lifi/swap/index.js +18 -0
- package/dist/calldata/lifi/swap/swapMethod.d.ts +2 -0
- package/dist/calldata/lifi/swap/swapMethod.js +40 -0
- package/dist/calldata/lifi/swapData.d.ts +5 -0
- package/dist/calldata/lifi/swapData.js +33 -0
- package/dist/calldata/match.d.ts +3 -0
- package/dist/calldata/match.js +21 -0
- package/dist/calldata/mayan/destination.d.ts +2 -0
- package/dist/calldata/mayan/destination.js +13 -0
- package/dist/calldata/mayan/fastMctpBridge.d.ts +3 -0
- package/dist/calldata/mayan/fastMctpBridge.js +48 -0
- package/dist/calldata/mayan/fastMctpCreateOrder.d.ts +3 -0
- package/dist/calldata/mayan/fastMctpCreateOrder.js +39 -0
- package/dist/calldata/mayan/forward.d.ts +8 -0
- package/dist/calldata/mayan/forward.js +35 -0
- package/dist/calldata/mayan/forwardERC20.d.ts +2 -0
- package/dist/calldata/mayan/forwardERC20.js +19 -0
- package/dist/calldata/mayan/forwardEth.d.ts +2 -0
- package/dist/calldata/mayan/forwardEth.js +16 -0
- package/dist/calldata/mayan/index.d.ts +4 -0
- package/dist/calldata/mayan/index.js +21 -0
- package/dist/calldata/mayan/mctp.d.ts +5 -0
- package/dist/calldata/mayan/mctp.js +41 -0
- package/dist/calldata/mayan/readProtocol.d.ts +2 -0
- package/dist/calldata/mayan/readProtocol.js +29 -0
- package/dist/calldata/mayan/swapAndForwardERC20.d.ts +2 -0
- package/dist/calldata/mayan/swapAndForwardERC20.js +24 -0
- package/dist/calldata/mayan/swapAndForwardEth.d.ts +2 -0
- package/dist/calldata/mayan/swapAndForwardEth.js +23 -0
- package/dist/calldata/mayan/swiftCreateOrder.d.ts +3 -0
- package/dist/calldata/mayan/swiftCreateOrder.js +49 -0
- package/dist/calldata/mayan/validate.d.ts +3 -0
- package/dist/calldata/mayan/validate.js +20 -0
- package/dist/calldata/protocols.d.ts +9 -0
- package/dist/calldata/protocols.js +58 -0
- package/dist/calldata/relay/calls.d.ts +13 -0
- package/dist/calldata/relay/calls.js +58 -0
- package/dist/calldata/relay/depositErc20.d.ts +2 -0
- package/dist/calldata/relay/depositErc20.js +22 -0
- package/dist/calldata/relay/depositErc20Allowance.d.ts +2 -0
- package/dist/calldata/relay/depositErc20Allowance.js +20 -0
- package/dist/calldata/relay/depositNative.d.ts +2 -0
- package/dist/calldata/relay/depositNative.js +20 -0
- package/dist/calldata/relay/index.d.ts +4 -0
- package/dist/calldata/relay/index.js +45 -0
- package/dist/calldata/relay/multicall.d.ts +2 -0
- package/dist/calldata/relay/multicall.js +15 -0
- package/dist/calldata/relay/nestedDeposit.d.ts +8 -0
- package/dist/calldata/relay/nestedDeposit.js +107 -0
- package/dist/calldata/relay/permit2TransferAndMulticall.d.ts +2 -0
- package/dist/calldata/relay/permit2TransferAndMulticall.js +42 -0
- package/dist/calldata/relay/permit3009TransferAndMulticall.d.ts +2 -0
- package/dist/calldata/relay/permit3009TransferAndMulticall.js +41 -0
- package/dist/calldata/relay/permit3009TransferAndMulticallSigned.d.ts +2 -0
- package/dist/calldata/relay/permit3009TransferAndMulticallSigned.js +40 -0
- package/dist/calldata/relay/permitTransferAndMulticall.d.ts +2 -0
- package/dist/calldata/relay/permitTransferAndMulticall.js +34 -0
- package/dist/calldata/relay/permitTransferAndMulticallLegacy.d.ts +2 -0
- package/dist/calldata/relay/permitTransferAndMulticallLegacy.js +35 -0
- package/dist/calldata/relay/transferAndMulticall.d.ts +2 -0
- package/dist/calldata/relay/transferAndMulticall.js +26 -0
- package/dist/calldata/relay/validate.d.ts +3 -0
- package/dist/calldata/relay/validate.js +18 -0
- package/dist/calldata/resolve.d.ts +2 -0
- package/dist/calldata/resolve.js +28 -0
- package/dist/calldata/socket/addresses.d.ts +9 -0
- package/dist/calldata/socket/addresses.js +9 -0
- package/dist/calldata/socket/bridge.d.ts +2 -0
- package/dist/calldata/socket/bridge.js +28 -0
- package/dist/calldata/socket/exec.d.ts +2 -0
- package/dist/calldata/socket/exec.js +71 -0
- package/dist/calldata/socket/index.d.ts +4 -0
- package/dist/calldata/socket/index.js +13 -0
- package/dist/calldata/socket/params.d.ts +5 -0
- package/dist/calldata/socket/params.js +14 -0
- package/dist/calldata/socket/protocols/ccip.d.ts +2 -0
- package/dist/calldata/socket/protocols/ccip.js +32 -0
- package/dist/calldata/socket/protocols/cctp.d.ts +2 -0
- package/dist/calldata/socket/protocols/cctp.js +25 -0
- package/dist/calldata/socket/protocols/eco.d.ts +2 -0
- package/dist/calldata/socket/protocols/eco.js +49 -0
- package/dist/calldata/socket/protocols/index.d.ts +3 -0
- package/dist/calldata/socket/protocols/index.js +87 -0
- package/dist/calldata/socket/protocols/native.d.ts +2 -0
- package/dist/calldata/socket/protocols/native.js +71 -0
- package/dist/calldata/socket/protocols/oft.d.ts +2 -0
- package/dist/calldata/socket/protocols/oft.js +33 -0
- package/dist/calldata/socket/protocols/swapsXYZ.d.ts +2 -0
- package/dist/calldata/socket/protocols/swapsXYZ.js +62 -0
- package/dist/calldata/socket/swapAndBridge.d.ts +2 -0
- package/dist/calldata/socket/swapAndBridge.js +41 -0
- package/dist/calldata/socket/validate.d.ts +3 -0
- package/dist/calldata/socket/validate.js +24 -0
- package/dist/calldata/types.d.ts +86 -0
- package/dist/calldata/types.js +20 -0
- package/dist/errors/constants.d.ts +906 -0
- package/dist/errors/constants.js +913 -0
- package/dist/errors/index.d.ts +65 -0
- package/dist/errors/index.js +53 -0
- package/dist/errors/sanitize.d.ts +3 -0
- package/dist/errors/sanitize.js +74 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3 -0
- package/dist/providers/data.d.ts +23 -0
- package/dist/providers/data.js +116 -0
- package/dist/providers/errors.d.ts +7 -0
- package/dist/providers/errors.js +10 -0
- package/dist/providers/layerswap.d.ts +9 -0
- package/dist/providers/layerswap.js +95 -0
- package/dist/providers/relay.d.ts +62 -0
- package/dist/providers/relay.js +237 -0
- package/dist/providers/socket.d.ts +5 -0
- package/dist/providers/socket.js +58 -0
- package/dist/quote.d.ts +30 -3
- package/dist/quote.js +236 -66
- package/package.json +13 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { asBigint, asString, decodeCall } from '../abi.js';
|
|
2
|
+
import { finishForward } from './forward.js';
|
|
3
|
+
export const swapAndForwardEth = {
|
|
4
|
+
name: 'swapAndForwardEth',
|
|
5
|
+
selector: '0xfa74fd43',
|
|
6
|
+
decode(data, value) {
|
|
7
|
+
const args = decodeCall([
|
|
8
|
+
{ name: 'amountIn', kind: 'uint' },
|
|
9
|
+
{ name: 'swapProtocol', kind: 'address' },
|
|
10
|
+
{ name: 'swapData', kind: 'bytes' },
|
|
11
|
+
{ name: 'middleToken', kind: 'address' },
|
|
12
|
+
{ name: 'minMiddleAmount', kind: 'uint' },
|
|
13
|
+
{ name: 'mayanProtocol', kind: 'address' },
|
|
14
|
+
{ name: 'mayanData', kind: 'bytes' },
|
|
15
|
+
], data);
|
|
16
|
+
const amount = asBigint(args.amountIn);
|
|
17
|
+
return finishForward('swapAndForwardEth', asString(args.mayanProtocol), asString(args.mayanData), {
|
|
18
|
+
token: '0x0000000000000000000000000000000000000000',
|
|
19
|
+
amount: amount > 0n ? amount : value,
|
|
20
|
+
protocolAmount: asBigint(args.minMiddleAmount),
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { asBigint, asRecord, asString, decodeCall } from '../abi.js';
|
|
2
|
+
import { accountFromBytes32 } from '../hex.js';
|
|
3
|
+
import { mayanDestination } from './destination.js';
|
|
4
|
+
const params = {
|
|
5
|
+
name: 'params',
|
|
6
|
+
kind: 'tuple',
|
|
7
|
+
components: [
|
|
8
|
+
{ name: 'payloadType', kind: 'uint' },
|
|
9
|
+
{ name: 'trader', kind: 'bytes', size: 32 },
|
|
10
|
+
{ name: 'destAddr', kind: 'bytes', size: 32 },
|
|
11
|
+
{ name: 'destChainId', kind: 'uint' },
|
|
12
|
+
{ name: 'referrerAddr', kind: 'bytes', size: 32 },
|
|
13
|
+
{ name: 'tokenOut', kind: 'bytes', size: 32 },
|
|
14
|
+
{ name: 'minAmountOut', kind: 'uint' },
|
|
15
|
+
{ name: 'gasDrop', kind: 'uint' },
|
|
16
|
+
{ name: 'cancelFee', kind: 'uint' },
|
|
17
|
+
{ name: 'refundFee', kind: 'uint' },
|
|
18
|
+
{ name: 'deadline', kind: 'uint' },
|
|
19
|
+
{ name: 'referrerBps', kind: 'uint' },
|
|
20
|
+
{ name: 'auctionMode', kind: 'uint' },
|
|
21
|
+
{ name: 'random', kind: 'bytes', size: 32 },
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
export const SWIFT_CREATE_ORDER = '0xa3a30834';
|
|
25
|
+
export const decodeSwiftCreateOrder = (data) => {
|
|
26
|
+
const args = decodeCall([
|
|
27
|
+
{ name: 'tokenIn', kind: 'address' },
|
|
28
|
+
{ name: 'amountIn', kind: 'uint' },
|
|
29
|
+
params,
|
|
30
|
+
{ name: 'customPayload', kind: 'bytes' },
|
|
31
|
+
], data);
|
|
32
|
+
const order = asRecord(args.params);
|
|
33
|
+
const customPayload = asString(args.customPayload);
|
|
34
|
+
const destination = mayanDestination('wormhole', asBigint(order.destChainId), accountFromBytes32(asString(order.tokenOut)), asBigint(order.minAmountOut));
|
|
35
|
+
if (customPayload !== '0x') {
|
|
36
|
+
delete destination.outputToken;
|
|
37
|
+
delete destination.outputAmountReference;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
protocolMethod: 'createOrderWithToken',
|
|
41
|
+
sourceToken: asString(args.tokenIn),
|
|
42
|
+
sourceAmount: asBigint(args.amountIn),
|
|
43
|
+
...destination,
|
|
44
|
+
bridgeReceiver: accountFromBytes32(asString(order.destAddr)),
|
|
45
|
+
receiver: customPayload === '0x' ? accountFromBytes32(asString(order.destAddr)) : undefined,
|
|
46
|
+
destinationCallData: customPayload === '0x' ? undefined : customPayload,
|
|
47
|
+
referrer: accountFromBytes32(asString(order.referrerAddr)),
|
|
48
|
+
};
|
|
49
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BRIDGE_ERRORS } from '../../errors/index.js';
|
|
2
|
+
import { isZeroWord } from '../hex.js';
|
|
3
|
+
export const mayanFailure = (parsed) => {
|
|
4
|
+
if (!parsed.protocolMethod) {
|
|
5
|
+
return BRIDGE_ERRORS.UNRECOGNIZED_MAYAN_PROTOCOL_CALLDATA;
|
|
6
|
+
}
|
|
7
|
+
if (parsed.destinationChainId === undefined && !parsed.destinationChainRef) {
|
|
8
|
+
return BRIDGE_ERRORS.MISSING_DESTINATION;
|
|
9
|
+
}
|
|
10
|
+
if (isZeroWord(parsed.receiver ?? parsed.bridgeReceiver)) {
|
|
11
|
+
return BRIDGE_ERRORS.MISSING_RECEIVER;
|
|
12
|
+
}
|
|
13
|
+
if ((parsed.sourceAmount ?? 0n) <= 0n) {
|
|
14
|
+
return BRIDGE_ERRORS.MISSING_SOURCE_AMOUNT;
|
|
15
|
+
}
|
|
16
|
+
if (parsed.protocolMethod !== 'bridge' && parsed.outputToken === undefined && !parsed.outputTokenReference && !parsed.destinationCallData) {
|
|
17
|
+
return BRIDGE_ERRORS.MISSING_OUTPUT_TOKEN;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const NATIVE_TOKEN = "0x0000000000000000000000000000000000000000";
|
|
2
|
+
export declare const WRAPPED_NATIVE_TOKENS: Record<string, string>;
|
|
3
|
+
export declare const isNative: (token: string) => boolean;
|
|
4
|
+
export declare const CCTP_CHAINS: Record<string, bigint>;
|
|
5
|
+
export declare const WORMHOLE_CHAINS: Record<string, bigint>;
|
|
6
|
+
export declare const LAYERZERO_CHAINS: Record<string, bigint>;
|
|
7
|
+
export declare const CCIP_CHAINS: Record<string, bigint>;
|
|
8
|
+
export declare const CCTP_USDC: Record<string, string>;
|
|
9
|
+
export declare const subtractFees: (amount: bigint, ...fees: bigint[]) => bigint;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BRIDGE_ERRORS, BridgeError } from '../errors/index.js';
|
|
2
|
+
export const NATIVE_TOKEN = '0x0000000000000000000000000000000000000000';
|
|
3
|
+
export const WRAPPED_NATIVE_TOKENS = {
|
|
4
|
+
1: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
|
5
|
+
10: '0x4200000000000000000000000000000000000006',
|
|
6
|
+
56: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c',
|
|
7
|
+
130: '0x4200000000000000000000000000000000000006',
|
|
8
|
+
137: '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270',
|
|
9
|
+
4663: '0x0bd7d308f8e1639fab988df18a8011f41eacad73',
|
|
10
|
+
8453: '0x4200000000000000000000000000000000000006',
|
|
11
|
+
42161: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1',
|
|
12
|
+
43114: '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7',
|
|
13
|
+
57073: '0x4200000000000000000000000000000000000006',
|
|
14
|
+
};
|
|
15
|
+
export const isNative = (token) => token === NATIVE_TOKEN || token.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
|
|
16
|
+
// Circle CCTP domains and Wormhole IDs are different namespaces from EVM chain IDs.
|
|
17
|
+
export const CCTP_CHAINS = {
|
|
18
|
+
0: 1n, 1: 43114n, 2: 10n, 3: 42161n, 6: 8453n, 7: 137n,
|
|
19
|
+
10: 130n, 11: 59144n, 13: 146n, 15: 143n, 19: 999n, 21: 57073n,
|
|
20
|
+
};
|
|
21
|
+
export const WORMHOLE_CHAINS = {
|
|
22
|
+
2: 1n, 4: 56n, 5: 137n, 6: 43114n, 23: 42161n, 24: 10n,
|
|
23
|
+
30: 8453n, 38: 59144n, 44: 130n, 47: 999n, 48: 143n, 52: 146n,
|
|
24
|
+
};
|
|
25
|
+
// Mainnet endpoint IDs from LayerZero's network metadata; v1 and v2 IDs coexist.
|
|
26
|
+
export const LAYERZERO_CHAINS = {
|
|
27
|
+
101: 1n, 30101: 1n, 102: 56n, 30102: 56n, 106: 43114n, 30106: 43114n,
|
|
28
|
+
109: 137n, 30109: 137n, 110: 42161n, 30110: 42161n, 111: 10n, 30111: 10n,
|
|
29
|
+
184: 8453n, 30184: 8453n, 183: 59144n, 30183: 59144n, 181: 5000n, 30181: 5000n,
|
|
30
|
+
320: 130n, 30320: 130n, 332: 146n, 30332: 146n, 340: 1868n, 30340: 1868n,
|
|
31
|
+
367: 999n, 30367: 999n, 370: 98866n, 30370: 98866n, 383: 9745n, 30383: 9745n,
|
|
32
|
+
390: 143n, 30390: 143n, 416: 4663n, 30416: 4663n,
|
|
33
|
+
255: 252n, 30255: 252n, 280: 1329n, 30280: 1329n,
|
|
34
|
+
};
|
|
35
|
+
export const CCIP_CHAINS = {
|
|
36
|
+
'5009297550715157269': 1n, '15971525489660198786': 8453n, '11344663589394136015': 56n,
|
|
37
|
+
};
|
|
38
|
+
// Canonical Circle USDC, not a symbol-based or quote-provided token mapping.
|
|
39
|
+
export const CCTP_USDC = {
|
|
40
|
+
1: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
41
|
+
10: '0x0b2c639c533813f4aa9d7837caf62653d097ff85',
|
|
42
|
+
137: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
|
|
43
|
+
8453: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
|
|
44
|
+
42161: '0xaf88d065e77c8cc2239327c5edb3a432268e5831',
|
|
45
|
+
43114: '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
46
|
+
130: '0x078d782b760474a361dda0af3839290b0ef57ad6',
|
|
47
|
+
143: '0x754704bc059f8c67012fed69bc8a327a5aafb603',
|
|
48
|
+
146: '0x29219dd400f2bf60e5a23d13be72b486d4038894',
|
|
49
|
+
999: '0xb88339cb7199b77e23db6e890353e22632ba630f',
|
|
50
|
+
59144: '0x176211869ca2b568f2a7d4ee941e073a821ee1ff',
|
|
51
|
+
57073: '0x2d270e6886d130d724215a266106e6832161eaed',
|
|
52
|
+
};
|
|
53
|
+
export const subtractFees = (amount, ...fees) => {
|
|
54
|
+
const total = fees.reduce((sum, fee) => sum + fee, 0n);
|
|
55
|
+
if (total > amount)
|
|
56
|
+
throw new BridgeError(BRIDGE_ERRORS.BRIDGE_FEES_EXCEED_THE_INPUT_AMOUNT);
|
|
57
|
+
return amount - total;
|
|
58
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type AbiParam, type AbiValue } from '../abi.js';
|
|
2
|
+
import type { ParsedBridgeCall } from '../types.js';
|
|
3
|
+
export declare const callTuple: AbiParam;
|
|
4
|
+
export declare const callsParam: AbiParam;
|
|
5
|
+
export declare const requestIdFromMetadata: (metadata: string) => string | undefined;
|
|
6
|
+
export declare const relayCall: (method: string, metadata: string, value: bigint, calls: AbiValue, source?: {
|
|
7
|
+
token?: string;
|
|
8
|
+
amount?: bigint;
|
|
9
|
+
}) => ParsedBridgeCall;
|
|
10
|
+
export declare const firstPositive: (values: AbiValue[]) => {
|
|
11
|
+
token?: string;
|
|
12
|
+
amount: bigint;
|
|
13
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BRIDGE_ERRORS, BridgeError } from '../../errors/index.js';
|
|
2
|
+
import { asBigint, asRecord, asString } from '../abi.js';
|
|
3
|
+
import { isZeroWord } from '../hex.js';
|
|
4
|
+
import { NATIVE_TOKEN } from '../protocols.js';
|
|
5
|
+
import { nestedRelayOrder } from './nestedDeposit.js';
|
|
6
|
+
export const callTuple = {
|
|
7
|
+
name: 'call',
|
|
8
|
+
kind: 'tuple',
|
|
9
|
+
components: [
|
|
10
|
+
{ name: 'target', kind: 'address' },
|
|
11
|
+
{ name: 'allowFailure', kind: 'bool' },
|
|
12
|
+
{ name: 'value', kind: 'uint' },
|
|
13
|
+
{ name: 'callData', kind: 'bytes' },
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
export const callsParam = {
|
|
17
|
+
name: 'calls',
|
|
18
|
+
kind: 'array',
|
|
19
|
+
item: callTuple,
|
|
20
|
+
};
|
|
21
|
+
export const requestIdFromMetadata = (metadata) => {
|
|
22
|
+
const body = metadata.toLowerCase().replace(/^0x/, '');
|
|
23
|
+
if (body.length < 64) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const requestId = `0x${body.slice(0, 64)}`;
|
|
27
|
+
return isZeroWord(requestId) ? undefined : requestId;
|
|
28
|
+
};
|
|
29
|
+
export const relayCall = (method, metadata, value, calls, source) => ({
|
|
30
|
+
aggregatorId: 'relay',
|
|
31
|
+
method,
|
|
32
|
+
kind: 'deposit',
|
|
33
|
+
requestId: requestIdFromMetadata(metadata),
|
|
34
|
+
sourceToken: source?.token ?? (value > 0n ? NATIVE_TOKEN : undefined),
|
|
35
|
+
sourceAmount: source?.amount && source.amount > 0n ? source.amount : value,
|
|
36
|
+
...nestedRelayOrder(calls, method === 'transferAndMulticall' && value === 0n && source?.token && source.amount !== undefined
|
|
37
|
+
? { token: source.token, amount: source.amount }
|
|
38
|
+
: method === 'multicall' && value > 0n ? { token: NATIVE_TOKEN, amount: value } : undefined),
|
|
39
|
+
});
|
|
40
|
+
const amountOf = (record) => {
|
|
41
|
+
const amount = record.amount ?? record.value;
|
|
42
|
+
return asBigint(amount);
|
|
43
|
+
};
|
|
44
|
+
export const firstPositive = (values) => {
|
|
45
|
+
let amount = 0n;
|
|
46
|
+
let token;
|
|
47
|
+
for (const value of values) {
|
|
48
|
+
const record = asRecord(value);
|
|
49
|
+
amount += amountOf(record);
|
|
50
|
+
if (record.token) {
|
|
51
|
+
const current = asString(record.token);
|
|
52
|
+
if (token && token !== current)
|
|
53
|
+
throw new BridgeError(BRIDGE_ERRORS.MULTIPLE_SOURCE_ASSETS_ARE_NOT_SUPPORTED);
|
|
54
|
+
token = current;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return { token, amount };
|
|
58
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { asBigint, asString, decodeCall } from '../abi.js';
|
|
2
|
+
export const depositErc20 = {
|
|
3
|
+
name: 'depositErc20',
|
|
4
|
+
selector: '0xe8017952',
|
|
5
|
+
decode(data) {
|
|
6
|
+
const args = decodeCall([
|
|
7
|
+
{ name: 'depositor', kind: 'address' },
|
|
8
|
+
{ name: 'token', kind: 'address' },
|
|
9
|
+
{ name: 'amount', kind: 'uint' },
|
|
10
|
+
{ name: 'id', kind: 'bytes', size: 32 },
|
|
11
|
+
], data);
|
|
12
|
+
return {
|
|
13
|
+
aggregatorId: 'relay',
|
|
14
|
+
method: 'depositErc20',
|
|
15
|
+
kind: 'deposit',
|
|
16
|
+
sourceToken: asString(args.token),
|
|
17
|
+
sourceAmount: asBigint(args.amount),
|
|
18
|
+
orderId: asString(args.id),
|
|
19
|
+
depositor: asString(args.depositor),
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { asString, decodeCall } from '../abi.js';
|
|
2
|
+
export const depositErc20Allowance = {
|
|
3
|
+
name: 'depositErc20Allowance',
|
|
4
|
+
selector: '0x5a1ee3ac',
|
|
5
|
+
decode(data) {
|
|
6
|
+
const args = decodeCall([
|
|
7
|
+
{ name: 'depositor', kind: 'address' },
|
|
8
|
+
{ name: 'token', kind: 'address' },
|
|
9
|
+
{ name: 'id', kind: 'bytes', size: 32 },
|
|
10
|
+
], data);
|
|
11
|
+
return {
|
|
12
|
+
aggregatorId: 'relay',
|
|
13
|
+
method: 'depositErc20Allowance',
|
|
14
|
+
kind: 'deposit',
|
|
15
|
+
sourceToken: asString(args.token),
|
|
16
|
+
orderId: asString(args.id),
|
|
17
|
+
depositor: asString(args.depositor),
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { asString, decodeCall } from '../abi.js';
|
|
2
|
+
export const depositNative = {
|
|
3
|
+
name: 'depositNative',
|
|
4
|
+
selector: '0x49290c1c',
|
|
5
|
+
decode(data, value) {
|
|
6
|
+
const args = decodeCall([
|
|
7
|
+
{ name: 'depositor', kind: 'address' },
|
|
8
|
+
{ name: 'id', kind: 'bytes', size: 32 },
|
|
9
|
+
], data);
|
|
10
|
+
return {
|
|
11
|
+
aggregatorId: 'relay',
|
|
12
|
+
method: 'depositNative',
|
|
13
|
+
kind: 'deposit',
|
|
14
|
+
sourceToken: '0x0000000000000000000000000000000000000000',
|
|
15
|
+
sourceAmount: value,
|
|
16
|
+
orderId: asString(args.id),
|
|
17
|
+
depositor: asString(args.depositor),
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BridgeCallExpectation } from '../expect.js';
|
|
2
|
+
import type { BridgeCheck, DecodeHit } from '../types.js';
|
|
3
|
+
export declare const decodeRelay: (data: string, value: bigint) => DecodeHit;
|
|
4
|
+
export declare const validateRelay: (data: string, value: bigint, expectation?: BridgeCallExpectation, chainId?: string) => BridgeCheck;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { matchMethod } from '../match.js';
|
|
2
|
+
import { finishCheck } from '../expect.js';
|
|
3
|
+
import { depositErc20 } from './depositErc20.js';
|
|
4
|
+
import { depositErc20Allowance } from './depositErc20Allowance.js';
|
|
5
|
+
import { depositNative } from './depositNative.js';
|
|
6
|
+
import { multicall } from './multicall.js';
|
|
7
|
+
import { permit2TransferAndMulticall } from './permit2TransferAndMulticall.js';
|
|
8
|
+
import { permit3009TransferAndMulticall } from './permit3009TransferAndMulticall.js';
|
|
9
|
+
import { permit3009TransferAndMulticallSigned } from './permit3009TransferAndMulticallSigned.js';
|
|
10
|
+
import { permitTransferAndMulticall } from './permitTransferAndMulticall.js';
|
|
11
|
+
import { permitTransferAndMulticallLegacy } from './permitTransferAndMulticallLegacy.js';
|
|
12
|
+
import { transferAndMulticall } from './transferAndMulticall.js';
|
|
13
|
+
import { getBridgeRouter } from '../../list.js';
|
|
14
|
+
import { relayFailure } from './validate.js';
|
|
15
|
+
import { BRIDGE_ERRORS } from '../../errors/index.js';
|
|
16
|
+
const METHODS = [
|
|
17
|
+
depositErc20,
|
|
18
|
+
depositErc20Allowance,
|
|
19
|
+
depositNative,
|
|
20
|
+
multicall,
|
|
21
|
+
transferAndMulticall,
|
|
22
|
+
permit2TransferAndMulticall,
|
|
23
|
+
permit3009TransferAndMulticall,
|
|
24
|
+
permit3009TransferAndMulticallSigned,
|
|
25
|
+
permitTransferAndMulticall,
|
|
26
|
+
permitTransferAndMulticallLegacy,
|
|
27
|
+
];
|
|
28
|
+
export const decodeRelay = (data, value) => matchMethod(METHODS, data, value);
|
|
29
|
+
const relayCompareMask = (parsed) => ({
|
|
30
|
+
fromToken: parsed.sourceToken !== undefined,
|
|
31
|
+
fromAmount: parsed.sourceAmount !== undefined && parsed.sourceToken !== undefined,
|
|
32
|
+
toToken: false,
|
|
33
|
+
toAmount: false,
|
|
34
|
+
receiver: false,
|
|
35
|
+
});
|
|
36
|
+
export const validateRelay = (data, value, expectation, chainId = '') => {
|
|
37
|
+
const hit = decodeRelay(data, value);
|
|
38
|
+
if (!hit.ok) {
|
|
39
|
+
return { ...hit, aggregatorId: 'relay' };
|
|
40
|
+
}
|
|
41
|
+
return finishCheck('relay', hit.parsed, hit.parsed.innerTarget && chainId && hit.parsed.innerTarget !== getBridgeRouter('relay', chainId)
|
|
42
|
+
? BRIDGE_ERRORS.RELAY_CANONICAL_DEPOSITORY_MISMATCH
|
|
43
|
+
: expectation && hit.parsed.depositor !== undefined && hit.parsed.depositor !== expectation.userAddress.toLowerCase()
|
|
44
|
+
? BRIDGE_ERRORS.DEPOSITOR_MISMATCH : relayFailure(hit.parsed), expectation, chainId, relayCompareMask(hit.parsed));
|
|
45
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { asString, decodeCall } from '../abi.js';
|
|
2
|
+
import { callsParam, relayCall } from './calls.js';
|
|
3
|
+
export const multicall = {
|
|
4
|
+
name: 'multicall',
|
|
5
|
+
selector: '0xcd6e13f7',
|
|
6
|
+
decode(data, value) {
|
|
7
|
+
const args = decodeCall([
|
|
8
|
+
callsParam,
|
|
9
|
+
{ name: 'refundTo', kind: 'address' },
|
|
10
|
+
{ name: 'nftRecipient', kind: 'address' },
|
|
11
|
+
{ name: 'metadata', kind: 'bytes' },
|
|
12
|
+
], data);
|
|
13
|
+
return relayCall('multicall', asString(args.metadata), value, args.calls);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type AbiValue } from '../abi.js';
|
|
2
|
+
import type { ParsedBridgeCall } from '../types.js';
|
|
3
|
+
export declare const relayFundingRouter: (method: string, target: string) => string | undefined;
|
|
4
|
+
/** Read one final deposit from actual calls, never from metadata or signatures. */
|
|
5
|
+
export declare const nestedRelayOrder: (rawCalls: AbiValue, funding?: {
|
|
6
|
+
token: string;
|
|
7
|
+
amount: bigint;
|
|
8
|
+
}) => Pick<ParsedBridgeCall, "orderId" | "depositor" | "innerTarget" | "bridgeToken" | "bridgeAmount" | "bridgeReceiver"> | undefined;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { depositErc20 } from './depositErc20.js';
|
|
2
|
+
import { depositErc20Allowance } from './depositErc20Allowance.js';
|
|
3
|
+
import { depositNative } from './depositNative.js';
|
|
4
|
+
import { asArray, asBigint, asRecord, asString, decodeCall } from '../abi.js';
|
|
5
|
+
import { BRIDGE_ROUTER_WHITELIST } from '../../list.js';
|
|
6
|
+
import { isZeroWord, readSelector } from '../hex.js';
|
|
7
|
+
import { NATIVE_TOKEN } from '../protocols.js';
|
|
8
|
+
const DEPOSITORIES = new Set(Object.values(BRIDGE_ROUTER_WHITELIST.relay));
|
|
9
|
+
// shortcut: reviewed v3.2 cleanup wrappers only; review new deployments before adding them.
|
|
10
|
+
const PROXY_ROUTERS = {
|
|
11
|
+
'0x5567954cd026cebfe486062cb75848e0f1c12e58': '0x0729e2a4716d9f7dd17858d5d504426d228697f7',
|
|
12
|
+
'0xe4dfbd5e6784db1058124e2c87554c0591f0fb7b': '0x6328ea02d28131e58b28e55c6258258a30d90e05',
|
|
13
|
+
};
|
|
14
|
+
const ROUTERS = new Set(Object.values(PROXY_ROUTERS));
|
|
15
|
+
export const relayFundingRouter = (method, target) => method === 'transferAndMulticall' ? PROXY_ROUTERS[target]
|
|
16
|
+
: method === 'multicall' && ROUTERS.has(target) ? target : undefined;
|
|
17
|
+
const CLEANUP_NATIVE = '0x5d1fe6a2';
|
|
18
|
+
const CLEANUP_ERC20 = '0x73b7bb2f';
|
|
19
|
+
/** Read one final deposit from actual calls, never from metadata or signatures. */
|
|
20
|
+
export const nestedRelayOrder = (rawCalls, funding) => {
|
|
21
|
+
try {
|
|
22
|
+
const calls = asArray(rawCalls).map(asRecord);
|
|
23
|
+
if (!calls.length)
|
|
24
|
+
return undefined;
|
|
25
|
+
// Multiple deposit/cleanup calls cannot be bound to a single backend order.
|
|
26
|
+
if (calls.slice(0, -1).some((call) => DEPOSITORIES.has(asString(call.target)) ||
|
|
27
|
+
(ROUTERS.has(asString(call.target)) && [CLEANUP_NATIVE, CLEANUP_ERC20].includes(readSelector(asString(call.callData)) ?? ''))))
|
|
28
|
+
return undefined;
|
|
29
|
+
const last = calls[calls.length - 1];
|
|
30
|
+
if (last.allowFailure !== false)
|
|
31
|
+
return undefined;
|
|
32
|
+
let target = asString(last.target), data = asString(last.callData);
|
|
33
|
+
const wrapper = ROUTERS.has(target) ? target : undefined;
|
|
34
|
+
let value = asBigint(last.value);
|
|
35
|
+
let token;
|
|
36
|
+
let nativeCleanup = false;
|
|
37
|
+
let cleanupAmount;
|
|
38
|
+
if (ROUTERS.has(target)) {
|
|
39
|
+
if (value !== 0n)
|
|
40
|
+
return undefined;
|
|
41
|
+
if (readSelector(data) === CLEANUP_NATIVE) {
|
|
42
|
+
const args = decodeCall([{ name: 'amount', kind: 'uint' }, { name: 'to', kind: 'address' }, { name: 'data', kind: 'bytes' }], data);
|
|
43
|
+
target = asString(args.to);
|
|
44
|
+
data = asString(args.data);
|
|
45
|
+
value = asBigint(args.amount);
|
|
46
|
+
cleanupAmount = value;
|
|
47
|
+
nativeCleanup = true;
|
|
48
|
+
}
|
|
49
|
+
else if (readSelector(data) === CLEANUP_ERC20) {
|
|
50
|
+
const args = decodeCall([
|
|
51
|
+
{ name: 'tokens', kind: 'array', item: { name: 'token', kind: 'address' } },
|
|
52
|
+
{ name: 'tos', kind: 'array', item: { name: 'to', kind: 'address' } },
|
|
53
|
+
{ name: 'datas', kind: 'array', item: { name: 'data', kind: 'bytes' } },
|
|
54
|
+
{ name: 'amounts', kind: 'array', item: { name: 'amount', kind: 'uint' } },
|
|
55
|
+
], data);
|
|
56
|
+
if (Object.values(args).some((items) => asArray(items).length !== 1))
|
|
57
|
+
return undefined;
|
|
58
|
+
target = asString(asArray(args.tos)[0]);
|
|
59
|
+
data = asString(asArray(args.datas)[0]);
|
|
60
|
+
token = asString(asArray(args.tokens)[0]);
|
|
61
|
+
cleanupAmount = asBigint(asArray(args.amounts)[0]);
|
|
62
|
+
}
|
|
63
|
+
else
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
if (!DEPOSITORIES.has(target))
|
|
67
|
+
return undefined;
|
|
68
|
+
const method = [depositNative, depositErc20, depositErc20Allowance].find((item) => item.selector === readSelector(data));
|
|
69
|
+
if (!method || (nativeCleanup && method !== depositNative) || (token && method === depositNative))
|
|
70
|
+
return undefined;
|
|
71
|
+
const parsed = method.decode(data, value);
|
|
72
|
+
if (isZeroWord(parsed.orderId) || (token && token !== parsed.sourceToken))
|
|
73
|
+
return undefined;
|
|
74
|
+
const result = { orderId: parsed.orderId, depositor: parsed.depositor, innerTarget: target };
|
|
75
|
+
if (!funding || funding.amount <= 0n || funding.token !== parsed.sourceToken)
|
|
76
|
+
return result;
|
|
77
|
+
// shortcut: only one approval before deposit; add funding analysis before supporting swaps/other calls.
|
|
78
|
+
const prefix = calls.slice(0, -1);
|
|
79
|
+
if (prefix.length > 1)
|
|
80
|
+
return result;
|
|
81
|
+
let approved;
|
|
82
|
+
if (prefix.length) {
|
|
83
|
+
const call = prefix[0];
|
|
84
|
+
if (funding.token === NATIVE_TOKEN || call.allowFailure !== false ||
|
|
85
|
+
asString(call.target) !== funding.token || asBigint(call.value) !== 0n ||
|
|
86
|
+
readSelector(asString(call.callData)) !== '0x095ea7b3')
|
|
87
|
+
return result;
|
|
88
|
+
const args = decodeCall([{ name: 'spender', kind: 'address' }, { name: 'amount', kind: 'uint' }], asString(call.callData));
|
|
89
|
+
if (asString(args.spender) !== target)
|
|
90
|
+
return result;
|
|
91
|
+
approved = asBigint(args.amount);
|
|
92
|
+
}
|
|
93
|
+
// Zero cleanup means all remaining balance; here the full input is still on Router.
|
|
94
|
+
const amount = cleanupAmount === 0n ? funding.amount : cleanupAmount;
|
|
95
|
+
const depositAmount = method === depositErc20Allowance ? amount ?? approved
|
|
96
|
+
: nativeCleanup ? amount : parsed.sourceAmount;
|
|
97
|
+
if (depositAmount !== funding.amount ||
|
|
98
|
+
(cleanupAmount !== undefined && amount !== funding.amount) ||
|
|
99
|
+
(method !== depositNative && value !== 0n))
|
|
100
|
+
return result;
|
|
101
|
+
return { ...result, bridgeToken: funding.token, bridgeAmount: funding.amount, bridgeReceiver: wrapper };
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Unknown or malformed calls leave the order unresolved for the signing check.
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { asArray, asRecord, asString, decodeCall } from '../abi.js';
|
|
2
|
+
import { callsParam, firstPositive, relayCall } from './calls.js';
|
|
3
|
+
const permit = {
|
|
4
|
+
name: 'permit',
|
|
5
|
+
kind: 'tuple',
|
|
6
|
+
components: [
|
|
7
|
+
{
|
|
8
|
+
name: 'permitted',
|
|
9
|
+
kind: 'array',
|
|
10
|
+
item: {
|
|
11
|
+
name: 'tokenPermissions',
|
|
12
|
+
kind: 'tuple',
|
|
13
|
+
components: [
|
|
14
|
+
{ name: 'token', kind: 'address' },
|
|
15
|
+
{ name: 'amount', kind: 'uint' },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{ name: 'nonce', kind: 'uint' },
|
|
20
|
+
{ name: 'deadline', kind: 'uint' },
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
export const permit2TransferAndMulticall = {
|
|
24
|
+
name: 'permit2TransferAndMulticall',
|
|
25
|
+
selector: '0x0a2b8f36',
|
|
26
|
+
decode(data, value) {
|
|
27
|
+
const args = decodeCall([
|
|
28
|
+
{ name: 'user', kind: 'address' },
|
|
29
|
+
permit,
|
|
30
|
+
callsParam,
|
|
31
|
+
{ name: 'refundTo', kind: 'address' },
|
|
32
|
+
{ name: 'nftRecipient', kind: 'address' },
|
|
33
|
+
{ name: 'metadata', kind: 'bytes' },
|
|
34
|
+
{ name: 'permitSignature', kind: 'bytes' },
|
|
35
|
+
], data);
|
|
36
|
+
const source = firstPositive(asArray(asRecord(args.permit).permitted));
|
|
37
|
+
return {
|
|
38
|
+
...relayCall('permit2TransferAndMulticall', asString(args.metadata), value, args.calls, source),
|
|
39
|
+
depositor: asString(args.user),
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { asArray, asString, decodeCall } from '../abi.js';
|
|
2
|
+
import { callsParam, firstPositive, relayCall } from './calls.js';
|
|
3
|
+
const permits = {
|
|
4
|
+
name: 'permits',
|
|
5
|
+
kind: 'array',
|
|
6
|
+
item: {
|
|
7
|
+
name: 'permit',
|
|
8
|
+
kind: 'tuple',
|
|
9
|
+
components: [
|
|
10
|
+
{ name: 'from', kind: 'address' },
|
|
11
|
+
{ name: 'value', kind: 'uint' },
|
|
12
|
+
{ name: 'validAfter', kind: 'uint' },
|
|
13
|
+
{ name: 'validBefore', kind: 'uint' },
|
|
14
|
+
{ name: 'v', kind: 'uint' },
|
|
15
|
+
{ name: 'r', kind: 'bytes', size: 32 },
|
|
16
|
+
{ name: 's', kind: 'bytes', size: 32 },
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const decodePermits = (name, selector, tail) => ({
|
|
21
|
+
name,
|
|
22
|
+
selector,
|
|
23
|
+
decode(data, value) {
|
|
24
|
+
const args = decodeCall([
|
|
25
|
+
permits,
|
|
26
|
+
{ name: 'tokens', kind: 'array', item: { name: 'token', kind: 'address' } },
|
|
27
|
+
callsParam,
|
|
28
|
+
{ name: 'refundTo', kind: 'address' },
|
|
29
|
+
{ name: 'nftRecipient', kind: 'address' },
|
|
30
|
+
{ name: 'metadata', kind: 'bytes' },
|
|
31
|
+
...tail,
|
|
32
|
+
], data);
|
|
33
|
+
const source = firstPositive(asArray(args.permits));
|
|
34
|
+
const tokens = asArray(args.tokens).map((token) => asString(token));
|
|
35
|
+
return relayCall(name, asString(args.metadata), value, args.calls, {
|
|
36
|
+
token: tokens[0] ?? source.token,
|
|
37
|
+
amount: source.amount,
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
export const permit3009TransferAndMulticall = decodePermits('permit3009TransferAndMulticall', '0xf80f00fb', []);
|