Skip to main content

Module 0xb::message

use 0x1::ascii; use 0x1::vector; use 0x2::bcs; use 0xb::chain_ids; use 0xb::message_types;

Struct BridgeMessage

struct BridgeMessage has copy, drop, store

Fields
message_type: u8
message_version: u8
seq_num: u64
source_chain: u8
payload: vector<u8>

Struct BridgeMessageKey

struct BridgeMessageKey has copy, drop, store

Fields
source_chain: u8
message_type: u8
bridge_seq_num: u64

Struct TokenTransferPayload

struct TokenTransferPayload has drop

Fields
sender_address: vector<u8>
target_chain: u8
target_address: vector<u8>
token_type: u8
amount: u64

Struct EmergencyOp

struct EmergencyOp has drop

Fields
op_type: u8

Struct Blocklist

struct Blocklist has drop

Fields
blocklist_type: u8
validator_eth_addresses: vector<vector<u8>>

Struct UpdateBridgeLimit

struct UpdateBridgeLimit has drop

Fields
receiving_chain: u8
sending_chain: u8
limit: u64

Struct UpdateAssetPrice

struct UpdateAssetPrice has drop

Fields
token_id: u8
new_price: u64

Struct AddTokenOnIota

struct AddTokenOnIota has drop

Fields
native_token: bool
token_ids: vector<u8>
token_type_names: vector<ascii::String>
token_prices: vector<u64>

Struct ParsedTokenTransferMessage

struct ParsedTokenTransferMessage has drop

Fields
message_version: u8
seq_num: u64
source_chain: u8
payload: vector<u8>
parsed_payload: message::TokenTransferPayload

Constants

const CURRENT_MESSAGE_VERSION: u8 = 1;

const ECDSA_ADDRESS_LENGTH: u64 = 20;

const EEmptyList: u64 = 2;

const EInvalidAddressLength: u64 = 1;

const EInvalidEmergencyOpType: u64 = 4;

const EInvalidMessageType: u64 = 3;

const EInvalidPayloadLength: u64 = 5;

const EMustBeTokenMessage: u64 = 6;

const ETrailingBytes: u64 = 0;

const PAUSE: u8 = 0;

const UNPAUSE: u8 = 1;

Function extract_token_bridge_payload

public fun extract_token_bridge_payload(message: &message::BridgeMessage): message::TokenTransferPayload

Implementation

public fun extract_token_bridge_payload(message: &BridgeMessage): TokenTransferPayload { let mut bcs = bcs::new(message.payload); let sender_address = bcs.peel_vec_u8(); let target_chain = bcs.peel_u8(); let target_address = bcs.peel_vec_u8(); let token_type = bcs.peel_u8(); let amount = peel_u64_be(&mut bcs);

chain_ids::assert_valid_chain_id(target_chain); assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes);

TokenTransferPayload { sender_address, target_chain, target_address, token_type, amount } }

Function extract_emergency_op_payload

Emergency op payload is just a single byte

public fun extract_emergency_op_payload(message: &message::BridgeMessage): message::EmergencyOp

Implementation

public fun extract_emergency_op_payload(message: &BridgeMessage): EmergencyOp { assert!(message.payload.length() == 1, ETrailingBytes); EmergencyOp { op_type: message.payload[0] } }

Function extract_blocklist_payload

public fun extract_blocklist_payload(message: &message::BridgeMessage): message::Blocklist

Implementation

public fun extract_blocklist_payload(message: &BridgeMessage): Blocklist { // blocklist payload should consist of one byte blocklist type, and list of 20 bytes evm addresses // derived from ECDSA public keys let mut bcs = bcs::new(message.payload); let blocklist_type = bcs.peel_u8(); let mut address_count = bcs.peel_u8();

assert!(address_count != 0, EEmptyList);

let mut validator_eth_addresses = vector[]; while (address_count > 0) { let (mut address, mut i) = (vector[], 0); while (i < ECDSA_ADDRESS_LENGTH) { address.push_back(bcs.peel_u8()); i = i + 1; }; validator_eth_addresses.push_back(address); address_count = address_count - 1; };

assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes);

Blocklist { blocklist_type, validator_eth_addresses } }

Function extract_update_bridge_limit

public fun extract_update_bridge_limit(message: &message::BridgeMessage): message::UpdateBridgeLimit

Implementation

public fun extract_update_bridge_limit(message: &BridgeMessage): UpdateBridgeLimit { let mut bcs = bcs::new(message.payload); let sending_chain = bcs.peel_u8(); let limit = peel_u64_be(&mut bcs);

chain_ids::assert_valid_chain_id(sending_chain); assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes);

UpdateBridgeLimit { receiving_chain: message.source_chain, sending_chain, limit } }

Function extract_update_asset_price

public fun extract_update_asset_price(message: &message::BridgeMessage): message::UpdateAssetPrice

Implementation

public fun extract_update_asset_price(message: &BridgeMessage): UpdateAssetPrice { let mut bcs = bcs::new(message.payload); let token_id = bcs.peel_u8(); let new_price = peel_u64_be(&mut bcs);

assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes);

UpdateAssetPrice { token_id, new_price } }

Function extract_add_tokens_on_iota

public fun extract_add_tokens_on_iota(message: &message::BridgeMessage): message::AddTokenOnIota

Implementation

public fun extract_add_tokens_on_iota(message: &BridgeMessage): AddTokenOnIota { let mut bcs = bcs::new(message.payload); let native_token = bcs.peel_bool(); let token_ids = bcs.peel_vec_u8(); let token_type_names_bytes = bcs.peel_vec_vec_u8(); let token_prices = bcs.peel_vec_u64();

let mut n = 0; let mut token_type_names = vector[]; while (n < token_type_names_bytes.length()){ token_type_names.push_back(ascii::string(*token_type_names_bytes.borrow(n))); n = n + 1; }; assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes); AddTokenOnIota { native_token, token_ids, token_type_names, token_prices } }

Function serialize_message

public fun serialize_message(message: message::BridgeMessage): vector<u8>

Implementation

public fun serialize_message(message: BridgeMessage): vector<u8> { let BridgeMessage { message_type, message_version, seq_num, source_chain, payload } = message;

let mut message = vector[ message_type, message_version, ];

// bcs serializes u64 as 8 bytes message.append(reverse_bytes(bcs::to_bytes(&seq_num))); message.push_back(source_chain); message.append(payload); message }

Function create_token_bridge_message

Token Transfer Message Format: [message_type: u8] [version:u8] [nonce:u64] [source_chain: u8] [sender_address_length:u8] [sender_address: byte[]] [target_chain:u8] [target_address_length:u8] [target_address: byte[]] [token_type:u8] [amount:u64]

public fun create_token_bridge_message(source_chain: u8, seq_num: u64, sender_address: vector<u8>, target_chain: u8, target_address: vector<u8>, token_type: u8, amount: u64): message::BridgeMessage

Implementation

public fun create_token_bridge_message( source_chain: u8, seq_num: u64, sender_address: vector<u8>, target_chain: u8, target_address: vector<u8>, token_type: u8, amount: u64 ): BridgeMessage { chain_ids::assert_valid_chain_id(source_chain); chain_ids::assert_valid_chain_id(target_chain);

let mut payload = vector[];

// sender address should be less than 255 bytes so can fit into u8 payload.push_back((vector::length(&sender_address) as u8)); payload.append(sender_address); payload.push_back(target_chain); // target address should be less than 255 bytes so can fit into u8 payload.push_back((vector::length(&target_address) as u8)); payload.append(target_address); payload.push_back(token_type); // bcs serialzies u64 as 8 bytes payload.append(reverse_bytes(bcs::to_bytes(&amount)));

assert!(vector::length(&payload) == 64, EInvalidPayloadLength);

BridgeMessage { message_type: message_types::token(), message_version: CURRENT_MESSAGE_VERSION, seq_num, source_chain, payload, } }

Function create_emergency_op_message

Emergency Op Message Format: [message_type: u8] [version:u8] [nonce:u64] [chain_id: u8] [op_type: u8]

public fun create_emergency_op_message(source_chain: u8, seq_num: u64, op_type: u8): message::BridgeMessage

Implementation

public fun create_emergency_op_message( source_chain: u8, seq_num: u64, op_type: u8, ): BridgeMessage { chain_ids::assert_valid_chain_id(source_chain);

BridgeMessage { message_type: message_types::emergency_op(), message_version: CURRENT_MESSAGE_VERSION, seq_num, source_chain, payload: vector[op_type], } }

Function create_blocklist_message

Blocklist Message Format: [message_type: u8] [version:u8] [nonce:u64] [chain_id: u8] [blocklist_type: u8] [validator_length: u8] [validator_ecdsa_addresses: byte[][]]

public fun create_blocklist_message(source_chain: u8, seq_num: u64, blocklist_type: u8, validator_ecdsa_addresses: vector<vector<u8>>): message::BridgeMessage

Implementation

public fun create_blocklist_message( source_chain: u8, seq_num: u64, // 0: block, 1: unblock blocklist_type: u8, validator_ecdsa_addresses: vector<vector<u8>>, ): BridgeMessage { chain_ids::assert_valid_chain_id(source_chain);

let address_length = validator_ecdsa_addresses.length(); let mut payload = vector[blocklist_type, (address_length as u8)]; let mut i = 0;

while (i < address_length) { let address = validator_ecdsa_addresses[i]; assert!(address.length() == ECDSA_ADDRESS_LENGTH, EInvalidAddressLength); payload.append(address);

i = i + 1; };

BridgeMessage { message_type: message_types::committee_blocklist(), message_version: CURRENT_MESSAGE_VERSION, seq_num, source_chain, payload, } }

Function create_update_bridge_limit_message

Update bridge limit Message Format: [message_type: u8] [version:u8] [nonce:u64] [receiving_chain_id: u8] [sending_chain_id: u8] [new_limit: u64]

public fun create_update_bridge_limit_message(receiving_chain: u8, seq_num: u64, sending_chain: u8, new_limit: u64): message::BridgeMessage

Implementation

public fun create_update_bridge_limit_message( receiving_chain: u8, seq_num: u64, sending_chain: u8, new_limit: u64, ): BridgeMessage { chain_ids::assert_valid_chain_id(receiving_chain); chain_ids::assert_valid_chain_id(sending_chain);

let mut payload = vector[sending_chain]; payload.append(reverse_bytes(bcs::to_bytes(&new_limit)));

BridgeMessage { message_type: message_types::update_bridge_limit(), message_version: CURRENT_MESSAGE_VERSION, seq_num, source_chain: receiving_chain, payload, } }

Function create_update_asset_price_message

Update asset price message [message_type: u8] [version:u8] [nonce:u64] [chain_id: u8] [token_id: u8] [new_price:u64]

public fun create_update_asset_price_message(token_id: u8, source_chain: u8, seq_num: u64, new_price: u64): message::BridgeMessage

Implementation

public fun create_update_asset_price_message( token_id: u8, source_chain: u8, seq_num: u64, new_price: u64, ): BridgeMessage { chain_ids::assert_valid_chain_id(source_chain);

let mut payload = vector[token_id]; payload.append(reverse_bytes(bcs::to_bytes(&new_price))); BridgeMessage { message_type: message_types::update_asset_price(), message_version: CURRENT_MESSAGE_VERSION, seq_num, source_chain, payload, } }

Function create_add_tokens_on_iota_message

Update Iota token message [message_type:u8] [version:u8] [nonce:u64] [chain_id: u8] [native_token:bool] [token_ids:vector<u8>] [token_type_name:vector<String>] [token_prices:vector<u64>]

public fun create_add_tokens_on_iota_message(source_chain: u8, seq_num: u64, native_token: bool, token_ids: vector<u8>, type_names: vector<ascii::String>, token_prices: vector<u64>): message::BridgeMessage

Implementation

public fun create_add_tokens_on_iota_message( source_chain: u8, seq_num: u64, native_token: bool, token_ids: vector<u8>, type_names: vector<String>, token_prices: vector<u64>, ): BridgeMessage { chain_ids::assert_valid_chain_id(source_chain); let mut payload = bcs::to_bytes(&native_token); payload.append(bcs::to_bytes(&token_ids)); payload.append(bcs::to_bytes(&type_names)); payload.append(bcs::to_bytes(&token_prices)); BridgeMessage { message_type: message_types::add_tokens_on_iota(), message_version: CURRENT_MESSAGE_VERSION, seq_num, source_chain, payload, } }

Function create_key

public fun create_key(source_chain: u8, message_type: u8, bridge_seq_num: u64): message::BridgeMessageKey

Implementation

public fun create_key(source_chain: u8, message_type: u8, bridge_seq_num: u64): BridgeMessageKey { BridgeMessageKey { source_chain, message_type, bridge_seq_num } }

Function key

public fun key(self: &message::BridgeMessage): message::BridgeMessageKey

Implementation

public fun key(self: &BridgeMessage): BridgeMessageKey { create_key(self.source_chain, self.message_type, self.seq_num) }

Function message_version

public fun message_version(self: &message::BridgeMessage): u8

Implementation

public fun message_version(self: &BridgeMessage): u8 { self.message_version }

Function message_type

public fun message_type(self: &message::BridgeMessage): u8

Implementation

public fun message_type(self: &BridgeMessage): u8 { self.message_type }

Function seq_num

public fun seq_num(self: &message::BridgeMessage): u64

Implementation

public fun seq_num(self: &BridgeMessage): u64 { self.seq_num }

Function source_chain

public fun source_chain(self: &message::BridgeMessage): u8

Implementation

public fun source_chain(self: &BridgeMessage): u8 { self.source_chain }

Function payload

public fun payload(self: &message::BridgeMessage): vector<u8>

Implementation

public fun payload(self: &BridgeMessage): vector<u8> { self.payload }

Function token_target_chain

public fun token_target_chain(self: &message::TokenTransferPayload): u8

Implementation

public fun token_target_chain(self: &TokenTransferPayload): u8 { self.target_chain }

Function token_target_address

public fun token_target_address(self: &message::TokenTransferPayload): vector<u8>

Implementation

public fun token_target_address(self: &TokenTransferPayload): vector<u8> { self.target_address }

Function token_type

public fun token_type(self: &message::TokenTransferPayload): u8

Implementation

public fun token_type(self: &TokenTransferPayload): u8 { self.token_type }

Function token_amount

public fun token_amount(self: &message::TokenTransferPayload): u64

Implementation

public fun token_amount(self: &TokenTransferPayload): u64 { self.amount }

Function emergency_op_type

public fun emergency_op_type(self: &message::EmergencyOp): u8

Implementation

public fun emergency_op_type(self: &EmergencyOp): u8 { self.op_type }

Function blocklist_type

public fun blocklist_type(self: &message::Blocklist): u8

Implementation

public fun blocklist_type(self: &Blocklist): u8 { self.blocklist_type }

Function blocklist_validator_addresses

public fun blocklist_validator_addresses(self: &message::Blocklist): &vector<vector<u8>>

Implementation

public fun blocklist_validator_addresses(self: &Blocklist): &vector<vector<u8>> { &self.validator_eth_addresses }

Function update_bridge_limit_payload_sending_chain

public fun update_bridge_limit_payload_sending_chain(self: &message::UpdateBridgeLimit): u8

Implementation

public fun update_bridge_limit_payload_sending_chain(self: &UpdateBridgeLimit): u8 { self.sending_chain }

Function update_bridge_limit_payload_receiving_chain

public fun update_bridge_limit_payload_receiving_chain(self: &message::UpdateBridgeLimit): u8

Implementation

public fun update_bridge_limit_payload_receiving_chain(self: &UpdateBridgeLimit): u8 { self.receiving_chain }

Function update_bridge_limit_payload_limit

public fun update_bridge_limit_payload_limit(self: &message::UpdateBridgeLimit): u64

Implementation

public fun update_bridge_limit_payload_limit(self: &UpdateBridgeLimit): u64 { self.limit }

Function update_asset_price_payload_token_id

public fun update_asset_price_payload_token_id(self: &message::UpdateAssetPrice): u8

Implementation

public fun update_asset_price_payload_token_id(self: &UpdateAssetPrice): u8 { self.token_id }

Function update_asset_price_payload_new_price

public fun update_asset_price_payload_new_price(self: &message::UpdateAssetPrice): u64

Implementation

public fun update_asset_price_payload_new_price(self: &UpdateAssetPrice): u64 { self.new_price }

Function is_native

public fun is_native(self: &message::AddTokenOnIota): bool

Implementation

public fun is_native(self: &AddTokenOnIota): bool { self.native_token }

Function token_ids

public fun token_ids(self: &message::AddTokenOnIota): vector<u8>

Implementation

public fun token_ids(self: &AddTokenOnIota): vector<u8> { self.token_ids }

Function token_type_names

public fun token_type_names(self: &message::AddTokenOnIota): vector<ascii::String>

Implementation

public fun token_type_names(self: &AddTokenOnIota): vector<String> { self.token_type_names }

Function token_prices

public fun token_prices(self: &message::AddTokenOnIota): vector<u64>

Implementation

public fun token_prices(self: &AddTokenOnIota): vector<u64> { self.token_prices }

Function emergency_op_pause

public fun emergency_op_pause(): u8

Implementation

public fun emergency_op_pause(): u8 { PAUSE }

Function emergency_op_unpause

public fun emergency_op_unpause(): u8

Implementation

public fun emergency_op_unpause(): u8 { UNPAUSE }

Function required_voting_power

Return the required signature threshold for the message, values are voting power in the scale of 10000

public fun required_voting_power(self: &message::BridgeMessage): u64

Implementation

public fun required_voting_power(self: &BridgeMessage): u64 { let message_type = message_type(self);

if (message_type == message_types::token()) { 3334 } else if (message_type == message_types::emergency_op()) { let payload = extract_emergency_op_payload(self); if (payload.op_type == PAUSE) { 450 } else if (payload.op_type == UNPAUSE) { 5001 } else { abort EInvalidEmergencyOpType } } else if (message_type == message_types::committee_blocklist()) { 5001 } else if (message_type == message_types::update_asset_price()) { 5001 } else if (message_type == message_types::update_bridge_limit()) { 5001 } else if (message_type == message_types::add_tokens_on_iota()) { 5001 } else { abort EInvalidMessageType } }

Function to_parsed_token_transfer_message

public fun to_parsed_token_transfer_message(message: &message::BridgeMessage): message::ParsedTokenTransferMessage

Implementation

Function reverse_bytes

fun reverse_bytes(bytes: vector<u8>): vector<u8>

Implementation

fun reverse_bytes(mut bytes: vector<u8>): vector<u8> { vector::reverse(&mut bytes); bytes }

Function peel_u64_be

fun peel_u64_be(bcs: &mut bcs::BCS): u64

Implementation

fun peel_u64_be(bcs: &mut BCS): u64 { let (mut value, mut i) = (0u64, 64u8); while (i > 0) { i = i - 8; let byte = (bcs::peel_u8(bcs) as u64); value = value + (byte << i); }; value }