2020-07-31 10:51:07 -07:00
|
|
|
|
# Solana Wormhole Program
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
|
|
|
|
The `Wormhole` program acts as a bridge for Solana \<> Foreign Chain transfers using the WhP (WormHoleProtocol).
|
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
## Instructions
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
#### Initialize
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
|
|
|
|
Initializes a new Bridge at `bridge`.
|
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------ | ------------ | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 0 | sys | SystemProgram | | | | |
|
|
|
|
|
| 1 | clock | Sysvar | | | | ✅ |
|
2020-11-19 13:47:09 -08:00
|
|
|
|
| 2 | bridge | BridgeConfig | | ✅ | ✅ | ✅ |
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| 3 | guardian_set | GuardianSet | | ✅ | ✅ | ✅ |
|
|
|
|
|
| 4 | payer | Account | ✅ | | | |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-31 12:05:38 -07:00
|
|
|
|
#### PokeProposal
|
|
|
|
|
|
|
|
|
|
Pokes a `TransferOutProposal` so it is reprocessed by the guardians.
|
|
|
|
|
|
2021-01-21 02:59:06 -08:00
|
|
|
|
**Deprecated:** PokeProposals were a workaround for unreliable message delivery on Solana. Now that this has been fixed
|
|
|
|
|
using a control loop (https://github.com/certusone/wormhole/commit/fd6c54de836cb9f4c423aa334b73546a139c0ee6), poking is
|
|
|
|
|
no longer required. The feature is left in place for backwards compatibility reasons.
|
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------ | ------------ | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 0 | proposal | TransferOutProposal | | ✅ | ️ | ✅ |
|
2020-08-31 12:05:38 -07:00
|
|
|
|
|
2020-10-14 02:49:13 -07:00
|
|
|
|
#### CreateWrappedAsset
|
|
|
|
|
|
|
|
|
|
Creates a new `WrappedAsset` to be used to create accounts and later receive transfers on chain.
|
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 0 | sys | SystemProgram | | | | |
|
|
|
|
|
| 1 | token_program | SplToken | | | | |
|
|
|
|
|
| 2 | rent | Sysvar | | | | ✅ |
|
|
|
|
|
| 3 | bridge | BridgeConfig | | | | |
|
|
|
|
|
| 4 | payer | Account | ✅ | | | |
|
|
|
|
|
| 5 | wrapped_mint | WrappedAsset | | | ✅ | ✅ |
|
|
|
|
|
| 6 | wrapped_meta_account | WrappedAssetMeta | | ✅ | ✅ | ✅ |
|
2020-10-14 02:49:13 -07:00
|
|
|
|
|
2020-10-01 07:42:45 -07:00
|
|
|
|
#### VerifySignatures
|
|
|
|
|
|
|
|
|
|
Checks secp checks (in the previous instruction) and stores results.
|
|
|
|
|
|
2020-11-19 13:47:09 -08:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------ | ------------ | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 0 | bridge_p | BridgeProgram | | | | |
|
|
|
|
|
| 1 | sys | SystemProgram | | | | |
|
|
|
|
|
| 2 | instructions | Sysvar | | | | ✅ |
|
|
|
|
|
| 3 | bridge_config | BridgeConfig | | ✅ | | ✅ |
|
|
|
|
|
| 4 | sig_status | SignatureState | | ✅ | | |
|
|
|
|
|
| 5 | guardian_set | GuardianSet | | | | ✅ |
|
|
|
|
|
| 6 | payer | Account | ✅ | | | |
|
2020-10-01 07:42:45 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
#### TransferOut
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
|
|
|
|
Burns a wrapped asset `token` from `sender` on the Solana chain.
|
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
The transfer proposal will be tracked at a new account `proposal` where VAAs will be submitted by guardians.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-11-30 02:09:08 -08:00
|
|
|
|
This instruction needs to be preceded by a SOL Transfer instruction that transfers the fee to the BridgeConfig.
|
|
|
|
|
The fee can be calculated using the rules explained in the protocol documentation and `Bridge::transfer_fee()`.
|
|
|
|
|
|
2020-07-28 03:40:15 -07:00
|
|
|
|
Parameters:
|
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 0 | bridge_p | BridgeProgram | | | | |
|
|
|
|
|
| 1 | sys | SystemProgram | | | | |
|
|
|
|
|
| 2 | token_program | SplToken | | | | |
|
|
|
|
|
| 3 | rent | Sysvar | | | | ✅ |
|
2020-11-30 02:09:08 -08:00
|
|
|
|
| 4 | clock | Sysvar | | | | ✅ |
|
|
|
|
|
| 5 | instructions | Sysvar | | | | ✅ |
|
|
|
|
|
| 6 | token_account | TokenAccount | | ✅ | | |
|
|
|
|
|
| 7 | bridge | BridgeConfig | | | | |
|
|
|
|
|
| 8 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
|
|
|
|
|
| 9 | token | WrappedAsset | | ✅ | | ✅ |
|
|
|
|
|
| 10 | payer | Account | ✅ | | | |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
#### TransferOutNative
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
Locks a Solana native token (spl-token) `token` from `sender` on the Solana chain by transferring it to the
|
2020-07-28 03:40:15 -07:00
|
|
|
|
`custody_account`.
|
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
The transfer proposal will be tracked at a new account `proposal` where a VAA will be submitted by guardians.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-11-30 02:09:08 -08:00
|
|
|
|
This instruction needs to be preceded by a SOL Transfer instruction that transfers the fee to the BridgeConfig.
|
|
|
|
|
The fee can be calculated using the rules explained in the protocol documentation and `Bridge::transfer_fee()`.
|
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | --------------- | ------------------- | ------ | --------- | ----- | ------- |
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| 0 | bridge_p | BridgeProgram | | | | |
|
|
|
|
|
| 1 | sys | SystemProgram | | | | |
|
|
|
|
|
| 2 | token_program | SplToken | | | | |
|
|
|
|
|
| 3 | rent | Sysvar | | | | ✅ |
|
|
|
|
|
| 4 | clock | Sysvar | | | | ✅ |
|
2020-11-30 02:09:08 -08:00
|
|
|
|
| 5 | instructions | Sysvar | | | | ✅ |
|
|
|
|
|
| 6 | token_account | TokenAccount | | ✅ | | |
|
|
|
|
|
| 7 | bridge | BridgeConfig | | | | |
|
|
|
|
|
| 8 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
|
|
|
|
|
| 9 | token | Mint | | ✅ | | |
|
|
|
|
|
| 10 | payer | Account | ✅ | | | |
|
|
|
|
|
| 11 | custody_account | TokenAccount | | ✅ | opt | ✅ |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
#### EvictTransferOut
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
Deletes a `proposal` after the `VAA_EXPIRATION_TIME` to free up space on chain. This returns the rent to `guardian`.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| 0 | bridge_p | BridgeProgram | | | | |
|
|
|
|
|
| 1 | guardian | Account | ✅ | | | |
|
|
|
|
|
| 2 | clock | Sysvar | | | | ✅ |
|
|
|
|
|
| 3 | bridge | BridgeConfig | | | | |
|
|
|
|
|
| 4 | proposal | TransferOutProposal | | ✅ | | ✅ |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-09 23:48:25 -07:00
|
|
|
|
#### EvictClaimedVAA
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-09 23:48:25 -07:00
|
|
|
|
Deletes a `ClaimedVAA` after the `VAA_EXPIRATION_TIME` to free up space on chain. This returns the rent to `guardian`.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| 0 | bridge_p | BridgeProgram | | | | |
|
|
|
|
|
| 1 | guardian | Account | ✅ | | | |
|
|
|
|
|
| 2 | clock | Sysvar | | | | ✅ |
|
|
|
|
|
| 3 | bridge | BridgeConfig | | | | |
|
|
|
|
|
| 4 | claim | ClaimedVAA | | ✅ | | ✅ |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-09 09:26:58 -07:00
|
|
|
|
#### SubmitVAA
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
Submits a VAA signed by the guardians to perform an action.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
The required accounts depend on the `action` of the VAA:
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-07 03:09:53 -07:00
|
|
|
|
All require:
|
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 0 | bridge_p | BridgeProgram | | | | |
|
|
|
|
|
| 1 | sys | SystemProgram | | | | |
|
|
|
|
|
| 2 | rent | Sysvar | | | | ✅ |
|
|
|
|
|
| 3 | clock | Sysvar | | | | ✅ |
|
2020-11-19 13:47:09 -08:00
|
|
|
|
| 4 | bridge | BridgeConfig | | ✅ | | |
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| 5 | guardian_set | GuardianSet | | | | |
|
|
|
|
|
| 6 | claim | ExecutedVAA | | ✅ | ✅ | ✅ |
|
2020-11-19 13:47:09 -08:00
|
|
|
|
| 7 | sig_info | SigState | | ✅ | ✅ | |
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| 8 | payer | Account | ✅ | | | |
|
2020-08-07 03:09:53 -07:00
|
|
|
|
|
|
|
|
|
followed by:
|
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
##### Guardian set update
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 9 | guardian_set_new | GuardianSet | | ✅ | ✅ | ✅ |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2021-01-19 04:01:45 -08:00
|
|
|
|
##### Contract upgrade
|
|
|
|
|
|
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------------------ | ----------------- | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 9 | new_contract | Account | | | ✅ | |
|
|
|
|
|
| 10 | program_data | Account | | ✅ | ✅ | ✅ |
|
|
|
|
|
| 11 | upgradeable_loader | UpgradeableLoader | | | | |
|
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
##### Transfer: Ethereum (native) -> Solana (wrapped)
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 9 | token_program | SplToken | | | | |
|
|
|
|
|
| 10 | token | WrappedAsset | | | | ✅ |
|
|
|
|
|
| 11 | destination | TokenAccount | | ✅ | | |
|
|
|
|
|
| 12 | wrapped_meta | WrappedMeta | | ✅ | opt | ✅ |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
##### Transfer: Ethereum (wrapped) -> Solana (native)
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
|
|
|
|
|
| 9 | token_program | SplToken | | | | |
|
|
|
|
|
| 10 | token | Mint | | | | ✅ |
|
|
|
|
|
| 11 | destination | TokenAccount | | ✅ | opt | |
|
|
|
|
|
| 12 | custody_src | TokenAccount | | ✅ | | ✅ |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
##### Transfer: Solana (any) -> Ethereum (any)
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
| Index | Name | Type | signer | writeable | empty | derived |
|
|
|
|
|
| ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- |
|
2020-10-01 07:42:45 -07:00
|
|
|
|
| 9 | out_proposal | TransferOutProposal | | ✅ | | ✅ |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
## Accounts
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
|
|
|
|
The following types of accounts are owned by creators of bridges:
|
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
#### _BridgeConfig_ Account
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
|
|
|
|
This account tracks the configuration of the transfer bridge.
|
|
|
|
|
|
2020-10-22 11:52:16 -07:00
|
|
|
|
| Parameter | Description |
|
|
|
|
|
| ------------------ | -------------------------------------------------------------------------------------------------------- |
|
|
|
|
|
| VAA_EXPIRATION_TIME | Period for how long a VAA is valid. This exists to guarantee data availability and prevent replays |
|
|
|
|
|
| GUARDIAN_SET_INDEX | Index of the current active guardian set //TODO do we need to track this if the VAA contains the index? |
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
## Program Accounts
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
|
|
|
|
The program own the following types of accounts:
|
|
|
|
|
|
2020-08-09 23:48:25 -07:00
|
|
|
|
#### _ClaimedVAA_ Account
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-09 23:48:25 -07:00
|
|
|
|
> Seed derivation: `claim || <bridge> || <hash>`
|
|
|
|
|
>
|
|
|
|
|
> **bridge**: Pubkey of the bridge
|
2020-07-28 03:40:15 -07:00
|
|
|
|
>
|
2020-08-09 23:48:25 -07:00
|
|
|
|
> **hash**: signing hash of the VAA
|
2020-07-31 10:51:07 -07:00
|
|
|
|
|
|
|
|
|
This account is created when a VAA is executed/consumed on Solana (i.e. not when a TransferOutProposal is approved).
|
|
|
|
|
It tracks a used VAA to protect from replay attacks where a VAA is executed multiple times. This account stays active
|
2020-08-09 23:48:25 -07:00
|
|
|
|
until the `VAA_EXPIRATION_TIME` has passed and can then be evicted using `IEvictClaimedVAA`.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
#### _GuardianSet_ Account
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-09 09:26:58 -07:00
|
|
|
|
> Seed derivation: `guardian || <bridge> || <index>`
|
|
|
|
|
>
|
|
|
|
|
> **bridge**: Pubkey of the bridge
|
2020-07-31 10:51:07 -07:00
|
|
|
|
>
|
|
|
|
|
> **index**: Index of the guardian set
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2021-01-20 15:59:50 -08:00
|
|
|
|
This account is created when a new guardian set is set. It tracks the public key hash, creation time and expiration time of
|
2020-07-31 10:51:07 -07:00
|
|
|
|
this set.
|
|
|
|
|
The expiration time is set when this guardian set is abandoned. When a switchover happens, the guardian-issued VAAs will
|
|
|
|
|
still be valid until the expiration time.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
#### _TransferOutProposal_ Account
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-09 09:26:58 -07:00
|
|
|
|
> Seed derivation: `transfer || <bridge> || <asset_chain> || <asset> || <target_chain> || <target_address> || <sender> || <nonce>`
|
2020-07-28 03:40:15 -07:00
|
|
|
|
>
|
2020-08-09 09:26:58 -07:00
|
|
|
|
> **bridge**: Pubkey of the bridge
|
|
|
|
|
>
|
|
|
|
|
> **asset_chain**: CHAIN_ID of the native chain of this asset
|
2020-07-28 03:40:15 -07:00
|
|
|
|
>
|
|
|
|
|
> **asset**: address of the asset
|
|
|
|
|
>
|
2020-08-09 09:26:58 -07:00
|
|
|
|
> **target_chain**: ChainID of the recipient
|
|
|
|
|
>
|
|
|
|
|
> **target_address**: address of the recipient
|
|
|
|
|
>
|
|
|
|
|
> **sender**: pubkey of the sender
|
|
|
|
|
>
|
|
|
|
|
> **nonce**: nonce of the transfer
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
This account is created when a user wants to lock tokens to transfer them to a foreign chain using the `ITransferOut`
|
|
|
|
|
instruction.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
It is used to signal a pending transfer to a foreign chain and will also store the respective VAA provided using
|
2020-08-09 09:26:58 -07:00
|
|
|
|
`ISubmitVAA`.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
Once the VAA has been published this TransferOut is considered completed and can be evicted using `EvictTransferOut`
|
|
|
|
|
after `VAA_EXPIRATION_TIME` has passed.
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-07-31 10:51:07 -07:00
|
|
|
|
#### _WrappedAsset_ Mint
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-09 09:26:58 -07:00
|
|
|
|
> Seed derivation: `wrapped || <bridge> || <chain> || <asset>`
|
|
|
|
|
>
|
|
|
|
|
> **bridge**: Pubkey of the bridge
|
2020-07-28 03:40:15 -07:00
|
|
|
|
>
|
|
|
|
|
> **chain**: CHAIN_ID of the native chain of this asset
|
|
|
|
|
>
|
|
|
|
|
> **asset**: address of the asset on the foreign chain
|
|
|
|
|
|
|
|
|
|
This account is an instance of `spl-token/Mint` tracks a wrapped asset on the Solana chain.
|
|
|
|
|
|
2020-08-09 09:26:58 -07:00
|
|
|
|
#### _WrappedAssetMeta_ Mint
|
|
|
|
|
|
|
|
|
|
> Seed derivation: `meta || <bridge> || <wrapped>`
|
|
|
|
|
>
|
|
|
|
|
> **bridge**: Pubkey of the bridge
|
|
|
|
|
>
|
|
|
|
|
> **wrapped**: address of the wrapped asset
|
|
|
|
|
|
|
|
|
|
This account tracks the metadata about a wrapped asset to allow reverse lookups.
|
|
|
|
|
|
|
|
|
|
#### _Custody_ TokenAccount
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
2020-08-09 09:26:58 -07:00
|
|
|
|
> Seed derivation: `custody || <bridge> || <asset>`
|
2020-07-28 03:40:15 -07:00
|
|
|
|
>
|
2020-08-09 09:26:58 -07:00
|
|
|
|
> **bridge**: Pubkey of the bridge
|
|
|
|
|
>
|
|
|
|
|
> **asset**: address of the asset mint on the native chain
|
2020-07-28 03:40:15 -07:00
|
|
|
|
|
|
|
|
|
This account is an instance of `spl-token/TokenAccount` and holds spl tokens in custody that have been transferred to a
|
|
|
|
|
foreign chain.
|