https://github.com/circlefin/solana-cctp-contracts
Official repository for Solana smart contracts used by the Cross-Chain Transfer Protocol
https://github.com/circlefin/solana-cctp-contracts
Last synced: over 1 year ago
JSON representation
Official repository for Solana smart contracts used by the Cross-Chain Transfer Protocol
- Host: GitHub
- URL: https://github.com/circlefin/solana-cctp-contracts
- Owner: circlefin
- License: apache-2.0
- Created: 2024-03-05T21:23:45.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2025-01-14T18:24:39.000Z (over 1 year ago)
- Last Synced: 2025-03-28T03:51:09.390Z (over 1 year ago)
- Language: Rust
- Homepage:
- Size: 24.2 MB
- Stars: 16
- Watchers: 9
- Forks: 21
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# Cross-Chain Transfer Protocol (CCTP) on Solana
## Contents
- [Introduction](#introduction)
- [Deployments](#deployments)
- [Contract Design](#contract-design)
- [TokenMessenger Module](#tokenmessenger-module)
- [MessageTransmitter Module](#messagetransmitter-module)
- [TokenMinter Module](#tokenminter-module)
- [Permissions](#permissions)
- [Deployment guide](#deployment-guide)
## Introduction
[Cross-Chain Transfer Protocol (CCTP)](https://circle.com/cctp) is a permissionless on-chain utility that facilitates USDC transfers securely between blockchains networks via native burning and minting. Circle created it to improve capital efficiency and minimize trust requirements when using USDC across blockchain networks. CCTP enables developers to build multi-chain applications that provide secure, 1:1 transfers of USDC across blockchains for their users.
## Developer Documentation
To learn more about how to integrate with CCTP, please see our developer documentation [here](https://developers.circle.com/stablecoins/docs/cctp-getting-started).
## Deployments
| Devnet | |
| -------------------- | -------------------------------------------- |
| MessageTransmitter | CCTPmbSD7gX1bxKPAmg77w8oFzNFpaQiQUWD43TKaecd |
| TokenMessengerMinter | CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3 |
| Mainnet | |
| -------------------- | ----- |
| MessageTransmitter | CCTPmbSD7gX1bxKPAmg77w8oFzNFpaQiQUWD43TKaecd |
| TokenMessengerMinter | CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3 |
### Program Verification
Mainnet on-chain progams can be verified with the following steps:
```sh
# Checkout deployed commit
git checkout 4e8f1d7bd4c95c3e1f4cb8ba2118897b7163c7c4
# Build a verifiable build
anchor build --verifiable
# Verify MessageTransmitter
anchor verify --program-name message_transmitter --provider.cluster mainnet --skip-build CCTPmbSD7gX1bxKPAmg77w8oFzNFpaQiQUWD43TKaecd
# Verify TokenMessengerMinter
anchor verify --program-name token_messenger_minter --provider.cluster mainnet --skip-build CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3
```
## Contract Design
Solana offers a different smart contract model to traditional EVM-based blockchains. In traditional EVM-based chains, contract code/logic and state are combined into a single contract deployed on-chain. With Solana, a smart contract is read-only or stateless and contains just program logic. This creates a logical separation of state (accounts) and contract logic (programs). This model allows for a single generic Solana program to operate across various accounts without requiring additional deployments. This is the crucial difference between Solana and EVM-based smart contracts.
CCTP protocol on EVM chains consists of three contracts:
- **MessageTransmitter**: Generic message passing. Sends all messages on the source chain, and receives all messages on the destination chain.
- **TokenMessenger**: Entrypoint for cross-chain token transfer. Routes messages to burn a token on source chain, and mint it on destination chain.
- **TokenMinter**: Responsible for minting and burning tokens. Contains chain-specific settings used by minters and burners.
On Solana, the CCTP protocol implementation is split into two programs: MessageTransmitter and TokenMessengerMinter. Where TokenMessengerMinter encapsulates the functionality of both TokenMessenger and TokenMinter contracts. To ensure alignment with EVM contracts' logic and state and to facilitate future upgrades and maintenance, the code and state of Solana programs reflect the EVM counterparts as closely as possible.
Solana CCTP programs are written in Rust and leverage the Anchor framework that makes it easier and more efficient for developers to create, deploy, and manage smart contracts on the Solana blockchain. Along with the program, an IDL (Interface Description Language) can be generated and deployed on-chain making it much easier for developers to interact with the CCTP program. See [Deployment guide](#deployment-guide) for more details.
Each CCTP program instruction emits one or more events upon execution. Depending on the purpose of instruction, events are emitted via Anchor's CPI events functionality or by creating new stand-alone accounts where such events are stored. Stand-alone account addresses are randomly generated on a client and passed to the program. The program initializes the account, writes the event, and sets itself as the owner. Replace instructions don't update previously created event accounts but create new ones. This is done to make it easier for the client to generate a replace instruction because it doesn't need to look up the original account address. At this time, only `MessageSent` events are emitted via stand-alone accounts.
Backend services can observe new account-based events by introspecting instructions and extracting event account addresses. Once the event has been processed, the account could be deleted and rent SOL reclaimed with `reclaimEventAccount` instruction. Rent SOL can only be returned to the original rent payer.
## MessageTransmitter Module
### **Instructions**
---
`initialize`
Initialize MessageTransmitter. This operation needs to be performed prior to using any other instructions. During the initialization, authorities are set to the upgrade authority.
| Parameter | Type | Description |
| ------------------ | :------: | -------------------------------------- |
| localDomain | u32 | Solana domain id |
| attester | [u8; 20] | Attester to enable |
| maxMessageBodySize | u64 | Maximum size of message body, in bytes |
| version | u32 | Message Format version |
`transferOwnership`
Change the authority of MessageTransmitter.
| Parameter | Type | Description |
| --------- | :----: | ------------- |
| newOwner | Pubkey | New authority |
`acceptOwnership`
Serves as a safety net after the authority has been changed. If an address has been inputted incorrectly, the former authority can rectify this by invoking the `transferOwnership` instruction once more.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| N/A | | |
`updatePauser`
Change the pauser of MessageTransmitter.
| Parameter | Type | Description |
| --------- | :----: | ----------- |
| newPauser | Pubkey | New pauser |
`updateAttesterManager`
Change the AttesterManager of MessageTransmitter.
| Parameter | Type | Description |
| ------------------ | :----: | ------------- |
| newAttesterManager | Pubkey | New authority |
---
`receiveMessage`
Receive a message. Messages with a given nonce can only be broadcast successfully once for a pair of domains. The message body of a valid message is passed to the specified recipient for further processing.
| Parameter | Type | Description |
| ----------- | :------: | ----------------------------- |
| message | Vec\ | Message bytes |
| attestation | Vec\ | Signed attestation of message |
`sendMessage`
Send a message to the destination domain and recipient. Emits a MessageSent event which will be attested by Circle’s attestation service.
| Parameter | Type | Description |
| ----------------- | :------: | ------------------------------------------------------- |
| destinationDomain | u32 | Destination domain identifier |
| recipient | Pubkey | Address to handle message body on destination domain |
| messageBody | Vec\ | Application-specific message to be handled by recipient |
`sendMessageWithCaller`
Send a message to the destination domain and recipient, for a specified destinationCaller on the destination domain. Emits a MessageSent event which will be attested by Circle’s attestation service.
| Parameter | Type | Description |
| ----------------- | :------: | ------------------------------------------------------- |
| destinationDomain | u32 | Destination domain identifier |
| recipient | Pubkey | Address to handle message body on destination domain |
| messageBody | Vec\ | Application-specific message to be handled by recipient |
| destinationCaller | Pubkey | Caller on the destination domain |
`replaceMessage`
Replace a message with a new message body and/or destination caller.
| Parameter | Type | Description |
| -------------------- | :------: | ------------------------------------------------------------------------------------ |
| originalMessage | Vec\ | Original message to replace |
| originalAttestation | Vec\ | Attestation of originalMessage |
| newMessageBody | Vec\ | New message body of replaced message |
| newDestinationCaller | Pubkey | The new destination caller, which may be the same as the original destination caller |
`setSignatureThreshold`
Set the threshold of signatures required to attest to a message.
| Parameter | Type | Description |
| --------------------- | :--: | ----------------------- |
| newSignatureThreshold | u32 | New signature threshold |
`enableAttester`
Enable an attester.
| Parameter | Type | Description |
| ----------- | :------: | ------------------ |
| newAttester | [u8; 20] | Attester to enable |
`disableAttester`
Disable an attester.
| Parameter | Type | Description |
| --------- | :------: | ------------------- |
| attester | [u8; 20] | Attester to disable |
`setMaxMessageBodySize`
Set the max message body size.
| Parameter | Type | Description |
| --------------------- | :--: | ----------------------- |
| newMaxMessageBodySize | u64 | New signature threshold |
`pause`
Pause MessageTransmitter.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| None | | |
`unpause`
Resume MessageTransmitter.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| None | | |
`reclaimEventAccount`
Deletes the event account and reclaims rent SOL to the original rent payer. This instruction requires a valid attestation to be executed.
| Parameter | Type | Description |
| ----------- | :------: | -------------------------- |
| attestation | Vec\ | Attestation of the message |
`getNoncePDA`
View-only helper instruction to look-up `usedNonces` account for `receiveMessage` and `isNonceUsed` instructions.
| Parameter | Type | Description |
| ------------ | :--: | ----------------- |
| nonce | u64 | Message nonce |
| sourceDomain | u32 | Domain identifier |
`isNonceUsed`
View-only helper instruction that returns true if the nonce is already used, i.e. the message is received on the destination chain.
| Parameter | Type | Description |
| --------- | :--: | ------------- |
| nonce | u64 | Message nonce |
### **State**
---
`MessageTransmitter`
Stores MessageTransmitter configuration and next available nonce.
| Field | Type | Description |
| ------------------ | :----------: | ------------------------------------------------------- |
| owner | Pubkey | Main authority of the program |
| pendingOwner | Pubkey | New authority that needs to be accepted |
| attesterManager | Pubkey | Attester Manager of the program |
| pauser | Pubkey | Pause / unpause authority |
| paused | bool | Specifies whether MessageTransmitter is paused |
| localDomain | u32 | Solana domain id |
| version | u32 | Message Format version |
| signatureThreshold | u32 | Threshold of signatures required to attest to a message |
| enabledAttesters | Vec\ | Enabled attesters (message signers) |
| maxMessageBodySize | u64 | Maximum size of message body, in bytes |
| nextAvailableNonce | u64 | Next available nonce from this source domain |
`UsedNonces`
On-chain account that stores used nonces.
| Field | Type | Description |
| ------------ | :---------: | ------------------------------------- |
| remoteDomain | u32 | Remote domain id |
| firstNonce | u64 | First nonce in the usedNonces array |
| usedNonces | [bool; 500] | Flags indicating if the nonce is used |
### **Events**
---
`OwnershipTransferStarted`
| Field | Type | Description |
| ------------- | :----: | -------------- |
| previousOwner | Pubkey | Previous owner |
| newOwner | Pubkey | New owner |
`OwnershipTransferred`
| Field | Type | Description |
| ------------- | :----: | -------------- |
| previousOwner | Pubkey | Previous owner |
| newOwner | Pubkey | New owner |
`PauserChanged`
| Field | Type | Description |
| ---------- | :----: | ----------- |
| newAddress | Pubkey | New pauser |
`AttesterManagerUpdated`
| Field | Type | Description |
| ----------------------- | :----: | ------------------------ |
| previousAttesterManager | Pubkey | Previous AttesterManager |
| newAttesterManager | Pubkey | New AttesterManager |
`MessageSent`
Emitted when a new message is dispatched.
| Field | Type | Description |
| ---------- | :------: | -------------------- |
| rent_payer | Pubkey | Account rent payer |
| message | Vec\ | Raw bytes of message |
`MessageReceived`
Emitted when a new message is received.
| Field | Type | Description |
| ------------ | :------: | ----------------------------------------------------------- |
| caller | Pubkey | Authorized caller of receiveMessage() on destination domain |
| sourceDomain | u32 | The source domain this message originated from |
| nonce | u64 | Unique message nonce |
| sender | Pubkey | The sender of this message |
| messageBody | Vec\ | Raw bytes of message |
`SignatureThresholdUpdated`
Emitted when threshold number of attestations (m in m/n multisig) is updated.
| Field | Type | Description |
| --------------------- | :--: | ----------------------- |
| oldSignatureThreshold | u32 | Old signature threshold |
| newSignatureThreshold | u32 | New signature threshold |
`AttesterEnabled`
Emitted when an attester is enabled.
| Field | Type | Description |
| -------- | :------: | ---------------------- |
| attester | [u8; 20] | Newly enabled attester |
`AttesterDisabled`
Emitted when an attester is disabled.
| Field | Type | Description |
| -------- | :------: | ----------------------- |
| attester | [u8; 20] | Newly disabled attester |
`MaxMessageBodySizeUpdated`
Emitted when max message body size is updated.
| Field | Type | Description |
| --------------------- | :--: | --------------------------------------- |
| newMaxMessageBodySize | u64 | New maximum message body size, in bytes |
`Pause`
Emitted when MessageTransmitter is paused.
| Field | Type | Description |
| ----- | :--: | ----------- |
| None | | |
`Unpause`
Emitted when MessageTransmitter is resumed.
| Field | Type | Description |
| ----- | :--: | ----------- |
| None | | |
## TokenMessenger Module
### **Instructions**
---
`initialize`
Initialize TokenMessenger. This operation needs to be performed prior to using any other instructions. During the initialization, authorities are set to the upgrade authority.
| Parameter | Type | Description |
| ------------------ | :----: | ------------------------------ |
| tokenController | Pubkey | Token controller address |
| messageTransmitter | Pubkey | Local Message Transmitter |
| messageBodyVersion | u32 | Version of message body format |
`transferOwnership`
Change the authority of TokenMessenger.
| Parameter | Type | Description |
| --------- | :----: | ------------- |
| newOwner | Pubkey | New authority |
`acceptOwnership`
Serves as a safety net after the authority has been changed. If an address has been inputted incorrectly, the former authority can rectify this by invoking the `transferOwnership` instruction once more.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| N/A | | |
`depositForBurn`
Deposit and burn tokens from sender to be minted on destination domain. Minted tokens will be transferred to mintRecipient.
| Parameter | Type | Description |
| ----------------- | :----: | ----------------------------------------------- |
| amount | u64 | Amount of tokens to deposit and burn |
| destinationDomain | u32 | Destination domain identifier |
| mintRecipient | Pubkey | Address of mint recipient on destination domain |
`depositForBurnWithCaller`
Deposit and burn tokens from sender to be minted on destination domain. Minted tokens will be transferred to mintRecipient.
| Parameter | Type | Description |
| ----------------- | :----: | ----------------------------------------------- |
| amount | u64 | Amount of tokens to deposit and burn |
| destinationDomain | u32 | Destination domain identifier |
| mintRecipient | Pubkey | Address of mint recipient on destination domain |
| destinationCaller | Pubkey | Caller on the destination domain |
`replaceDepositForBurn`
Replace a BurnMessage to change the mint recipient and/or destination caller. Allows the sender of a previous BurnMessage (created by depositForBurn) to send a new BurnMessage to replace the original. The new BurnMessage will reuse the amount and burn token of the original, without requiring a new deposit.
This is useful in cases where the user specified an incorrect address and has no way to safely mint the previously burned tokens.
| Parameter | Type | Description |
| -------------------- | :------: | ----------------------------------------------- |
| originalMessage | Vec\ | Original message to replace |
| originalAttestation | Vec\ | Attestation of originalMessage |
| newMintRecipient | Pubkey | Address of mint recipient on destination domain |
| newDestinationCaller | Pubkey | Caller on the destination domain |
`handleReceiveMessage`
Handle an incoming message received by the local MessageTransmitter, and take the appropriate action. For a burn message, mint the associated token to the requested recipient on the local domain.
| Parameter | Type | Description |
| ------------ | :------: | ------------------------------------------------- |
| remoteDomain | u32 | The domain where the message originated from |
| sender | Pubkey | The sender of the message (remote TokenMessenger) |
| messageBody | Vec\ | The message body bytes |
`addRemoteTokenMessenger`
Add the TokenMessenger for a remote domain.
| Parameter | Type | Description |
| -------------- | :----: | -------------------------------- |
| domain | u32 | Domain of remote TokenMessenger |
| tokenMessenger | Pubkey | Address of remote TokenMessenger |
`removeRemoteTokenMessenger`
Remove the TokenMessenger for a remote domain.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| N/A | | |
### **State**
---
`TokenMessenger`
Stores TokenMessenger configuration.
| Field | Type | Description |
| ----------------------- | :----: | ----------------------------------------------------------------------------------------------- |
| owner | Pubkey | Main authority of the program |
| pendingOwner | Pubkey | New authority that needs to be accepted |
| localMessageTransmitter | Pubkey | Local Message Transmitter responsible for sending and receiving messages to/from remote domains |
| messageBodyVersion | u32 | Version of message body format |
`RemoteTokenMessenger`
Stores information about TokenMessenger on remote domain.
| Field | Type | Description |
| -------------- | :----: | ------------------------------------- |
| domain | u32 | Domain of remote TokenMessenger |
| tokenMessenger | Pubkey | Valid TokenMessenger on remote domain |
### **Events**
---
`OwnershipTransferStarted`
| Field | Type | Description |
| ------------- | :----: | -------------- |
| previousOwner | Pubkey | Previous owner |
| newOwner | Pubkey | New owner |
`OwnershipTransferred`
| Field | Type | Description |
| ------------- | :----: | -------------- |
| previousOwner | Pubkey | Previous owner |
| newOwner | Pubkey | New owner |
`DepositForBurn`
Emitted when a DepositForBurn message is sent.
| Field | Type | Description |
| ------------------------- | :----: | ----------------------------------------------------------- |
| nonce | u64 | Unique nonce reserved by message |
| burnToken | Pubkey | Mint address of token burnt on Solana |
| amount | u64 | Deposit amount |
| depositor | Pubkey | Address where deposit is transferred from |
| mintRecipient | Pubkey | Address receiving minted tokens on destination domain |
| destinationDomain | u32 | Destination domain |
| destinationTokenMessenger | Pubkey | Address of TokenMessenger on destination domain |
| destinationCaller | Pubkey | Authorized caller of receiveMessage() on destination domain |
`MintAndWithdraw`
Emitted when tokens are minted.
| Field | Type | Description |
| ------------- | :----: | ---------------------------------- |
| mintRecipient | Pubkey | Recipient address of minted tokens |
| amount | u64 | Amount of minted tokens |
| mintToken | Pubkey | Mint address of minted token |
`RemoteTokenMessengerAdded`
Emitted when a remote TokenMessenger is added.
| Field | Type | Description |
| -------------- | :----: | -------------------------------- |
| domain | u32 | Domain of remote TokenMessenger |
| tokenMessenger | Pubkey | Address of remote TokenMessenger |
`RemoteTokenMessengerRemoved`
Emitted when a remote TokenMessenger is removed.
| Field | Type | Description |
| -------------- | :----: | -------------------------------- |
| domain | u32 | Domain of remote TokenMessenger |
| tokenMessenger | Pubkey | Address of remote TokenMessenger |
## TokenMinter Module
### **Instructions**
---
`setTokenController`
Change the token controller address.
| Parameter | Type | Description |
| ------------------ | :----: | -------------------- |
| newTokenController | Pubkey | New token controller |
`updatePauser`
Change the pauser address.
| Parameter | Type | Description |
| --------- | :----: | ----------- |
| newPauser | Pubkey | New pauser |
`setMaxBurnAmountPerMessage`
Set the maximum burn amount per message.
| Parameter | Type | Description |
| ------------------- | ---- | ------------------------------- |
| burnLimitPerMessage | u64 | Maximum burn amount per message |
`addLocalToken`
Add a new local token.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| N/A | | |
`removeLocalToken`
Remove local token.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| N/A | | |
`linkTokenPair`
Link supported pair of local and remote tokens.
| Parameter | Type | Description |
| ------------ | :----: | -------------------- |
| remoteDomain | u32 | Remote domain |
| remoteToken | Pubkey | Remote token address |
| localToken | Pubkey | Local token address |
`unlinkTokenPair`
Unlink a pair of local and remote tokens.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| N/A | | |
`pause`
Pause TokenMinter.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| None | | |
`unpause`
Resume TokenMinter.
| Parameter | Type | Description |
| --------- | :--: | ----------- |
| None | | |
`burnTokenCustody`
Burn tokens in the custody. If the specified amount is greater than the current balance, then the entire balance is burned, i.e., no error is returned in such case.
| Parameter | Type | Description |
| --------- | :--: | ------------------------ |
| amount | u64 | Amount of tokens to burn |
### **State**
---
`TokenMinter`
Stores TokenMinter configuration and records stats.
| Field | Type | Description |
| --------------- | :----: | ----------------------------------------------------------------------- |
| tokenController | Pubkey | Authority to manage token address mappings, and per-message burn limits |
| pauser | Pubkey | Pause / unpause authority |
| paused | bool | Specifies whether the TokenMinter is paused |
`TokenPair`
Supported mintable tokens on remote domains, mapped to their corresponding local token.
| Field | Type | Description |
| ------------ | :----: | ------------------------ |
| remoteDomain | u32 | Remote domain |
| remoteToken | Pubkey | Remote token address |
| localToken | Pubkey | Local token mint address |
`LocalToken`
Supported tokens on the local domain.
| Field | Type | Description |
| ------------------- | :----: | ---------------------------------- |
| custody | Pubkey | Custody token account |
| mint | Pubkey | Token mint address |
| burnLimitPerMessage | u64 | Maximum burn amount per message |
| messagesSent | u64 | Total number of messages sent |
| messagesReceived | u64 | Total number of messages received |
| amountSent | u64 | Amount of tokens sent (burned) |
| amountReceived | u64 | Amount of tokens received (minted) |
### **Events**
---
`SetTokenController`
| Field | Type | Description |
| --------------- | :----: | -------------------- |
| tokenController | Pubkey | New token controller |
`PauserChanged`
| Field | Type | Description |
| ---------- | :----: | ----------- |
| newAddress | Pubkey | New pauser |
`Mint`
Emitted when a mint request is processed.
| Field | Type | Description |
| ------ | :--: | ------------- |
| amount | u64 | Minted amount |
`Burn`
Emitted when a burn request is processed.
| Field | Type | Description |
| ------ | :--: | ------------- |
| amount | u64 | Burned amount |
`SetBurnLimitPerMessage`
Emitted when a burn limit per message is set.
| Field | Type | Description |
| ------------------- | :----: | -------------------------- |
| token | Pubkey | Token mint address |
| burnLimitPerMessage | u64 | New burn limit per message |
`LocalTokenAdded`
Emitted when a new local token is added.
| Field | Type | Description |
| ------- | :----: | --------------------- |
| custody | Pubkey | Custody token account |
| mint | Pubkey | Token mint address |
`LocalTokenRemoved`
Emitted when a local token is removed.
| Field | Type | Description |
| ------- | :----: | --------------------- |
| custody | Pubkey | Custody token account |
| mint | Pubkey | Token mint address |
`TokenPairLinked`
Emitted when a token pair is linked.
| Field | Type | Description |
| ------------ | :----: | ------------------------ |
| localToken | Pubkey | Local token mint address |
| remoteDomain | u32 | Remote domain |
| remoteToken | Pubkey | Remote token address |
`TokenPairUnlinked`
Emitted when a token pair is linked.
| Field | Type | Description |
| ------------ | :----: | ------------------------ |
| localToken | Pubkey | Local token mint address |
| remoteDomain | u32 | Remote domain |
| remoteToken | Pubkey | Remote token address |
`Pause`
Emitted when TokenMinter is paused.
| Field | Type | Description |
| ----- | :--: | ----------- |
| None | | |
`Unpause`
Emitted when TokenMinter is resumed.
| Field | Type | Description |
| ----- | :--: | ----------- |
| None | | |
## Permissions
The following table shows the permissions for calling each instruction:
| module | instruction | permissionless | pauser | attester manager | token controller | owner | upgrade authority | program (e.g. TokenMessenger) | MessageTransmitter |
| ------------------ | -------------------------- | :------------: | :----: | :--------------: | :--------------: | :---: | :---------------: | :---------------------------: | :----------------: |
| MessageTransmitter | initialize | | | | | | x | | |
| MessageTransmitter | transferOwnership | | | | | x | | | |
| MessageTransmitter | acceptOwnership | | | | | x | | | |
| MessageTransmitter | updatePauser | | | | | x | | | |
| MessageTransmitter | updateAttesterManager | | | | | x | | | |
| MessageTransmitter | receiveMessage | x | | | | | | | |
| MessageTransmitter | sendMessage | | | | | | | x | |
| MessageTransmitter | sendMessageWithCaller | | | | | | | x | |
| MessageTransmitter | replaceMessage | | | | | | | x | |
| MessageTransmitter | setSignatureThreshold | | | x | | | | | |
| MessageTransmitter | enableAttester | | | x | | | | | |
| MessageTransmitter | disableAttester | | | x | | | | | |
| MessageTransmitter | setMaxMessageBodySize | | | | | x | | | |
| MessageTransmitter | pause | | x | | | | | | |
| MessageTransmitter | unpause | | x | | | | | | |
| TokenMessenger | initialize | | | | | | x | | |
| TokenMessenger | transferOwnership | | | | | x | | | |
| TokenMessenger | acceptOwnership | | | | | x | | | |
| TokenMessenger | depositForBurn | x | | | | | | | |
| TokenMessenger | depositForBurnWithCaller | x | | | | | | | |
| TokenMessenger | replaceDepositForBurn | x | | | | | | | |
| TokenMessenger | handleReceiveMessage | | | | | | | | x |
| TokenMessenger | addRemoteTokenMessenger | | | | | x | | | |
| TokenMessenger | removeRemoteTokenMessenger | | | | | x | | | |
| TokenMinter | setTokenController | | | | | x | | | |
| TokenMinter | updatePauser | | | | | x | | | |
| TokenMinter | setMaxBurnAmountPerMessage | | | | x | | | | |
| TokenMinter | addLocalToken | | | | x | | | | |
| TokenMinter | removeLocalToken | | | | x | | | | |
| TokenMinter | linkTokenPair | | | | x | | | | |
| TokenMinter | unlinkTokenPair | | | | x | | | | |
| TokenMinter | pause | | x | | | | | | |
| TokenMinter | unpause | | x | | | | | | |
## Deployment guide
### Setup Environment
1. Clone the repository from .
2. Install the latest Solana tools from . If you already have Solana tools, run `solana-install update` to get the latest compatible version.
3. Install the latest Rust stable from . If you already have Rust, run `rustup update` to get the latest version.
4. Install the latest Anchor framework from . If you already have Anchor, run `avm update` to get the latest version.
Rustfmt is used to format the code. It requires `nightly` features to be activated:
5. Install `nightly` rust toolchain.
6. Execute `git config core.hooksPath .githooks` to activate pre-commit hooks.
#### [Optional] Vscode setup
1. Install `rust-analyzer` extension
2. If formatting doesn't work, make sure that `rust-analyzer.rustfmt.extraArgs` is set to `+nightly`
### Build
First, generate new keys for the program addresses with `solana-keygen new -o `. Then, replace the existing program IDs with the newly generated addresses in `Anchor.toml`, `programs/message-transmitter/src/lib.rs`, and `programs/token-messenger-minter/src/lib.rs`.
Also, ensure the path to your wallet in `Anchor.toml` is correct. Alternatively, when running Anchor deploy or test commands, you can specify your wallet with `--provider.wallet` argument. The wallet's pubkey will be set as an upgrade authority upon initial deployment of the program. It is strongly recommended to use multisig upgrade authority when deploying to the mainnet.
To build the program run `anchor build` command from the root `solana-cctp-contracts` directory:
```sh
cd solana-cctp-contracts
anchor build
```
#### Cargo Dependencies
To ensure with certainty that packages are not changed unexpectedly as well as to enable reproducible,
verifiable builds, all Cargo dependencies are vendored locally in the [vendor](/vendor/) directory and
enabled via the [.cargo/config.toml](.cargo/config.toml) file.
### Test
Unit tests are executed with the `cargo test` command:
```sh
cargo test -- --nocapture
```
Integration tests can be started as follows:
```sh
npm install
anchor test -- --features test
```
By default, integration tests are executed on a local validator, so it won't cost you any SOL.
### Deploy
To deploy the program to the devnet and upload the IDL use the following commands:
```sh
anchor deploy --provider.cluster devnet --program-name message_transmitter --program-keypair
anchor deploy --provider.cluster devnet --program-name token_messenger_minter --program-keypair
anchor idl init --provider.cluster devnet --filepath ./target/idl/message_transmitter.json
anchor idl init --provider.cluster devnet --filepath ./target/idl/token_messenger_minter.json
```
### Initialize
Before the first use of the CCTP programs they must be initialized with the [MessageTransmitter#initialize](#messagetransmitter-module) and [TokenMessenger#initialize](#tokenmessenger-module) instructions.
---
License: [LICENSE](./LICENSE)