forked from midas-apps/contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlayerzero.ts
More file actions
304 lines (276 loc) · 7.97 KB
/
layerzero.ts
File metadata and controls
304 lines (276 loc) · 7.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
import { createSignAndSendFlow } from '@layerzerolabs/devtools';
import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat';
import {
DebugLogger,
KnownOutputs,
KnownWarnings,
} from '@layerzerolabs/io-devtools';
import {
endpointIdToChainType,
endpointIdToNetwork,
ChainType,
} from '@layerzerolabs/lz-definitions';
import { subtask, task, types } from 'hardhat/config';
import {
layerZeroEids,
MTokenName,
Network,
PaymentTokenName,
} from '../config';
import { getCurrentAddresses } from '../config/constants/addresses';
import { lzConfigsPerMToken } from '../config/misc';
import {
getBlockExplorerLink,
sendEvm,
EvmArgs,
SendResult,
SignAndSendTaskArgs,
createSigner,
sendOVaultComposer,
} from '../helpers/layerzero';
import { isMTokenName, isPaymentTokenName } from '../helpers/utils';
interface OVaultComposerArgs {
dstNetwork: Network; // the destination chain we're receiving asset or share on
amount: string; // amount to send
to: string; // receiver wallet address
tokenType: 'asset' | 'share'; // Whether we're sending asset or share
minAmount?: string;
lzReceiveGas?: number;
lzReceiveValue?: string;
lzComposeGas?: number;
lzComposeValue?: string;
mtoken: MTokenName;
ptoken: PaymentTokenName;
}
task('lz:oft:send:midas', 'Sends OFT tokens cross‐chain from EVM chains')
.addParam('mtoken', 'MToken')
.addParam('amount', 'Amount', undefined, types.string)
.addParam('receiverNetwork', 'Receiver Network')
.addOptionalParam('receiver', 'Receiver address')
.setAction(async (taskArgs, hre) => {
const { deployer } = await hre.getNamedAccounts();
const deployerSigner = await hre.ethers.getSigner(deployer);
const mtoken = taskArgs.mtoken;
const amount = taskArgs.amount;
const receiverNetwork = taskArgs.receiverNetwork;
const receiver = taskArgs.receiver ?? deployerSigner.address;
if (mtoken) {
if (!isMTokenName(mtoken)) {
throw new Error('Invalid mtoken parameter');
}
}
const srcEid = layerZeroEids[hre.network.name as Network];
const dstEid = layerZeroEids[receiverNetwork as Network];
if (!srcEid || !dstEid) {
throw new Error('EIDs not found for networks');
}
const addresses = getCurrentAddresses(hre);
const oftAdapter = addresses?.[mtoken as MTokenName]?.layerZero?.oft;
if (!oftAdapter) {
throw new Error('OFT adapter not found');
}
const chainType = endpointIdToChainType(srcEid);
let result: SendResult;
if (oftAdapter) {
DebugLogger.printWarning(
KnownWarnings.USING_OVERRIDE_OFT,
`For network: ${endpointIdToNetwork(srcEid)}, OFT: ${oftAdapter}`,
);
}
// Only support EVM chains in this example
if (chainType === ChainType.EVM) {
result = await sendEvm(
{
srcEid,
dstEid,
to: receiver,
amount,
oftAddress: oftAdapter,
} as EvmArgs,
hre,
);
} else {
throw new Error(
`The chain type ${chainType} is not supported in this OFT example. Only EVM chains are supported.`,
);
}
DebugLogger.printLayerZeroOutput(
KnownOutputs.SENT_VIA_OFT,
`Successfully sent ${amount} tokens from ${endpointIdToNetwork(
srcEid,
)} to ${endpointIdToNetwork(dstEid)}`,
);
// print the explorer link for the srcEid from metadata
const explorerLink = await getBlockExplorerLink(srcEid, result.txHash);
// if explorer link is available, print the tx hash link
if (explorerLink) {
DebugLogger.printLayerZeroOutput(
KnownOutputs.TX_HASH,
`Explorer link for source chain ${endpointIdToNetwork(
srcEid,
)}: ${explorerLink}`,
);
}
// print the LayerZero Scan link from metadata
DebugLogger.printLayerZeroOutput(
KnownOutputs.EXPLORER_LINK,
`LayerZero Scan link for tracking all cross-chain transaction details: ${result.scanLink}`,
);
});
task('lz:oapp:wire:midas', 'Runs a user-defined script')
.addOptionalParam(
'oappConfig',
'Path to your LayerZero OApp config',
undefined,
types.string,
)
.addOptionalParam('mtoken', 'MToken')
.addOptionalParam('ptoken', 'Payment Token')
.addOptionalParam('originalNetwork', 'Original Network')
.setAction(async (taskArgs, hre) => {
const mtoken = taskArgs.mtoken;
const ptoken = taskArgs.ptoken;
const originalNetwork = taskArgs.originalNetwork;
if (mtoken) {
if (!isMTokenName(mtoken)) {
throw new Error('Invalid mtoken parameter');
}
hre.mtoken = mtoken;
}
if (ptoken) {
if (!isPaymentTokenName(ptoken)) {
throw new Error('Invalid ptoken parameter');
}
hre.paymentToken = ptoken;
}
if (originalNetwork) {
hre.layerZero = {
originalNetwork,
};
}
await hre.run('lz:oapp:wire', {
oappConfig: './config/misc/layerzero.config.ts',
signAndSendSubtask: '::lz:sign-and-send:midas',
});
});
task(
'lz:ovault:send:midas',
'Sends assets or shares through OVaultComposer with automatic composeMsg creation',
)
.addOptionalParam('mtoken', 'MToken')
.addOptionalParam('ptoken', 'Payment Token')
.addOptionalParam('dstNetwork', 'Destination Network')
.addParam(
'amount',
'Amount to send (human readable units, e.g. "1.5")',
undefined,
types.string,
)
.addOptionalParam(
'to',
'Recipient address (20-byte hex for EVM)',
undefined,
types.string,
)
.addParam(
'tokenType',
'Token type to send: "asset" (to get shares) or "share" (to get assets)',
undefined,
types.string,
)
.addOptionalParam(
'minAmount',
'Minimum amount to receive in case of custom slippage or fees (human readable units, e.g. "1.5")',
undefined,
types.string,
)
.addOptionalParam(
'lzReceiveGas',
'Gas for lzReceive operation',
undefined,
types.int,
)
.addOptionalParam(
'lzReceiveValue',
'Value for lzReceive operation (in wei)',
undefined,
types.string,
)
.addOptionalParam(
'lzComposeGas',
'Gas for lzCompose operation (defaults: 175k for hub destination, 375k for cross-chain)',
undefined,
types.int,
)
.addOptionalParam(
'lzComposeValue',
'Value for lzCompose operation (in wei)',
undefined,
types.string,
)
.setAction(async (args: OVaultComposerArgs, hre) => {
const mToken = args.mtoken;
const pToken = args.ptoken;
const dstNetwork = args.dstNetwork;
const hubNetwork = Object.entries(lzConfigsPerMToken).find(
([, networkConfig]) => {
return !!networkConfig[mToken];
},
)?.[0] as Network | undefined;
if (!hubNetwork) {
throw new Error('Hub network not found');
}
console.log('hubNetwork', hubNetwork);
await sendOVaultComposer(
{
...args,
dstEid: layerZeroEids[dstNetwork]!,
srcEid: layerZeroEids[hre.network.name as Network]!,
hubEid: layerZeroEids[hubNetwork]!,
mToken,
pToken,
},
hre,
);
});
// overriding default sign to support custom signer
subtask(
'::lz:sign-and-send:midas',
'Sign and send a list of transactions using a local signer',
async ({ transactions, ...args }: SignAndSendTaskArgs) => {
const hre = await import('hardhat');
return createSignAndSendFlow({ ...args, createSigner: createSigner(hre) })({
transactions,
});
},
)
.addFlag(
'ci',
'Continuous integration (non-interactive) mode. Will not ask for any input from the user',
)
.addParam(
'transactions',
'List of OmniTransaction objects',
undefined,
devtoolsTypes.any,
)
.addParam(
'createSigner',
'Function that creates a signer for a particular network',
undefined,
devtoolsTypes.fn,
)
.addParam(
'logger',
'Logger object (see @layerzerolabs/io-devtools',
undefined,
types.any,
true,
)
.addParam(
'onFailure',
'Function that handles sign & send failures',
undefined,
devtoolsTypes.fn,
true,
);