fix terra vaa parsing

Change-Id: I27306e004897f971d62c82e6046c1f6ec0016247
This commit is contained in:
Hendrik Hofstadt 2021-07-14 19:53:19 +02:00
parent bb446fb338
commit d12863f957
4 changed files with 122 additions and 86 deletions

View File

@ -83,6 +83,7 @@ pub fn handle<S: Storage, A: Api, Q: Querier>(
amount, amount,
recipient_chain, recipient_chain,
recipient, recipient,
fee,
nonce, nonce,
} => handle_initiate_transfer( } => handle_initiate_transfer(
deps, deps,
@ -91,6 +92,7 @@ pub fn handle<S: Storage, A: Api, Q: Querier>(
amount, amount,
recipient_chain, recipient_chain,
recipient.as_slice().to_vec(), recipient.as_slice().to_vec(),
fee,
nonce, nonce,
), ),
HandleMsg::SubmitVaa { data } => submit_vaa(deps, env, &data), HandleMsg::SubmitVaa { data } => submit_vaa(deps, env, &data),
@ -337,10 +339,13 @@ fn handle_complete_transfer<S: Storage, A: Api, Q: Querier>(
let token_chain = transfer_info.token_chain; let token_chain = transfer_info.token_chain;
let target_address = (&transfer_info.recipient.as_slice()).get_address(0); let target_address = (&transfer_info.recipient.as_slice()).get_address(0);
let (not_supported_amount, amount) = transfer_info.amount; let (not_supported_amount, mut amount) = transfer_info.amount;
let (not_supported_fee, fee) = transfer_info.fee;
amount -= fee;
// Check high 128 bit of amount value to be empty // Check high 128 bit of amount value to be empty
if not_supported_amount != 0 { if not_supported_amount != 0 || not_supported_fee != 0 {
return ContractError::AmountTooHigh.std_err(); return ContractError::AmountTooHigh.std_err();
} }
@ -359,15 +364,27 @@ fn handle_complete_transfer<S: Storage, A: Api, Q: Querier>(
.human_address(&target_address) .human_address(&target_address)
.or_else(|_| ContractError::WrongTargetAddressFormat.std_err())?; .or_else(|_| ContractError::WrongTargetAddressFormat.std_err())?;
Ok(HandleResponse { let mut messages = vec![CosmosMsg::Wasm(WasmMsg::Execute {
messages: vec![CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: contract_addr.clone(), contract_addr: contract_addr.clone(),
msg: to_binary(&WrappedMsg::Mint { msg: to_binary(&WrappedMsg::Mint {
recipient: recipient.clone(), recipient: recipient.clone(),
amount: Uint128::from(amount), amount: Uint128::from(amount),
})?, })?,
send: vec![], send: vec![],
})], })];
if fee != 0 {
messages.push(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: contract_addr.clone(),
msg: to_binary(&WrappedMsg::Mint {
recipient: env.message.sender.clone(),
amount: Uint128::from(fee),
})?,
send: vec![],
}))
}
Ok(HandleResponse {
messages,
log: vec![ log: vec![
log("action", "complete_transfer_wrapped"), log("action", "complete_transfer_wrapped"),
log("contract", contract_addr), log("contract", contract_addr),
@ -384,15 +401,29 @@ fn handle_complete_transfer<S: Storage, A: Api, Q: Querier>(
let recipient = deps.api.human_address(&target_address)?; let recipient = deps.api.human_address(&target_address)?;
let contract_addr = deps.api.human_address(&token_address)?; let contract_addr = deps.api.human_address(&token_address)?;
Ok(HandleResponse {
messages: vec![CosmosMsg::Wasm(WasmMsg::Execute { let mut messages = vec![CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: contract_addr.clone(), contract_addr: contract_addr.clone(),
msg: to_binary(&TokenMsg::Transfer { msg: to_binary(&TokenMsg::Transfer {
recipient: recipient.clone(), recipient: recipient.clone(),
amount: Uint128::from(amount), amount: Uint128::from(amount),
})?, })?,
send: vec![], send: vec![],
})], })];
if fee != 0 {
messages.push(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: contract_addr.clone(),
msg: to_binary(&TokenMsg::Transfer {
recipient: env.message.sender.clone(),
amount: Uint128::from(fee),
})?,
send: vec![],
}))
}
Ok(HandleResponse {
messages,
log: vec![ log: vec![
log("action", "complete_transfer_native"), log("action", "complete_transfer_native"),
log("recipient", recipient), log("recipient", recipient),
@ -411,6 +442,7 @@ fn handle_initiate_transfer<S: Storage, A: Api, Q: Querier>(
amount: Uint128, amount: Uint128,
recipient_chain: u16, recipient_chain: u16,
recipient: Vec<u8>, recipient: Vec<u8>,
fee: Uint128,
nonce: u32, nonce: u32,
) -> StdResult<HandleResponse> { ) -> StdResult<HandleResponse> {
// if recipient_chain == CHAIN_ID { // if recipient_chain == CHAIN_ID {
@ -421,6 +453,10 @@ fn handle_initiate_transfer<S: Storage, A: Api, Q: Querier>(
return ContractError::AmountTooLow.std_err(); return ContractError::AmountTooLow.std_err();
} }
if fee > amount {
return Err(StdError::generic_err("fee greater than sent amount"))
}
let asset_chain: u16; let asset_chain: u16;
let asset_address: Vec<u8>; let asset_address: Vec<u8>;
@ -471,6 +507,7 @@ fn handle_initiate_transfer<S: Storage, A: Api, Q: Querier>(
amount: (0, amount.u128()), amount: (0, amount.u128()),
recipient_chain, recipient_chain,
recipient: recipient.clone(), recipient: recipient.clone(),
fee: (0, fee.u128()),
}; };
let token_bridge_message = TokenBridgeMessage { let token_bridge_message = TokenBridgeMessage {

View File

@ -24,6 +24,7 @@ pub enum HandleMsg {
amount: Uint128, amount: Uint128,
recipient_chain: u16, recipient_chain: u16,
recipient: Binary, recipient: Binary,
fee: Uint128,
nonce: u32, nonce: u32,
}, },

View File

@ -89,65 +89,65 @@ impl TokenBridgeMessage {
} }
} }
// 0 u16 token_chain // 0 u256 amount
// 2 [u8; 32] token_address // 32 [u8; 32] token_address
// 34 u256 amount // 64 u16 token_chain
// 66 u16 recipient_chain // 66 [u8; 32] recipient
// 68 [u8; 32] recipient // 98 u16 recipient_chain
// 100 u256 fee
pub struct TransferInfo { pub struct TransferInfo {
pub token_chain: u16,
pub token_address: Vec<u8>,
pub amount: (u128, u128), pub amount: (u128, u128),
pub token_address: Vec<u8>,
pub token_chain: u16,
pub recipient_chain: u16, pub recipient_chain: u16,
pub recipient: Vec<u8>, pub recipient: Vec<u8>,
pub fee: (u128, u128),
} }
impl TransferInfo { impl TransferInfo {
pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> { pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> {
let data = data.as_slice(); let data = data.as_slice();
let token_chain = data.get_u16(0); let amount = data.get_u256(0);
let token_address = data.get_bytes32(2).to_vec(); let token_address = data.get_bytes32(32).to_vec();
let amount = data.get_u256(34); let token_chain = data.get_u16(64);
let recipient_chain = data.get_u16(66); let recipient = data.get_bytes32(66).to_vec();
let recipient = data.get_bytes32(68).to_vec(); let recipient_chain = data.get_u16(98);
let fee = data.get_u256(100);
Ok(TransferInfo { Ok(TransferInfo {
token_chain,
token_address,
amount, amount,
recipient_chain, token_address,
token_chain,
recipient, recipient,
recipient_chain,
fee,
}) })
} }
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
[ [
self.token_chain.to_be_bytes().to_vec(),
self.token_address.clone(),
self.amount.0.to_be_bytes().to_vec(), self.amount.0.to_be_bytes().to_vec(),
self.amount.1.to_be_bytes().to_vec(), self.amount.1.to_be_bytes().to_vec(),
self.recipient_chain.to_be_bytes().to_vec(), self.token_address.clone(),
self.token_chain.to_be_bytes().to_vec(),
self.recipient.to_vec(), self.recipient.to_vec(),
self.recipient_chain.to_be_bytes().to_vec(),
self.fee.0.to_be_bytes().to_vec(),
self.fee.1.to_be_bytes().to_vec(),
] ]
.concat() .concat()
} }
} }
//PayloadID uint8 = 2 // 0 [32]uint8 TokenAddress
// // Address of the token. Left-zero-padded if shorter than 32 bytes // 32 uint16 TokenChain
// TokenAddress [32]uint8 // 34 uint8 Decimals
// // Chain ID of the token // 35 [32]uint8 Symbol
// TokenChain uint16 // 67 [32]uint8 Name
// // Number of decimals of the token
// Decimals uint8
// // Symbol of the token (UTF-8)
// Symbol [32]uint8
// // Name of the token (UTF-8)
// Name [32]uint8
pub struct AssetMeta { pub struct AssetMeta {
pub token_chain: u16,
pub token_address: Vec<u8>, pub token_address: Vec<u8>,
pub token_chain: u16,
pub decimals: u8, pub decimals: u8,
pub symbol: Vec<u8>, pub symbol: Vec<u8>,
pub name: Vec<u8>, pub name: Vec<u8>,
@ -156,8 +156,8 @@ pub struct AssetMeta {
impl AssetMeta { impl AssetMeta {
pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> { pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> {
let data = data.as_slice(); let data = data.as_slice();
let token_chain = data.get_u16(0); let token_address = data.get_bytes32(0).to_vec();
let token_address = data.get_bytes32(2).to_vec(); let token_chain = data.get_u16(32);
let decimals = data.get_u8(34); let decimals = data.get_u8(34);
let symbol = data.get_bytes32(35).to_vec(); let symbol = data.get_bytes32(35).to_vec();
let name = data.get_bytes32(67).to_vec(); let name = data.get_bytes32(67).to_vec();
@ -173,8 +173,8 @@ impl AssetMeta {
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
[ [
self.token_chain.to_be_bytes().to_vec(),
self.token_address.clone(), self.token_address.clone(),
self.token_chain.to_be_bytes().to_vec(),
self.decimals.to_be_bytes().to_vec(), self.decimals.to_be_bytes().to_vec(),
self.symbol.clone(), self.symbol.clone(),
self.name.clone(), self.name.clone(),

View File

@ -42,7 +42,7 @@ pub struct ConfigInfo {
pub struct ParsedVAA { pub struct ParsedVAA {
pub version: u8, pub version: u8,
pub guardian_set_index: u32, pub guardian_set_index: u32,
pub timestamp: u64, pub timestamp: u32,
pub nonce: u32, pub nonce: u32,
pub len_signers: u8, pub len_signers: u8,
@ -68,13 +68,13 @@ impl ParsedVAA {
1 [65]uint8 signature 1 [65]uint8 signature
body: body:
0 uint64 timestamp (unix in seconds) 0 uint32 timestamp (unix in seconds)
8 uint32 nonce 4 uint32 nonce
12 uint16 emitter_chain 8 uint16 emitter_chain
14 [32]uint8 emitter_address 10 [32]uint8 emitter_address
46 uint64 sequence 42 uint64 sequence
46 uint8 consistency_level 50 uint8 consistency_level
54 []uint8 payload 51 []uint8 payload
*/ */
pub const HEADER_LEN: usize = 6; pub const HEADER_LEN: usize = 6;
@ -83,12 +83,12 @@ impl ParsedVAA {
pub const GUARDIAN_SET_INDEX_POS: usize = 1; pub const GUARDIAN_SET_INDEX_POS: usize = 1;
pub const LEN_SIGNER_POS: usize = 5; pub const LEN_SIGNER_POS: usize = 5;
pub const VAA_NONCE_POS: usize = 8; pub const VAA_NONCE_POS: usize = 4;
pub const VAA_EMITTER_CHAIN_POS: usize = 12; pub const VAA_EMITTER_CHAIN_POS: usize = 8;
pub const VAA_EMITTER_ADDRESS_POS: usize = 14; pub const VAA_EMITTER_ADDRESS_POS: usize = 10;
pub const VAA_SEQUENCE_POS: usize = 46; pub const VAA_SEQUENCE_POS: usize = 42;
pub const VAA_CONSISTENCY_LEVEL_POS: usize = 54; pub const VAA_CONSISTENCY_LEVEL_POS: usize = 50;
pub const VAA_PAYLOAD_POS: usize = 55; pub const VAA_PAYLOAD_POS: usize = 51;
// Signature data offsets in the signature block // Signature data offsets in the signature block
pub const SIG_DATA_POS: usize = 1; pub const SIG_DATA_POS: usize = 1;
@ -124,7 +124,7 @@ impl ParsedVAA {
return ContractError::InvalidVAA.std_err(); return ContractError::InvalidVAA.std_err();
} }
let timestamp = data.get_u64(body_offset); let timestamp = data.get_u32(body_offset);
let nonce = data.get_u32(body_offset + Self::VAA_NONCE_POS); let nonce = data.get_u32(body_offset + Self::VAA_NONCE_POS);
let emitter_chain = data.get_u16(body_offset + Self::VAA_EMITTER_CHAIN_POS); let emitter_chain = data.get_u16(body_offset + Self::VAA_EMITTER_CHAIN_POS);
let emitter_address = data let emitter_address = data
@ -402,31 +402,29 @@ mod tests {
#[test] #[test]
fn test_deserialize() { fn test_deserialize() {
let x = vec![ let x = hex::decode("080000000901007bfa71192f886ab6819fa4862e34b4d178962958d9b2e3d9437338c9e5fde1443b809d2886eaa69e0f0158ea517675d96243c9209c3fe1d94d5b19866654c6980000000b150000000500020001020304000000000000000000000000000000000000000000000000000000000000000000000a0261626364").unwrap();
1u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 96u8, 180u8, 80u8, 111u8, 0u8, 0u8, let v = ParsedVAA::deserialize(x.as_slice()).unwrap();
0u8, 1u8, 0u8, 3u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 120u8, assert_eq!(
73u8, 153u8, 19u8, 90u8, 170u8, 138u8, 60u8, 165u8, 145u8, 68u8, 104u8, 133u8, 47u8, v,
221u8, 219u8, 221u8, 216u8, 120u8, 157u8, 0u8, 91u8, 48u8, 44u8, 48u8, 44u8, 51u8, ParsedVAA {
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, version: 8,
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 53u8, 54u8, 44u8, guardian_set_index: 9,
50u8, 51u8, 51u8, 44u8, 49u8, 44u8, 49u8, 49u8, 49u8, 44u8, 49u8, 54u8, 55u8, 44u8, timestamp: 2837,
49u8, 57u8, 48u8, 44u8, 50u8, 48u8, 51u8, 44u8, 49u8, 54u8, 44u8, 49u8, 55u8, 54u8, nonce: 5,
44u8, 50u8, 49u8, 56u8, 44u8, 50u8, 53u8, 49u8, 44u8, 49u8, 51u8, 49u8, 44u8, 51u8, len_signers: 1,
57u8, 44u8, 49u8, 54u8, 44u8, 49u8, 57u8, 53u8, 44u8, 50u8, 50u8, 55u8, 44u8, 49u8, emitter_chain: 2,
52u8, 57u8, 44u8, 50u8, 51u8, 54u8, 44u8, 49u8, 57u8, 48u8, 44u8, 50u8, 49u8, 50u8, emitter_address: vec![
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 0, 0, 0, 0, 0, 0
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, ],
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, sequence: 10,
44u8, 48u8, 44u8, 48u8, 44u8, 51u8, 44u8, 50u8, 51u8, 50u8, 44u8, 48u8, 44u8, 51u8, consistency_level: 2,
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, payload: vec![97, 98, 99, 100],
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 53u8, 51u8, 44u8, hash: vec![
49u8, 49u8, 54u8, 44u8, 52u8, 56u8, 44u8, 49u8, 49u8, 54u8, 44u8, 49u8, 52u8, 57u8, 195, 10, 19, 96, 8, 61, 218, 69, 160, 238, 165, 142, 105, 119, 139, 121, 212,
44u8, 49u8, 48u8, 56u8, 44u8, 49u8, 49u8, 51u8, 44u8, 56u8, 44u8, 48u8, 44u8, 50u8, 73, 238, 179, 13, 80, 245, 224, 75, 110, 163, 8, 185, 132, 55, 34
51u8, 50u8, 44u8, 52u8, 57u8, 44u8, 49u8, 53u8, 50u8, 44u8, 49u8, 44u8, 50u8, 56u8, ]
44u8, 50u8, 48u8, 51u8, 44u8, 50u8, 49u8, 50u8, 44u8, 50u8, 50u8, 49u8, 44u8, 50u8, }
52u8, 49u8, 44u8, 56u8, 53u8, 44u8, 49u8, 48u8, 57u8, 93u8, );
];
ParsedVAA::deserialize(x.as_slice()).unwrap();
} }
} }