Implement initial spec (#2)

* docs: Upgraded design doc

* update formatting

* update set change VAA

* typo fix

* Update protocol.md

* wording and typos

* Update protocol.md

* clarify use of MultiSig and data-availability

* nits in the protocol

* fix typo

* update solana program for new spec

* track executed VAAs

* finalize initial spec

Co-authored-by: Leopold Schabel <leo@certus.one>
This commit is contained in:
Hendrik Hofstadt 2020-07-31 19:51:07 +02:00 committed by GitHub
parent ec7f7565da
commit 72cbb2aec2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 411 additions and 150 deletions

260
docs/protocol.md Normal file
View File

@ -0,0 +1,260 @@
# Wormhole Protocol
The Wormhole protocol is a way of transferring assets between a **root chain** and multiple **foreign chains**.
Therefor it makes use of decentralized oracles called **guardians** to relay transfer information about token transfers
between the chains.
## The role of guardians
Guardians are responsible for monitoring the root and foreign chains for token transfers to bridge *smart contracts*.
This can be done using full or light clients of the particular network.
They need to make sure to monitor finality of transactions (e.g. track number of confirmations) before relaying messages.
A guardian is identified by an **admin key** and **voter key**.
The **admin key** is supposed to be held in cold-storage and is used to manage rewards and assign a signer key.
The **signer key** is a hot-key that is used to confirm asset transfers between chains by reporting lockups of tokens
on a foreign chain on the root chain or the other way around.
## Protocol
The following section describes the protocol and design decisions made.
### Signature scheme
In order to implement a trustless bridge, there needs to be a consensus mechanism to measure whether there is a quorum
on a cross chain transfer to prevent a single malicious actor from unlocking or minting an infinite amount of assets.
There are multiple ways to measure whether enough validators have approved a decision:
#### Multiple signatures - MultiSig
The most simple solution is by using a *MultiSig* mechanism. This means that each guardian would sign a message
and submit it to a smart contract on-chain with reference to a *decision* that the guardians need to make (e.g. a transfer).
Since a transaction itself is already signed, we can simplify this to using the transaction itself as proof.
Said smart contract will count the number of guardians that have submitted a transaction for a *decision*.
Once the consensus threshold has been reached, the contract will execute the action the guardians have agreed on.
The issue with this schema is that it requires at least `n=2/3*m+1` transactions for `m` validators. On Ethereum for
example one such transaction would cost `21k+20k+x` gas (base + `SSTORE` \[to track the tx] + additional compute).
With `n` txs and 20 guardians threshold (`2/3m+1`) the cost would be `n*(41k+x)` which is `820k+20x`.
At a gas price of `50 Gwei` this would mean total tx costs of `0.041 ETH` at `x=0`. At an ETH price of `300$` that
means costs of `12.3$`.
These prices will require the guardians to charge significant fees. If these fees are not covered by the user, bridge
transactions would stall and time out.
There are a couple of other issues with this concept:
1. There is no way for the Solana Bridge program to verify whether the guardians have actually unlocked the tokens on
the foreign chain.
2. Users cannot cover gas costs themselves because transactions are not "portable". I.e. the require serialized nonces.
If a guardian submits a transaction with nonce 20 to the user but in the meantime issues another transaction with the
same nonce, the user tx will be invalid even though the Solana program might successfully verify the tx (as it does not
know the state of ETH).
There is an alternative way by using portable ECDSA signatures that approve an action i.e. a transfer. The guardians
could submit all of those signatures to the lock proposal and the user or another participant in the network could relay
them to Ethereum.
That way the Solana program can verify that the signatures and signed action are valid, being sure that if there is a
quorum (i.e. enough signatures), the user could use these signatures to trigger the execution of the signed action on
the foreign chain.
The downside here is that this makes tracking and synchronizing guardian changes highly complex and further increases
gas costs by about `(5k+5k)*n` (`ECRECOVER+GTXDATANONZERO*72`) for the additional `ecrecover` calls that need to be made.
However since all signatures can be aggregate into one tx, we'll save `(n-1)*21k` leading to an effective gas saving of
`~10k*n`. Still, transfers would be considerably expensive applying the aforementioned assumptions.
#### Threshold signatures
Most of the disadvantages of the MultiSig solution come down to the high gas costs of verifying multiple transactions
and tracking individual guardian key changes / set changes on other chains.
In order to prove a quorum on a single signature, there exist different mechanisms for so-called Threshold signatures.
A single signature is generated using a multi party computation process or aggregation of signatures from different
parties of a group and only valid if a previously specified quorum has participated in the generation of such signature.
This would essentially mean that such a signature could be published on the Solana chain and relayed by anyone to
authorize an action on another chain, the same concept as described above but implemented with the cost of only
sending and verifying one signature.
Since we target Ethereum as primary foreign chain, there are 3 viable options of threshold signatures:
**t-ECDSA**
Threshold ECDSA signatures generated using [GG20](https://eprint.iacr.org/2020/540.pdf).
This is a highly complex, cutting edge cryptographic protocol that requires significant amounts of compute to generate
signatures with larger quorums.
Still, it generates plain ECDSA signatures that can easily be verified on Ethereum (`5k gas`) or even be used for Bitcoin
transactions.
**BLS**
BonehLynnShacham threshold signatures are very lightweight because they don't require a multi-round process and can
simply be aggregated from multiple individual signatures. This would eliminate the need for a p2p layer for MPC
communication.
However, verifying a BLS signature on Ethereum costs about 130k gas using the precompiled pairing functions over bn128.
Also there's very little prior work on this scheme especially in the context of Solidity.
**Schnorr-Threshold**
Schnorr threshold signatures require a multi-round computation and distributed key generation.
They can be verified on Ethereum extremely cheaply (https://blog.chain.link/threshold-signatures-in-chainlink/) and scale
well with more signing parties.
There's been significant prior work in the blockchain space, several implementations over different curves and a proposal
to implement support on Bitcoin (BIP340).
---
A great overview can be found [here](https://github.com/Turing-Chain/TSSKit-Threshold-Signature-Scheme-Toolkit)
#### Design choices
For transfers we implement a Schnorr-Threshold signature schema based on the implementation from Chainlink.
We'll create a portable "action blob" with a threshold signature to allow anyone to relay action approvals
between chains. We call this structure: **VAA** (Verifiable Action Approval).
A validator action approval leads to information symmetry i.e. if the validators have submitted a VAA to a token lockup
on Solana, this VAA can be used to unlock the tokens on the specified foreign chain, it also proves to the Solana chain
that the lockup is not refundable as it can provably be claimed (as long as safety guarantees are not broken and except
for the case of a guardian set change which is discussed later).
While for the above mentioned transfers from Solana => foreign chain we use Solana for data availability of the VAAs,
in the other direction data availability i.e. the guardians posting the VAA on the foreign chain (where the transfer
was initiated) is optional because in most cases it will be substantially cheaper for the guardians to directly submit
the VAA on Solana itself to unlock/mint the transferred tokens there.
### VAA - Verifiable Action Approval
Verifiable action approvals are used to approve the execution of a specified action on a chain.
They are structured as follows:
```
Header:
uint8 version (0x01)
uint32 guardian set index
[72]uint8 signature(body)
body:
uint32 unix seconds
uint8 action
uint8 payload_size
[payload_size]uint8 payload
```
The `guardian set index` does not need to be in the signed body since it is verifiable using the signature itself which
is created using the guardian set's key.
It is a monotonically number that's increased every time a validator set update happens and tracks the public key of the
set.
#### Actions
##### Guardian set update
ID: `0x01`
Size: `32 byte`
Payload:
```
[32]uint8 new_key
uint32 new_index
```
The `new_index` must be monotonically increasing and is manually specified here to fix a potential guardian_set index
desynchronization between the any of the chains in the system.
##### Transfer
ID: `0x10`
Size: `75 byte`
Payload:
```
uint8 source_chain
uint8 target_chain
[32]uint8 target_address
uint8 token_chain
[32]uint8 token_address
uint64 amount
```
### Cross-Chain Transfers
#### Transfer of assets Foreign Chain -> Root Chain
The user sends a chain native asset to the bridge on the foreign chain using the `Lock` function.
The lock function takes a Solana `address` as parameter which is the TokenAccount that should receive the wrapped token.
Guardians will pick up the *Lock transaction* once it has enough confirmations on the foreign chain. The amount of
confirmations required is a parameter that guardians can specify individually.
They check for the validity, parse it and will then send a `ConfirmForeignLockup` transaction to the Solana program
testifying that they have seen a foreign lockup. Once the quorum has been reached, a new wrapped asset will be minted or
released from custody. Custody is used for Solana-native tokens that have previously been transferred to a foreign
chain, minting will be used to create new units of a wrapped foreign-chain asset.
If this is the first time a foreign asset is minted, a new **Mint** (token) will be created on quorum.
### Transfer of assets Root Chain -> Foreign Chain
The user sends a **Lock** or **LockNative** instruction to the *Bridge program*.
**Lock** has to be used for wrapped assets that should be transferred to a foreign chain. They will be burned on Solana.
**LockNative** has to be used for Solana-native assets that should be transferred to a foreign chain. They will be held
in a custody account until the tokens are transferred back from the foreign chain.
The lock function takes a `chain_id` which identifies the foreign chain the tokens should be sent to and a `foreign_address`
which is a left-zero-padded address on the foreign chain. This operation creates a **LockProposal** account
that tracks the status of the transfer.
Guardians will pick up the **LockProposal** once it has enough confirmations on the Solana network. It defaults to
full confirmation (i.e. the max lockup, currently 32 slots), but can be changed to a different commitment levels
on each guardian's discretion.
They check for the validity of the tx, parse it and will initiate an off-chain threshold signature ceremony which will
output a **VAA** that can be used with a foreign chain smart contract to reclaim an unwrapped local asset or mint a
wrapped `spl-token`.
This VAA will be posted on Solana by one of the guardians using the `PostVAA` instruction and will be stored in the
`LockProposal`.
Depending on whether the fees are sufficient for **guardians** or **relayers** to cover the foreign chain fees, they
will also post the VAA on the foreign chain, completing the transfer.
If no fee or an insufficient fee is specified, the user can pick up the VAA from the `LockProposal` and submit it on the foreign chain themselves.
VAAs for conducting transfers to a foreign chain are submitted using `FinalizeTransfer`.
### Fees
TODO \o/
### Config changes
#### Guardian set changes
Since we use a *TSS* (Threshold signature scheme) for VAAs, changes to the guardian list are finalized by setting a
new aggregate public key that's derived from a distributed key generation ("DKG") ceremony of the new guardian set.
This new public key is set via a VAA with the `UPDATE_GUARDIANS` action that is signed by the previous guardians.
The guardians need to make sure that the sets are synchronized between all chains.
If the guardian set is changed, the guardian must also be replaced on all foreign chains. Therefore we
conduct these changes via VAAs that are universally valid on all chains.
That way, if a change is made on the root chain, the same signatures can be used to trigger the same
update on the foreign chain. This allows all parties in the system to propagate bridge state changes across all
chains.
If all VAAs issued by the previous guardian set would immediately become invalid once a new guardian set takes over, that would
lead to some payments being "stuck". Therefore we track a list of previous guardian sets. VAAs issued by old
guardian sets stay valid for one day from the time that the change happens.

View File

@ -1,10 +1,10 @@
## Solana Wormhole Program
# Solana Wormhole Program
The `Wormhole` program acts as a bridge for Solana \<> Foreign Chain transfers using the WhP (WormHoleProtocol).
### Instructions
## Instructions
##### Initialize
#### Initialize
Initializes a new Bridge at `bridge`.
@ -13,198 +13,158 @@ Initializes a new Bridge at `bridge`.
| 0 | owner | Account | ✅️ | | | |
| 0 | bridge | BridgeConfig | | | ✅️ | ✅️ |
##### Lock
#### TransferOut
Burns a wrapped asset `token` from `sender` on the Solana chain.
The transfer proposal will be tracked at a new account `proposal` where VPAs will be submitted by guardians.
The transfer proposal will be tracked at a new account `proposal` where VAAs will be submitted by guardians.
Parameters:
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | -------- | ------------ | ------ | --------- | ----- | ------- |
| 0 | sender | TokenAccount | | ✅ | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | LockProposal | | ✅ | ✅ | ✅ |
| 3 | token | WrappedAsset | | ✅ | | ✅ |
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
| 0 | sender | TokenAccount | | ✅ | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
| 3 | token | WrappedAsset | | ✅ | | ✅ |
##### LockNative
#### TransferOutNative
Locks a Solana native token (spl-token) `token` from `sender` on the Solana chain by transferring it to the
Locks a Solana native token (spl-token) `token` from `sender` on the Solana chain by transferring it to the
`custody_account`.
The transfer proposal will be tracked at a new account `proposal` where VPAs will be submitted by guardians.
The transfer proposal will be tracked at a new account `proposal` where a VAA will be submitted by guardians.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | --------------- | ------------ | ------ | --------- | ----- | ------- |
| 0 | sender | TokenAccount | | ✅ | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | LockProposal | | ✅ | ✅ | ✅ |
| 3 | token | Mint | | ✅ | | |
| 4 | custody_account | Mint | | ✅ | opt | ✅ |
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | --------------- | ------------------- | ------ | --------- | ----- | ------- |
| 0 | sender | TokenAccount | | ✅ | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
| 3 | token | Mint | | ✅ | | |
| 4 | custody_account | Mint | | ✅ | opt | ✅ |
##### PostVPA
#### EvictTransferOut
Submits a VPA signed by `guardian` on a valid `proposal`.
Deletes a `proposal` after the `VAA_EXPIRATION_TIME` to free up space on chain. This returns the rent to `guardian`.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | --------------- | ------------ | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | ✅ | | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | LockProposal | | ✅ | | ✅ |
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | | | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | TransferOutProposal | | ✅ | | ✅ |
##### Reclaim
#### EvictExecutedVAA
Reclaim tokens that did not receive enough VPAs on the `proposal` within the `SIGN_PERIOD` to finish the transfer.
`claimant` will get back the `locked_token` previously locked via `ILock`.
Deletes a `ExecutedVAA` after the `VAA_EXPIRATION_TIME` to free up space on chain. This returns the rent to `guardian`.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | ✅ | | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | ExecutedVAA | | ✅ | | ✅ |
#### PostVAA
Submits a VAA signed by the guardians to perform an action.
The required accounts depend on the `action` of the VAA:
##### Guardian set update
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- |
| 0 | bridge | BridgeConfig | | ✅ | | |
| 1 | guardian_set | GuardianSet | | ✅ | ✅ | ✅ |
| 2 | claim | ExecutedVAA | | ✅ | ✅ | ✅ |
##### Transfer: Ethereum (native) -> Solana (wrapped)
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
| 0 | claimant | TokenAccount | | ✅ | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | LockProposal | | ✅ | | ✅ |
| 3 | locked_token | WrappedAsset | | | | ✅ |
| 0 | bridge | BridgeConfig | | | | |
| 1 | guardian_set | GuardianSet | | | | |
| 2 | claim | ExecutedVAA | | ✅ | ✅ | ✅ |
| 3 | token | WrappedAsset | | | opt | ✅ |
| 4 | destination | TokenAccount | | ✅ | opt | |
##### ReclaimNative
Reclaim tokens that did not receive enough VPAs on the `proposal` within the `SIGN_PERIOD` to finish the transfer.
`claimant` will get back the `locked_token` previously locked via `ILockNative` from the `custody_account`.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | --------------- | ------------ | ------ | --------- | ----- | ------- |
| 0 | claimant | TokenAccount | | ✅ | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | LockProposal | | ✅ | | ✅ |
| 3 | locked_token | Mint | | | | |
| 4 | custody_account | Mint | | ✅ | | ✅ |
##### EvictLock
Deletes a `proposal` after the `BRIDGE_WAIT_PERIOD` to free up space on chain. This returns the rent to `guardian`.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | -------- | ------------ | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | ✅ | | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | LockProposal | | ✅ | | ✅ |
##### ConfirmForeignLockup
The `guardian` confirms that a user locked up a foreign asset on a foreign chain.
This creates or updates a `proposal` to mint the wrapped asset `token` to `destination`.
If enough confirmations have been submitted, this instruction mints the token.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | ----------- | ---------------------- | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | ✅ | | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | ReleaseWrappedProposal | opt | ✅ | | ✅ |
| 3 | token | WrappedAsset | | | opt | ✅ |
| 4 | destination | TokenAccount | | ✅ | opt? | |
##### ConfirmForeignLockupOfNative
The `guardian` confirms that a user locked up a native asset on a foreign chain.
This creates or updates a `proposal` to release the `token` to `destination` from `custody_src`.
If enough confirmations have been submitted, this instruction releases the token.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | ----------- | ---------------------- | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | ✅ | | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | ReleaseWrappedProposal | opt | ✅ | opt | ✅ |
| 3 | token | WrappedAsset | | | | ✅ |
| 4 | custody_src | TokenAccount | | ✅ | | ✅ |
| 5 | destination | TokenAccount | | ✅ | opt? | |
##### EvictRelease
Deletes a `proposal` after the `RELEASE_WRAPPED_TIMEOUT_PERIOD` to free up space on chain. This returns the rent to `guardian`.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | -------- | ------------------------------- | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | ✅ | | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | ReleaseWrappedProposal | | ✅ | | ✅ |✅ |
##### ChangeGuardianAdmin
This instruction is used to change the admin account of a guardian i.e. the account that manages rewards and the
signer account.
##### Transfer: Ethereum (wrapped) -> Solana (native)
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | ✅ | | | |
| 1 | bridge | BridgeConfig | | ✅ | | |
| 2 | new_guardian | Account | ✅ | | | |
| 0 | bridge | BridgeConfig | | | | |
| 1 | guardian_set | GuardianSet | | | | |
| 2 | claim | ExecutedVAA | | ✅ | ✅ | ✅ |
| 3 | token | Mint | | | | ✅ |
| 4 | custody_src | TokenAccount | | ✅ | | ✅ |
| 5 | destination | TokenAccount | | ✅ | opt | |
##### ChangeGuardianSigner
##### Transfer: Solana (any) -> Ethereum (any)
This instruction is used to change the signer account of a guardian.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- |
| 0 | bridge | BridgeConfig | | | | |
| 1 | guardian_set | GuardianSet | | | | |
| 2 | claim | ExecutedVAA | | ✅ | ✅ | ✅ |
| 3 | out_proposal | TransferOutProposal | | ✅ | | ✅ |
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | ---------- | ------------ | ------ | --------- | ----- | ------- |
| 0 | guardian | Account | ✅ | | | |
| 1 | bridge | BridgeConfig | | ✅ | | |
| 2 | new_signer | Account | ✅ | | | |
### Accounts
## Accounts
The following types of accounts are owned by creators of bridges:
##### _BridgeConfig_ Account
#### _BridgeConfig_ Account
This account tracks the configuration of the transfer bridge.
| Parameter | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SIGN_PERIOD | The period in which enough foreign chain signatures need to be aggregated before tokens are freed up again |
| BRIDGE_WAIT_PERIOD | The period after enough signatures have been published to a _lock account_ after which the account can be evicted. This exists to guarantee data availability |
| RELEASE_WRAPPED_TIMEOUT_PERIOD | The period in which enough votes need to be cast for an asset to be minted. |
| 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? |
### Program Accounts
## Program Accounts
The program own the following types of accounts:
##### _LockProposal_ Account
#### _ExecutedVAA_ Account
> Seed derivation: `lock_<chain>_<asset>_<lock_hash>`
> Seed derivation: `executedvaa_<vaa_hash>`
>
> **vaa_hash**: Hash of the VAA
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
until the `VAA_EXPIRATION_TIME` has passed and can then be evicted using `IEvictExecutedVAA`.
#### _GuardianSet_ Account
> Seed derivation: `guardians_<index>`
>
> **index**: Index of the guardian set
This account is created when a new guardian set is set. It tracks the public key, creation time and expiration time of
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.
#### _TransferOutProposal_ Account
> Seed derivation: `out_<chain>_<asset>_<transfer_hash>`
>
> **chain**: CHAIN_ID of the native chain of this asset
>
> **asset**: address of the asset
>
> **lock_hash**: Random ID of the lock
> **transfer_hash**: Random ID of the transfer
This account is created when a user wants to lock tokens to transfer them to a foreign chain using the `ILock` instruction.
This account is created when a user wants to lock tokens to transfer them to a foreign chain using the `ITransferOut`
instruction.
It tracks the progress of validator signatures. If not enough valid signatures are submitted within `SIGN_PERIOD`,
the tokens can be claimed by the user using the `IReclaim` instruction.
It is used to signal a pending transfer to a foreign chain and will also store the respective VAA provided using
`IPostVAA`.
If enough signatures have been submitted, the account can be deleted using `IEvictLock` after `BRIDGE_WAIT_PERIOD`,
freeing up the rent.
Once the VAA has been published this TransferOut is considered completed and can be evicted using `EvictTransferOut`
after `VAA_EXPIRATION_TIME` has passed.
##### _ReleaseWrappedProposal_ Account
> Seed derivation: `release_<chain>_<asset>_<foreign_lock_hash>`
>
> **chain**: CHAIN_ID of the native chain of this asset
>
> **asset**: address of the asset
>
> **foreign_lock_hash**: Hash of the foreign chain lock transaction
This account is created when the first validator sees a _fully confirmed_ **Lockup** of an asset on a foreign chain.
It tracks the confirmations of validators that have also seen the Lockup using `IConfirmForeignLockup`.
Once enough votes have been cast within the `RELEASE_WRAPPED_TIMEOUT_PERIOD`, this account is evicted and wrapped tokens are minted
or native tokens released.
If not enough votes are cast within the `RELEASE_WRAPPED_TIMEOUT_PERIOD`, the account can be evicted and the release aborted using
`IEvictRelease`.
##### _WrappedAsset_ Mint
#### _WrappedAsset_ Mint
> Seed derivation: `wrapped_<chain>_<asset>`
>
@ -214,7 +174,7 @@ If not enough votes are cast within the `RELEASE_WRAPPED_TIMEOUT_PERIOD`, the ac
This account is an instance of `spl-token/Mint` tracks a wrapped asset on the Solana chain.
##### _NativeAsset_ TokenAccount
#### _NativeAsset_ TokenAccount
> Seed derivation: `custody_<asset>`
>
@ -222,3 +182,44 @@ This account is an instance of `spl-token/Mint` tracks a wrapped asset on the So
This account is an instance of `spl-token/TokenAccount` and holds spl tokens in custody that have been transferred to a
foreign chain.
## Archive
### Reclaim mechanism
**Options:**
| Parameter | Description |
| ------------------------------ | --------------------------------------------------------------------------- |
| RELEASE_WRAPPED_TIMEOUT_PERIOD | The period in which enough votes need to be cast for an asset to be minted. |
Reclaim calls were intended to allow users to reclaim tokens if no VAA was provided in time. This would protect a user
against censorship attacks from guardians.
However this opens a window for race conditions where a VAA would be delayed and the user would frontrun that VAA with
a Reclaim.
#### Reclaim
Reclaim tokens that did not receive enough VAAs on the `proposal` within the `SIGN_PERIOD` to finish the transfer.
`claimant` will get back the `locked_token` previously locked via `ITransferOut`.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- |
| 0 | claimant | TokenAccount | | ✅ | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | TransferOutProposal | | ✅ | | ✅ |
| 3 | locked_token | WrappedAsset | | | | ✅ |
#### ReclaimNative
Reclaim tokens that did not receive enough VAAs on the `proposal` within the `SIGN_PERIOD` to finish the transfer.
`claimant` will get back the `locked_token` previously locked via `ITransferOutNative` from the `custody_account`.
| Index | Name | Type | signer | writeable | empty | derived |
| ----- | --------------- | ------------------- | ------ | --------- | ----- | ------- |
| 0 | claimant | TokenAccount | | ✅ | | |
| 1 | bridge | BridgeConfig | | | | |
| 2 | proposal | TransferOutProposal | | ✅ | | ✅ |
| 3 | locked_token | Mint | | | | |
| 4 | custody_account | Mint | | ✅ | | ✅ |