wormhole/solana/modules/token_bridge/program/src/messages.rs

199 lines
5.7 KiB
Rust

use crate::{
types::{Address, ChainID},
TokenBridgeError,
};
use borsh::{BorshDeserialize, BorshSerialize};
use bridge::vaa::{DeserializePayload, SerializePayload};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use primitive_types::U256;
use solana_program::{native_token::Sol, program_error::ProgramError};
use solitaire::SolitaireError;
use std::{
error::Error,
io::{Cursor, Read, Write},
str::Utf8Error,
string::FromUtf8Error,
};
pub struct PayloadTransfer {
// Amount being transferred (big-endian uint256)
pub amount: U256,
// Address of the token. Left-zero-padded if shorter than 32 bytes
pub token_address: Address,
// Chain ID of the token
pub token_chain: ChainID,
// Address of the recipient. Left-zero-padded if shorter than 32 bytes
pub to: Address,
// Chain ID of the recipient
pub to_chain: ChainID,
// Amount of tokens (big-endian uint256) that the user is willing to pay as relayer fee. Must be <= Amount.
pub fee: U256,
}
impl DeserializePayload for PayloadTransfer {
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
let mut v = Cursor::new(buf);
if v.read_u8()? != 1 {
return Err(SolitaireError::Custom(0));
};
let mut am_data: [u8; 32] = [0; 32];
v.read_exact(&mut am_data)?;
let amount = U256::from_big_endian(&am_data);
let mut token_address = Address::default();
v.read_exact(&mut token_address)?;
let token_chain = v.read_u16::<BigEndian>()?;
let mut to = Address::default();
v.read_exact(&mut to)?;
let to_chain = v.read_u16::<BigEndian>()?;
let mut fee_data: [u8; 32] = [0; 32];
v.read_exact(&mut fee_data)?;
let fee = U256::from_big_endian(&fee_data);
Ok(PayloadTransfer {
amount,
token_address,
token_chain,
to,
to_chain,
fee,
})
}
}
impl SerializePayload for PayloadTransfer {
fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), SolitaireError> {
// Payload ID
writer.write_u8(1)?;
let mut am_data: [u8; 32] = [0; 32];
self.amount.to_big_endian(&mut am_data);
writer.write(&am_data)?;
writer.write(&self.token_address)?;
writer.write_u16::<BigEndian>(self.token_chain)?;
writer.write(&self.to)?;
writer.write_u16::<BigEndian>(self.to_chain)?;
let mut fee_data: [u8; 32] = [0; 32];
self.fee.to_big_endian(&mut fee_data);
writer.write(&fee_data)?;
Ok(())
}
}
pub struct PayloadAssetMeta {
// Address of the token. Left-zero-padded if shorter than 32 bytes
pub token_address: Address,
// Chain ID of the token
pub token_chain: ChainID,
// Number of decimals of the token (big-endian uint256)
pub decimals: U256,
// Symbol of the token
pub symbol: String,
// Name of the token
pub name: String,
}
impl DeserializePayload for PayloadAssetMeta {
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
let mut v = Cursor::new(buf);
if v.read_u8()? != 2 {
return Err(SolitaireError::Custom(0));
};
let mut token_address = Address::default();
v.read_exact(&mut token_address)?;
let token_chain = v.read_u16::<BigEndian>()?;
let mut decimals_data: [u8; 32] = [0; 32];
v.read_exact(&mut decimals_data)?;
let decimals = U256::from_big_endian(&decimals_data);
let mut symbol_data: [u8; 32] = [0; 32];
v.read_exact(&mut symbol_data)?;
let symbol = String::from_utf8(symbol_data.to_vec())
.map_err::<SolitaireError, _>(|_| TokenBridgeError::InvalidUTF8String.into())?;
let mut name_data: [u8; 32] = [0; 32];
v.read_exact(&mut name_data)?;
let name = String::from_utf8(name_data.to_vec())
.map_err::<SolitaireError, _>(|_| TokenBridgeError::InvalidUTF8String.into())?;
Ok(PayloadAssetMeta {
token_address,
token_chain,
decimals,
symbol,
name,
})
}
}
impl SerializePayload for PayloadAssetMeta {
fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), SolitaireError> {
// Payload ID
writer.write_u8(2)?;
writer.write(&self.token_address)?;
writer.write_u16::<BigEndian>(self.token_chain)?;
let mut decimal_data: [u8; 32] = [0; 32];
self.decimals.to_big_endian(&mut decimal_data);
writer.write(&decimal_data)?;
let mut symbol: [u8; 32] = [0; 32];
for i in 0..self.symbol.len() {
symbol[(32 - self.symbol.len()) + i] = self.symbol.as_bytes()[i];
}
writer.write(&symbol);
let mut name: [u8; 32] = [0; 32];
for i in 0..self.name.len() {
name[(32 - self.name.len()) + i] = self.name.as_bytes()[i];
}
writer.write(&name);
Ok(())
}
}
pub struct PayloadGovernanceRegisterChain {
// Chain ID of the chain to be registered
pub chain: ChainID,
// Address of the endpoint on the chain
pub endpoint_address: Address,
}
impl DeserializePayload for PayloadGovernanceRegisterChain {
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
let mut v = Cursor::new(buf);
if v.read_u8()? != 2 {
return Err(SolitaireError::Custom(0));
};
Ok(PayloadGovernanceRegisterChain {
chain: 0,
endpoint_address: [0u8; 32],
})
}
}
impl SerializePayload for PayloadGovernanceRegisterChain {
fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), SolitaireError> {
// Payload ID
writer.write_u8(2)?;
Ok(())
}
}