@@ -14,6 +14,7 @@ import {
14
14
TokenAddress ,
15
15
TokenId ,
16
16
toNative ,
17
+ toUniversal ,
17
18
universalAddress ,
18
19
} from "@wormhole-foundation/sdk-definitions" ;
19
20
import type { EvmChains , EvmPlatformType } from "@wormhole-foundation/sdk-evm" ;
@@ -30,6 +31,7 @@ import {
30
31
MultiTokenNtt ,
31
32
Ntt ,
32
33
NttTransceiver ,
34
+ TrimmedAmount ,
33
35
} from "@wormhole-foundation/sdk-definitions-ntt" ;
34
36
import { ethers , type Provider } from "ethers" ;
35
37
import { EvmNttWormholeTranceiver } from "./ntt.js" ;
@@ -39,6 +41,11 @@ import {
39
41
loadAbiVersion ,
40
42
MultiTokenNttManagerBindings ,
41
43
} from "./multiTokenNttBindings.js" ;
44
+ import {
45
+ decodeTrimmedAmount ,
46
+ EncodedTrimmedAmount ,
47
+ untrim ,
48
+ } from "./trimmedAmount.js" ;
42
49
43
50
export class EvmMultiTokenNtt < N extends Network , C extends EvmChains >
44
51
implements MultiTokenNtt < N , C >
@@ -318,46 +325,68 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
318
325
) ;
319
326
}
320
327
321
- async getCurrentOutboundCapacity ( ) : Promise < bigint > {
322
- // return await this.manager.getCurrentOutboundCapacity();
323
- throw new Error ( "Not implemented" ) ;
328
+ async getCurrentOutboundCapacity ( localToken : TokenId ) : Promise < bigint > {
329
+ const { chain, address } = await this . getOriginalToken ( localToken ) ;
330
+
331
+ return await this . manager . getCurrentOutboundCapacity ( {
332
+ chainId : toChainId ( chain ) ,
333
+ tokenAddress : address . toUint8Array ( ) ,
334
+ } ) ;
324
335
}
325
336
326
- async getOutboundLimit ( ) : Promise < bigint > {
327
- //const encoded: EncodedTrimmedAmount = (
328
- // await this.manager.getOutboundLimitParams()
329
- //).limit;
330
- //const trimmedAmount: TrimmedAmount = decodeTrimmedAmount(encoded);
331
- //const tokenDecimals = await this.getTokenDecimals();
337
+ async getOutboundLimit ( localToken : TokenId ) : Promise < bigint > {
338
+ const { chain, address } = await this . getOriginalToken ( localToken ) ;
332
339
333
- //return untrim(trimmedAmount, tokenDecimals);
334
- throw new Error ( "Not implemented" ) ;
340
+ const encoded : EncodedTrimmedAmount = (
341
+ await this . manager . getOutboundLimitParams ( {
342
+ chainId : toChainId ( chain ) ,
343
+ tokenAddress : address . toUint8Array ( ) ,
344
+ } )
345
+ ) . limit ;
346
+
347
+ const trimmedAmount : TrimmedAmount = decodeTrimmedAmount ( encoded ) ;
348
+ const tokenDecimals = await this . getTokenDecimals ( localToken ) ;
349
+
350
+ return untrim ( trimmedAmount , tokenDecimals ) ;
335
351
}
336
352
337
353
async getCurrentInboundCapacity (
338
- originalToken : TokenId ,
354
+ originalToken : MultiTokenNtt . OriginalTokenId ,
339
355
fromChain : Chain
340
356
) : Promise < bigint > {
341
- if ( isNative ( originalToken . address ) )
342
- throw new Error ( "Native token not supported" ) ;
343
357
return await this . manager . getCurrentInboundCapacity (
344
358
{
345
- chainId : toChainId ( fromChain ) ,
346
- tokenAddress : originalToken . address . toUniversalAddress ( ) . toUint8Array ( ) ,
359
+ chainId : toChainId ( originalToken . chain ) ,
360
+ tokenAddress : originalToken . address . toUint8Array ( ) ,
347
361
} ,
348
362
toChainId ( fromChain )
349
363
) ;
350
364
}
351
365
352
- async getInboundLimit ( fromChain : Chain ) : Promise < bigint > {
353
- //const encoded: EncodedTrimmedAmount = (
354
- // await this.manager.getInboundLimitParams(toChainId(fromChain))
355
- //).limit;
356
- //const trimmedAmount: TrimmedAmount = decodeTrimmedAmount(encoded);
357
- //const tokenDecimals = await this.getTokenDecimals();
366
+ async getInboundLimit (
367
+ originalToken : MultiTokenNtt . OriginalTokenId ,
368
+ fromChain : Chain
369
+ ) : Promise < bigint | null > {
370
+ const localToken = await this . getLocalToken ( originalToken ) ;
371
+ if ( localToken === null ) return null ; // Token not yet created
372
+
373
+ const encoded : EncodedTrimmedAmount = (
374
+ await this . manager . getInboundLimitParams (
375
+ {
376
+ chainId : toChainId ( originalToken . chain ) ,
377
+ tokenAddress : originalToken . address . toUint8Array ( ) ,
378
+ } ,
379
+ toChainId ( fromChain )
380
+ )
381
+ ) . limit ;
382
+
383
+ const trimmedAmount : TrimmedAmount = decodeTrimmedAmount ( encoded ) ;
384
+ if ( trimmedAmount . amount === 0n && trimmedAmount . decimals === 0 )
385
+ return null ;
358
386
359
- //return untrim(trimmedAmount, tokenDecimals);
360
- throw new Error ( "Not implemented" ) ;
387
+ const tokenDecimals = await this . getTokenDecimals ( localToken ) ;
388
+
389
+ return untrim ( trimmedAmount , tokenDecimals ) ;
361
390
}
362
391
363
392
async getRateLimitDuration ( ) : Promise < bigint > {
@@ -395,21 +424,29 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
395
424
yield this . createUnsignedTx ( tx , "Ntt.completeInboundQueuedTransfer" ) ;
396
425
}
397
426
398
- async getOriginalToken ( localToken : TokenId ) : Promise < TokenId > {
427
+ async getOriginalToken (
428
+ localToken : TokenId
429
+ ) : Promise < MultiTokenNtt . OriginalTokenId > {
399
430
const [ tokenId ] = await this . manager . getTokenId (
400
431
localToken . address . toString ( )
401
432
) ;
402
- return Wormhole . tokenId ( toChain ( tokenId . chainId ) , tokenId . tokenAddress ) ;
433
+
434
+ const chain = toChain ( tokenId . chainId ) ;
435
+ const address = toUniversal ( chain , tokenId . tokenAddress ) ;
436
+
437
+ return {
438
+ chain,
439
+ address,
440
+ } ;
403
441
}
404
442
405
443
// This will return null if the token is not yet created
406
- async getLocalToken ( originalToken : TokenId ) : Promise < TokenId | null > {
407
- if ( isNative ( originalToken . address ) )
408
- throw new Error ( "Native token not supported" ) ;
409
-
444
+ async getLocalToken (
445
+ originalToken : MultiTokenNtt . OriginalTokenId
446
+ ) : Promise < TokenId | null > {
410
447
const localToken = await this . manager . getToken ( {
411
448
chainId : toChainId ( originalToken . chain ) ,
412
- tokenAddress : originalToken . address . toUniversalAddress ( ) . toUint8Array ( ) ,
449
+ tokenAddress : originalToken . address . toUint8Array ( ) ,
413
450
} ) ;
414
451
415
452
if ( localToken === ethers . ZeroAddress ) return null ;
@@ -423,14 +460,11 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
423
460
}
424
461
425
462
async calculateLocalTokenAddress (
426
- originalToken : TokenId ,
463
+ originalToken : MultiTokenNtt . OriginalTokenId ,
427
464
tokenName : string ,
428
465
tokenSymbol : string ,
429
466
tokenDecimals : number
430
467
) : Promise < TokenAddress < C > > {
431
- if ( isNative ( originalToken . address ) )
432
- throw new Error ( "Native token not supported" ) ;
433
-
434
468
const tokenImplementation = await this . manager . tokenImplementation ( ) ;
435
469
436
470
const initializeSelector = ethers . id ( "initialize(string,string,uint8)" ) ;
@@ -445,28 +479,20 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
445
479
initializeSelector . slice ( 0 , 10 ) ,
446
480
coder . encode (
447
481
[ "string" , "string" , "uint8" ] ,
448
- // name and symbol cannot be longer than 32 bytes
449
- // TODO: this assumes ascii
450
482
[ tokenName . slice ( 0 , 32 ) , tokenSymbol . slice ( 0 , 32 ) , tokenDecimals ]
451
483
) ,
452
484
] ) ,
453
485
]
454
486
) ;
455
487
456
- // TODO: we should fetch this from on-chain somehow?
457
- // type(ERC1967Proxy).creationCode;
458
- const proxyBytecode =
459
- "0x60806040526040516104e13803806104e1833981016040819052610022916102de565b61002e82826000610035565b50506103fb565b61003e83610061565b60008251118061004b5750805b1561005c5761005a83836100a1565b505b505050565b61006a816100cd565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100c683836040518060600160405280602781526020016104ba60279139610180565b9392505050565b6001600160a01b0381163b61013f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080856001600160a01b03168560405161019d91906103ac565b600060405180830381855af49150503d80600081146101d8576040519150601f19603f3d011682016040523d82523d6000602084013e6101dd565b606091505b5090925090506101ef868383876101f9565b9695505050505050565b60608315610268578251600003610261576001600160a01b0385163b6102615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610136565b5081610272565b610272838361027a565b949350505050565b81511561028a5781518083602001fd5b8060405162461bcd60e51b815260040161013691906103c8565b634e487b7160e01b600052604160045260246000fd5b60005b838110156102d55781810151838201526020016102bd565b50506000910152565b600080604083850312156102f157600080fd5b82516001600160a01b038116811461030857600080fd5b60208401519092506001600160401b038082111561032557600080fd5b818501915085601f83011261033957600080fd5b81518181111561034b5761034b6102a4565b604051601f8201601f19908116603f01168101908382118183101715610373576103736102a4565b8160405282815288602084870101111561038c57600080fd5b61039d8360208301602088016102ba565b80955050505050509250929050565b600082516103be8184602087016102ba565b9190910192915050565b60208152600082518060208401526103e78160408501602087016102ba565b601f01601f19169190910160400192915050565b60b1806104096000396000f3fe608060405236601057600e6013565b005b600e5b601f601b6021565b6058565b565b600060537f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e8080156076573d6000f35b3d6000fdfea2646970667358221220a2c581c6f59f8c322a89fe1c7cb21b56cf367c966e2b04f8b38bf4488beca08d64736f6c63430008130033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564" ;
488
+ const creationCode = await this . manager . tokenProxyCreationCode ( ) ;
460
489
461
- const initCode = ethers . concat ( [ proxyBytecode , constructorArgs ] ) ;
490
+ const initCode = ethers . concat ( [ creationCode , constructorArgs ] ) ;
462
491
const initCodeHash = ethers . keccak256 ( initCode ) ;
463
492
464
493
const salt = ethers . solidityPackedKeccak256 (
465
494
[ "uint16" , "bytes32" ] ,
466
- [
467
- toChainId ( originalToken . chain ) ,
468
- originalToken . address . toUniversalAddress ( ) . toUint8Array ( ) ,
469
- ]
495
+ [ toChainId ( originalToken . chain ) , originalToken . address . toUint8Array ( ) ]
470
496
) ;
471
497
472
498
// The address where the token will be deployed
0 commit comments