cosmwasm: Add fromAddress to payload 3 (#1292)
* cosmwasm: fix some clippy warnings * cosmwasm: remove fee and add msg.sender to payload 3 * cosmwasm: fix payload 3 parsing test * cosmwasm: fix fixed payload 3 parsing test * cosmwasm: fix fixed fixed payload 3 parsing test * cosmwasm: update payload tests Co-authored-by: Csongor Kiss <ckiss@jumptrading.com> Co-authored-by: Evan Gray <battledingo@gmail.com>
This commit is contained in:
parent
c4da29c209
commit
d3a1fa99d9
|
@ -169,9 +169,12 @@ pub fn reply(deps: DepsMut, env: Env, _msg: Reply) -> StdResult<Response> {
|
|||
Action::TRANSFER_WITH_PAYLOAD => {
|
||||
let info = TransferWithPayloadInfo::deserialize(&token_bridge_message.payload)?;
|
||||
Ok((
|
||||
info.transfer_info,
|
||||
info.as_transfer_info(),
|
||||
TransferType::WithPayload {
|
||||
payload: info.payload,
|
||||
// put both the payload and sender_address into the payload
|
||||
// field here (which we can do, since [`TransferType`] is
|
||||
// parametric)
|
||||
payload: (info.payload, info.sender_address),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -209,8 +212,13 @@ pub fn reply(deps: DepsMut, env: Env, _msg: Reply) -> StdResult<Response> {
|
|||
TransferType::WithPayload { payload } => TokenBridgeMessage {
|
||||
action: Action::TRANSFER_WITH_PAYLOAD,
|
||||
payload: TransferWithPayloadInfo {
|
||||
transfer_info,
|
||||
payload,
|
||||
amount: transfer_info.amount,
|
||||
token_address: transfer_info.token_address,
|
||||
token_chain: transfer_info.token_chain,
|
||||
recipient: transfer_info.recipient,
|
||||
recipient_chain: transfer_info.recipient_chain,
|
||||
sender_address: payload.1,
|
||||
payload: payload.0,
|
||||
}
|
||||
.serialize(),
|
||||
},
|
||||
|
@ -368,7 +376,7 @@ fn handle_register_asset(
|
|||
|
||||
let mut bucket = wrapped_asset(deps.storage, chain);
|
||||
let result = bucket.load(&token_address.serialize()).ok();
|
||||
if let Some(_) = result {
|
||||
if result.is_some() {
|
||||
return ContractError::AssetAlreadyRegistered.std_err();
|
||||
}
|
||||
|
||||
|
@ -379,7 +387,7 @@ fn handle_register_asset(
|
|||
},
|
||||
)?;
|
||||
|
||||
let contract_address: CanonicalAddr = deps.api.addr_canonicalize(&info.sender.as_str())?;
|
||||
let contract_address: CanonicalAddr = deps.api.addr_canonicalize(info.sender.as_str())?;
|
||||
is_wrapped_asset(deps.storage).save(contract_address.as_slice(), &())?;
|
||||
|
||||
Ok(Response::new()
|
||||
|
@ -537,7 +545,7 @@ fn handle_create_asset_meta_token(
|
|||
nonce,
|
||||
})?,
|
||||
// forward coins sent to this message
|
||||
funds: info.funds.clone(),
|
||||
funds: info.funds,
|
||||
}))
|
||||
.add_attribute("meta.token_chain", CHAIN_ID.to_string())
|
||||
.add_attribute("meta.token", asset_address)
|
||||
|
@ -577,7 +585,7 @@ fn handle_create_asset_meta_native_token(
|
|||
nonce,
|
||||
})?,
|
||||
// forward coins sent to this message
|
||||
funds: info.funds.clone(),
|
||||
funds: info.funds,
|
||||
}))
|
||||
.add_attribute("meta.token_chain", CHAIN_ID.to_string())
|
||||
.add_attribute("meta.symbol", symbol)
|
||||
|
@ -610,7 +618,7 @@ fn handle_complete_transfer_with_payload(
|
|||
_ => ContractError::InvalidVAAAction.std_err(),
|
||||
}
|
||||
} else {
|
||||
return ContractError::InvalidVAAAction.std_err();
|
||||
ContractError::InvalidVAAAction.std_err()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -640,7 +648,7 @@ fn parse_and_archive_vaa(
|
|||
}
|
||||
|
||||
let message = TokenBridgeMessage::deserialize(&vaa.payload)?;
|
||||
return Ok((vaa, Either::Right(message)));
|
||||
Ok((vaa, Either::Right(message)))
|
||||
}
|
||||
|
||||
fn submit_vaa(
|
||||
|
@ -651,9 +659,7 @@ fn submit_vaa(
|
|||
) -> StdResult<Response> {
|
||||
let (vaa, payload) = parse_and_archive_vaa(deps.branch(), env.clone(), data)?;
|
||||
match payload {
|
||||
Either::Left(governance_packet) => {
|
||||
return handle_governance_payload(deps, env, &governance_packet)
|
||||
}
|
||||
Either::Left(governance_packet) => handle_governance_payload(deps, env, &governance_packet),
|
||||
Either::Right(message) => match message.action {
|
||||
Action::TRANSFER => {
|
||||
let sender = info.sender.to_string();
|
||||
|
@ -706,7 +712,7 @@ fn handle_governance_payload(
|
|||
}
|
||||
|
||||
fn handle_upgrade_contract(_deps: DepsMut, env: Env, data: &Vec<u8>) -> StdResult<Response> {
|
||||
let UpgradeContract { new_contract } = UpgradeContract::deserialize(&data)?;
|
||||
let UpgradeContract { new_contract } = UpgradeContract::deserialize(data)?;
|
||||
|
||||
Ok(Response::new()
|
||||
.add_message(CosmosMsg::Wasm(WasmMsg::Migrate {
|
||||
|
@ -721,7 +727,7 @@ fn handle_register_chain(deps: DepsMut, _env: Env, data: &Vec<u8>) -> StdResult<
|
|||
let RegisterChain {
|
||||
chain_id,
|
||||
chain_address,
|
||||
} = RegisterChain::deserialize(&data)?;
|
||||
} = RegisterChain::deserialize(data)?;
|
||||
|
||||
let existing = bridge_contracts_read(deps.storage).load(&chain_id.to_be_bytes());
|
||||
if existing.is_ok() {
|
||||
|
@ -738,6 +744,7 @@ fn handle_register_chain(deps: DepsMut, _env: Env, data: &Vec<u8>) -> StdResult<
|
|||
.add_attribute("chain_address", hex::encode(chain_address)))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn handle_complete_transfer(
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
|
@ -748,7 +755,7 @@ fn handle_complete_transfer(
|
|||
data: &Vec<u8>,
|
||||
relayer_address: &HumanAddr,
|
||||
) -> StdResult<Response> {
|
||||
let transfer_info = TransferInfo::deserialize(&data)?;
|
||||
let transfer_info = TransferInfo::deserialize(data)?;
|
||||
let token_id = transfer_info
|
||||
.token_address
|
||||
.to_token_id(deps.storage, transfer_info.token_chain)?;
|
||||
|
@ -778,6 +785,8 @@ fn handle_complete_transfer(
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[allow(clippy::bind_instead_of_map)]
|
||||
fn handle_complete_transfer_token(
|
||||
deps: DepsMut,
|
||||
_env: Env,
|
||||
|
@ -790,9 +799,9 @@ fn handle_complete_transfer_token(
|
|||
relayer_address: &HumanAddr,
|
||||
) -> StdResult<Response> {
|
||||
let transfer_info = match transfer_type {
|
||||
TransferType::WithoutPayload => TransferInfo::deserialize(&data)?,
|
||||
TransferType::WithoutPayload => TransferInfo::deserialize(data)?,
|
||||
TransferType::WithPayload { payload: _ } => {
|
||||
TransferWithPayloadInfo::deserialize(&data)?.transfer_info
|
||||
TransferWithPayloadInfo::deserialize(data)?.as_transfer_info()
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -922,6 +931,7 @@ fn handle_complete_transfer_token(
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn handle_complete_transfer_token_native(
|
||||
deps: DepsMut,
|
||||
_env: Env,
|
||||
|
@ -934,9 +944,9 @@ fn handle_complete_transfer_token_native(
|
|||
relayer_address: &HumanAddr,
|
||||
) -> StdResult<Response> {
|
||||
let transfer_info = match transfer_type {
|
||||
TransferType::WithoutPayload => TransferInfo::deserialize(&data)?,
|
||||
TransferType::WithoutPayload => TransferInfo::deserialize(data)?,
|
||||
TransferType::WithPayload { payload: () } => {
|
||||
TransferWithPayloadInfo::deserialize(&data)?.transfer_info
|
||||
TransferWithPayloadInfo::deserialize(data)?.as_transfer_info()
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1000,6 +1010,7 @@ fn handle_complete_transfer_token_native(
|
|||
.add_attribute("fee", fee.to_string()))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn handle_initiate_transfer(
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
|
@ -1039,6 +1050,7 @@ fn handle_initiate_transfer(
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn handle_initiate_transfer_token(
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
|
@ -1067,6 +1079,10 @@ fn handle_initiate_transfer_token(
|
|||
let mut messages: Vec<CosmosMsg> = vec![];
|
||||
let mut submessages: Vec<SubMsg> = vec![];
|
||||
|
||||
// we'll only need this for payload 3 transfers
|
||||
let sender_address = deps.api.addr_canonicalize(&info.sender.to_string())?;
|
||||
let sender_address = extend_address_to_32_array(&sender_address);
|
||||
|
||||
match is_wrapped_asset_read(deps.storage).load(asset_canonical.as_slice()) {
|
||||
Ok(_) => {
|
||||
// If the fee is too large the user will receive nothing.
|
||||
|
@ -1091,28 +1107,38 @@ fn handle_initiate_transfer_token(
|
|||
asset_chain = wrapped_token_info.asset_chain;
|
||||
asset_address = wrapped_token_info.asset_address.to_array()?;
|
||||
|
||||
let transfer_info = TransferInfo {
|
||||
token_chain: asset_chain,
|
||||
token_address: ExternalTokenId::from_foreign_token(asset_chain, asset_address),
|
||||
amount: (0, amount.u128()),
|
||||
recipient_chain,
|
||||
recipient,
|
||||
fee: (0, fee.u128()),
|
||||
};
|
||||
let external_id = ExternalTokenId::from_foreign_token(asset_chain, asset_address);
|
||||
|
||||
let token_bridge_message: TokenBridgeMessage = match transfer_type {
|
||||
TransferType::WithoutPayload => TokenBridgeMessage {
|
||||
action: Action::TRANSFER,
|
||||
payload: transfer_info.serialize(),
|
||||
},
|
||||
TransferType::WithPayload { payload } => TokenBridgeMessage {
|
||||
action: Action::TRANSFER_WITH_PAYLOAD,
|
||||
payload: TransferWithPayloadInfo {
|
||||
transfer_info,
|
||||
payload,
|
||||
TransferType::WithoutPayload => {
|
||||
let transfer_info = TransferInfo {
|
||||
amount: (0, amount.u128()),
|
||||
token_address: external_id,
|
||||
token_chain: asset_chain,
|
||||
recipient,
|
||||
recipient_chain,
|
||||
fee: (0, fee.u128()),
|
||||
};
|
||||
TokenBridgeMessage {
|
||||
action: Action::TRANSFER,
|
||||
payload: transfer_info.serialize(),
|
||||
}
|
||||
.serialize(),
|
||||
},
|
||||
}
|
||||
TransferType::WithPayload { payload } => {
|
||||
let transfer_info = TransferWithPayloadInfo {
|
||||
amount: (0, amount.u128()),
|
||||
token_address: external_id,
|
||||
token_chain: asset_chain,
|
||||
recipient,
|
||||
recipient_chain,
|
||||
sender_address,
|
||||
payload,
|
||||
};
|
||||
TokenBridgeMessage {
|
||||
action: Action::TRANSFER_WITH_PAYLOAD,
|
||||
payload: transfer_info.serialize(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
messages.push(CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
|
@ -1177,15 +1203,6 @@ fn handle_initiate_transfer_token(
|
|||
amount = Uint128::new(amount.u128().checked_div(multiplier).unwrap());
|
||||
fee = Uint128::new(fee.u128().checked_div(multiplier).unwrap());
|
||||
|
||||
let transfer_info = TransferInfo {
|
||||
token_chain: asset_chain,
|
||||
token_address: external_id,
|
||||
amount: (0, amount.u128()),
|
||||
recipient_chain,
|
||||
recipient: recipient.clone(),
|
||||
fee: (0, fee.u128()),
|
||||
};
|
||||
|
||||
// Fetch current CW20 Balance pre-transfer.
|
||||
let balance: BalanceResponse =
|
||||
deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart {
|
||||
|
@ -1206,18 +1223,35 @@ fn handle_initiate_transfer_token(
|
|||
assert!(wrapped_transfer_tmp(deps.storage).load().is_err());
|
||||
|
||||
let token_bridge_message: TokenBridgeMessage = match transfer_type {
|
||||
TransferType::WithoutPayload => TokenBridgeMessage {
|
||||
action: Action::TRANSFER,
|
||||
payload: transfer_info.serialize(),
|
||||
},
|
||||
TransferType::WithPayload { payload } => TokenBridgeMessage {
|
||||
action: Action::TRANSFER_WITH_PAYLOAD,
|
||||
payload: TransferWithPayloadInfo {
|
||||
transfer_info,
|
||||
payload,
|
||||
TransferType::WithoutPayload => {
|
||||
let transfer_info = TransferInfo {
|
||||
amount: (0, amount.u128()),
|
||||
token_address: external_id,
|
||||
token_chain: asset_chain,
|
||||
recipient,
|
||||
recipient_chain,
|
||||
fee: (0, fee.u128()),
|
||||
};
|
||||
TokenBridgeMessage {
|
||||
action: Action::TRANSFER,
|
||||
payload: transfer_info.serialize(),
|
||||
}
|
||||
.serialize(),
|
||||
},
|
||||
}
|
||||
TransferType::WithPayload { payload } => {
|
||||
let transfer_info = TransferWithPayloadInfo {
|
||||
amount: (0, amount.u128()),
|
||||
token_address: external_id,
|
||||
token_chain: asset_chain,
|
||||
recipient,
|
||||
recipient_chain,
|
||||
sender_address,
|
||||
payload,
|
||||
};
|
||||
TokenBridgeMessage {
|
||||
action: Action::TRANSFER_WITH_PAYLOAD,
|
||||
payload: transfer_info.serialize(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let token_address = deps.api.addr_validate(&asset)?;
|
||||
|
@ -1242,7 +1276,7 @@ fn handle_initiate_transfer_token(
|
|||
.add_attribute(
|
||||
"transfer.sender",
|
||||
hex::encode(extend_address_to_32(
|
||||
&deps.api.addr_canonicalize(&info.sender.as_str())?,
|
||||
&deps.api.addr_canonicalize(info.sender.as_str())?,
|
||||
)),
|
||||
)
|
||||
.add_attribute("transfer.recipient_chain", recipient_chain.to_string())
|
||||
|
@ -1257,9 +1291,10 @@ fn format_native_denom_symbol(denom: &str) -> String {
|
|||
return "LUNA".to_string();
|
||||
}
|
||||
//TODO: is there better formatting to do here?
|
||||
denom.to_uppercase().to_string()
|
||||
denom.to_uppercase()
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn handle_initiate_transfer_native_token(
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
|
@ -1299,38 +1334,48 @@ fn handle_initiate_transfer_native_token(
|
|||
|
||||
send_native(deps.storage, &asset_address, amount)?;
|
||||
|
||||
let transfer_info = TransferInfo {
|
||||
token_chain: asset_chain,
|
||||
token_address: asset_address.clone(),
|
||||
amount: (0, amount.u128()),
|
||||
recipient_chain,
|
||||
recipient: recipient.clone(),
|
||||
fee: (0, fee.u128()),
|
||||
};
|
||||
|
||||
let token_bridge_message: TokenBridgeMessage = match transfer_type {
|
||||
TransferType::WithoutPayload => TokenBridgeMessage {
|
||||
action: Action::TRANSFER,
|
||||
payload: transfer_info.serialize(),
|
||||
},
|
||||
TransferType::WithPayload { payload } => TokenBridgeMessage {
|
||||
action: Action::TRANSFER_WITH_PAYLOAD,
|
||||
payload: TransferWithPayloadInfo {
|
||||
transfer_info,
|
||||
payload,
|
||||
TransferType::WithoutPayload => {
|
||||
let transfer_info = TransferInfo {
|
||||
amount: (0, amount.u128()),
|
||||
token_address: asset_address.clone(),
|
||||
token_chain: asset_chain,
|
||||
recipient,
|
||||
recipient_chain,
|
||||
fee: (0, fee.u128()),
|
||||
};
|
||||
TokenBridgeMessage {
|
||||
action: Action::TRANSFER,
|
||||
payload: transfer_info.serialize(),
|
||||
}
|
||||
.serialize(),
|
||||
},
|
||||
}
|
||||
TransferType::WithPayload { payload } => {
|
||||
let sender_address = deps.api.addr_canonicalize(&info.sender.to_string())?;
|
||||
let sender_address = extend_address_to_32_array(&sender_address);
|
||||
let transfer_info = TransferWithPayloadInfo {
|
||||
amount: (0, amount.u128()),
|
||||
token_address: asset_address.clone(),
|
||||
token_chain: asset_chain,
|
||||
recipient,
|
||||
recipient_chain,
|
||||
sender_address,
|
||||
payload,
|
||||
};
|
||||
TokenBridgeMessage {
|
||||
action: Action::TRANSFER_WITH_PAYLOAD,
|
||||
payload: transfer_info.serialize(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let sender = deps.api.addr_canonicalize(&info.sender.as_str())?;
|
||||
let sender = deps.api.addr_canonicalize(info.sender.as_str())?;
|
||||
messages.push(CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: cfg.wormhole_contract,
|
||||
msg: to_binary(&WormholeExecuteMsg::PostMessage {
|
||||
message: Binary::from(token_bridge_message.serialize()),
|
||||
nonce,
|
||||
})?,
|
||||
funds: info.funds.clone(),
|
||||
funds: info.funds,
|
||||
}));
|
||||
|
||||
Ok(Response::new()
|
||||
|
@ -1372,7 +1417,7 @@ pub fn query_wrapped_registry(
|
|||
address: &[u8],
|
||||
) -> StdResult<WrappedRegistryResponse> {
|
||||
// Check if this asset is already deployed
|
||||
match wrapped_asset_read(deps.storage, chain).load(&address) {
|
||||
match wrapped_asset_read(deps.storage, chain).load(address) {
|
||||
Ok(address) => Ok(WrappedRegistryResponse {
|
||||
address: address.into_string(),
|
||||
}),
|
||||
|
@ -1394,9 +1439,22 @@ fn query_transfer_info(deps: Deps, env: Env, vaa: &Binary) -> StdResult<Transfer
|
|||
let message = TokenBridgeMessage::deserialize(&data)?;
|
||||
match message.action {
|
||||
Action::ATTEST_META => ContractError::InvalidVAAAction.std_err(),
|
||||
_ => {
|
||||
Action::TRANSFER => {
|
||||
let core = TransferInfo::deserialize(&message.payload)?;
|
||||
|
||||
Ok(TransferInfoResponse {
|
||||
amount: core.amount.1.into(),
|
||||
token_address: core.token_address.serialize(),
|
||||
token_chain: core.token_chain,
|
||||
recipient: core.recipient,
|
||||
recipient_chain: core.recipient_chain,
|
||||
fee: core.fee.1.into(),
|
||||
payload: vec![],
|
||||
})
|
||||
}
|
||||
Action::TRANSFER_WITH_PAYLOAD => {
|
||||
let info = TransferWithPayloadInfo::deserialize(&message.payload)?;
|
||||
let core = info.transfer_info;
|
||||
let core = info.as_transfer_info();
|
||||
|
||||
Ok(TransferInfoResponse {
|
||||
amount: core.amount.1.into(),
|
||||
|
@ -1408,9 +1466,10 @@ fn query_transfer_info(deps: Deps, env: Env, vaa: &Binary) -> StdResult<Transfer
|
|||
payload: info.payload,
|
||||
})
|
||||
}
|
||||
other => Err(StdError::generic_err(format!("Invalid action: {}", other))),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_governance_emitter(cfg: &ConfigInfo, emitter_chain: u16, emitter_address: &Vec<u8>) -> bool {
|
||||
cfg.gov_chain == emitter_chain && cfg.gov_address == emitter_address.clone()
|
||||
fn is_governance_emitter(cfg: &ConfigInfo, emitter_chain: u16, emitter_address: &[u8]) -> bool {
|
||||
cfg.gov_chain == emitter_chain && cfg.gov_address == emitter_address
|
||||
}
|
||||
|
|
|
@ -250,30 +250,72 @@ impl TransferInfo {
|
|||
// 64 u16 token_chain
|
||||
// 66 [u8; 32] recipient
|
||||
// 98 u16 recipient_chain
|
||||
// 100 u256 fee
|
||||
// 100 [u8; 32] sender_address
|
||||
// 132 [u8] payload
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
pub struct TransferWithPayloadInfo {
|
||||
pub transfer_info: TransferInfo,
|
||||
pub amount: (u128, u128),
|
||||
pub token_address: ExternalTokenId,
|
||||
pub token_chain: u16,
|
||||
pub recipient: [u8; 32],
|
||||
pub recipient_chain: u16,
|
||||
pub sender_address: [u8; 32],
|
||||
pub payload: Vec<u8>,
|
||||
}
|
||||
|
||||
impl TransferWithPayloadInfo {
|
||||
pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> {
|
||||
let transfer_info = TransferInfo::deserialize(data)?;
|
||||
let data = data.as_slice();
|
||||
let amount = data.get_u256(0);
|
||||
let token_address = ExternalTokenId::deserialize(data.get_const_bytes::<32>(32));
|
||||
let token_chain = data.get_u16(64);
|
||||
let recipient = data.get_const_bytes::<32>(66);
|
||||
let recipient_chain = data.get_u16(98);
|
||||
let sender_address = data.get_const_bytes::<32>(100);
|
||||
let payload = TransferWithPayloadInfo::get_payload(data);
|
||||
|
||||
Ok(TransferWithPayloadInfo {
|
||||
transfer_info,
|
||||
amount,
|
||||
token_address,
|
||||
token_chain,
|
||||
recipient,
|
||||
recipient_chain,
|
||||
sender_address,
|
||||
payload,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
[self.transfer_info.serialize(), self.payload.clone()].concat()
|
||||
[
|
||||
self.amount.0.to_be_bytes().to_vec(),
|
||||
self.amount.1.to_be_bytes().to_vec(),
|
||||
self.token_address.serialize().to_vec(),
|
||||
self.token_chain.to_be_bytes().to_vec(),
|
||||
self.recipient.to_vec(),
|
||||
self.recipient_chain.to_be_bytes().to_vec(),
|
||||
self.sender_address.to_vec(),
|
||||
self.payload.clone(),
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
pub fn get_payload(data: &Vec<u8>) -> Vec<u8> {
|
||||
return data[132..].to_vec();
|
||||
|
||||
pub fn get_payload(data: &[u8]) -> Vec<u8> {
|
||||
data[132..].to_vec()
|
||||
}
|
||||
|
||||
/// Convert [`TransferWithPayloadInfo`] into [`TransferInfo`] for the
|
||||
/// purpose of handling them uniformly. Transfers with payload have 0 fees.
|
||||
pub fn as_transfer_info(&self) -> TransferInfo {
|
||||
TransferInfo {
|
||||
amount: self.amount,
|
||||
token_address: self.token_address.clone(),
|
||||
token_chain: self.token_chain,
|
||||
recipient: self.recipient,
|
||||
recipient_chain: self.recipient_chain,
|
||||
fee: (0, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,15 +141,37 @@ fn deserialize_transfer_vaa() -> StdResult<()> {
|
|||
|
||||
#[test]
|
||||
fn deserialize_transfer_with_payload_vaa() -> StdResult<()> {
|
||||
|
||||
// ┌──────────────────────────────────────────────────────────────────────────────┐
|
||||
// │ Wormhole VAA v1 │ nonce: 2080370133 │ time: 0 │
|
||||
// │ guardian set #0 │ #4568529024235897313 │ consistency: 32 │
|
||||
// ├──────────────────────────────────────────────────────────────────────────────┤
|
||||
// │ Signature: │
|
||||
// │ #0: 2565e7ae10421624fd81118855acda893e752aeeef31c13fbfc417591ada... │
|
||||
// ├──────────────────────────────────────────────────────────────────────────────┤
|
||||
// │ Emitter: 11111111111111111111111111111115 (Solana) │
|
||||
// ╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
// │ Token transfer with payload (aka payload 3) │
|
||||
// │ Amount: 1.0 │
|
||||
// │ Token: terra1qqqqqqqqqqqqqqqqqqqqqqqqqp6h2umyswfh6y (Terra) │
|
||||
// │ Recipient: terra13nkgqrfymug724h8pprpexqj9h629sa3ncw7sh (Terra) │
|
||||
// │ From: 1399a4e782b935d2bb36b97586d3df8747b07dc66902d807eed0ae99e00ed256 │
|
||||
// ╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
// │ Custom payload: │
|
||||
// │ Length: 30 (0x1e) bytes │
|
||||
// │ 0000: 41 6c 6c 20 79 6f 75 72 20 62 61 73 65 20 61 72 All your base ar│
|
||||
// │ 0010: 65 20 62 65 6c 6f 6e 67 20 74 6f 20 75 73 e belong to us │
|
||||
// └──────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
let signed_vaa = "\
|
||||
010000000001002b0e392ebe370e718b91dcafbba21094efd8e7f1f12e28bd90\
|
||||
a178b4dfbbc708675152a3cd2edd20e8e018600026b73b6c6cbf02622903409e\
|
||||
8b48ab7fa30ef001000000010000000100010000000000000000000000000000\
|
||||
00000000000000000000000000000000ffff0000000000000002000300000000\
|
||||
00000000000000000000000000000000000000000000000005f5e10001000000\
|
||||
010000000001002565e7ae10421624fd81118855acda893e752aeeef31c13fbf\
|
||||
c417591ada039822195a1321a72cc4bac1c6031e0595f1c1361ca2a30d941a41\
|
||||
95fad8020d43d500000000007bffedd500010000000000000000000000000000\
|
||||
0000000000000000000000000000000000043f66acf143a481e1200300000000\
|
||||
00000000000000000000000000000000000000000000000005f5e10000000000\
|
||||
0000000000000000000000000000000000000000000000007575736400030000\
|
||||
000000000000000000008cec800d24df11e556e708461c98122df4a2c3b10003\
|
||||
00000000000000000000000000000000000000000000000000000000000f4240\
|
||||
1399a4e782b935d2bb36b97586d3df8747b07dc66902d807eed0ae99e00ed256\
|
||||
416c6c20796f75722062617365206172652062656c6f6e6720746f207573";
|
||||
let signed_vaa = hex::decode(signed_vaa).unwrap();
|
||||
|
||||
|
@ -161,13 +183,12 @@ fn deserialize_transfer_with_payload_vaa() -> StdResult<()> {
|
|||
"message.action != expected"
|
||||
);
|
||||
|
||||
let info_with_payload = TransferWithPayloadInfo::deserialize(&message.payload)?;
|
||||
let info = info_with_payload.transfer_info;
|
||||
let info = TransferWithPayloadInfo::deserialize(&message.payload)?;
|
||||
|
||||
let amount = (0u128, 100_000_000u128);
|
||||
assert_eq!(info.amount, amount, "info.amount != expected");
|
||||
|
||||
let token_address = "0100000000000000000000000000000000000000000000000000000075757364";
|
||||
let token_address = "0000000000000000000000000000000000000000000000000000000075757364";
|
||||
let token_address = hex::decode(token_address).unwrap();
|
||||
assert_eq!(
|
||||
info.token_address.serialize().to_vec(),
|
||||
|
@ -189,19 +210,25 @@ fn deserialize_transfer_with_payload_vaa() -> StdResult<()> {
|
|||
"info.recipient != expected"
|
||||
);
|
||||
|
||||
let sender = "1399a4e782b935d2bb36b97586d3df8747b07dc66902d807eed0ae99e00ed256";
|
||||
let sender = hex::decode(sender).unwrap();
|
||||
assert_eq!(
|
||||
info.sender_address.to_vec(),
|
||||
sender,
|
||||
"info.sender != expected"
|
||||
);
|
||||
|
||||
let recipient_chain = 3u16;
|
||||
assert_eq!(
|
||||
info.recipient_chain, recipient_chain,
|
||||
"info.recipient_chain != expected"
|
||||
);
|
||||
|
||||
let fee = (0u128, 1_000_000u128);
|
||||
assert_eq!(info.fee, fee, "info.fee != expected");
|
||||
|
||||
let transfer_payload = "All your base are belong to us";
|
||||
let transfer_payload = transfer_payload.as_bytes();
|
||||
assert_eq!(
|
||||
info_with_payload.payload.as_slice(),
|
||||
info.payload.as_slice(),
|
||||
transfer_payload,
|
||||
"info.payload != expected"
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
getEmitterAddressTerra,
|
||||
parseSequenceFromLogTerra,
|
||||
setDefaultWasm,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
|
@ -539,7 +540,7 @@ describe("Bridge Tests", () => {
|
|||
|
||||
// need to deposit before initiating transfer
|
||||
const deposit = new MsgExecuteContract(
|
||||
wallet.key.accAddress,
|
||||
walletAddress,
|
||||
tokenBridge,
|
||||
{
|
||||
deposit_tokens: {},
|
||||
|
@ -565,7 +566,7 @@ describe("Bridge Tests", () => {
|
|||
"base64"
|
||||
),
|
||||
fee: relayerFee,
|
||||
payload: Buffer.from(myPayload, "hex").toString("base64"),
|
||||
payload: Buffer.from(myPayload, "ascii").toString("base64"),
|
||||
nonce: 69,
|
||||
},
|
||||
}
|
||||
|
@ -584,6 +585,61 @@ describe("Bridge Tests", () => {
|
|||
initiateTransferWithPayload,
|
||||
]);
|
||||
|
||||
console.log(receipt);
|
||||
|
||||
const jsonLog = JSON.parse(receipt.raw_log);
|
||||
let message = "";
|
||||
jsonLog.map((row: any) => {
|
||||
row.events.map((event: any) => {
|
||||
event.attributes.map((attribute: any) => {
|
||||
if (attribute.key === "message.message") {
|
||||
message = attribute.value;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
// payload type
|
||||
let last = 0;
|
||||
let len = 2;
|
||||
expect(message.substring(last, last + len)).toEqual("03");
|
||||
last += len;
|
||||
// amount
|
||||
len = 64;
|
||||
expect(message.substring(last, last + len)).toEqual(
|
||||
"0000000000000000000000000000000000000000000000000000000005f5e100"
|
||||
);
|
||||
last += len;
|
||||
// token address
|
||||
len = 64;
|
||||
expect(message.substring(last, last + len)).toEqual(
|
||||
"01fa6c6fbc36d8c245b0a852a43eb5d644e8b4c477b27bfab9537c10945939da"
|
||||
);
|
||||
last += len;
|
||||
// token chain
|
||||
len = 4;
|
||||
expect(message.substring(last, last + len)).toEqual("0012");
|
||||
last += len;
|
||||
// recipient address
|
||||
len = 64;
|
||||
expect(message.substring(last, last + len)).toEqual(
|
||||
"0000000000000000000000004206942069420694206942069420694206942069"
|
||||
);
|
||||
last += len;
|
||||
// recipient chain
|
||||
len = 4;
|
||||
expect(message.substring(last, last + len)).toEqual("0002");
|
||||
last += len;
|
||||
// sender address
|
||||
len = 64;
|
||||
expect(message.substring(last, last + len)).toEqual(
|
||||
await getEmitterAddressTerra(walletAddress)
|
||||
);
|
||||
last += len;
|
||||
// payload
|
||||
expect(message.substring(last)).toEqual(
|
||||
Buffer.from(myPayload, "ascii").toString("hex")
|
||||
);
|
||||
|
||||
const balanceAfter = await getNativeBalance(client, tokenBridge, denom);
|
||||
expect(balanceBefore.add(amount).eq(balanceAfter)).toBeTruthy();
|
||||
|
||||
|
@ -617,7 +673,7 @@ describe("Bridge Tests", () => {
|
|||
LUNA_ADDRESS,
|
||||
encodedTo,
|
||||
CHAIN_ID,
|
||||
relayerFee,
|
||||
relayerFee, // now sender_address
|
||||
additionalPayload
|
||||
);
|
||||
|
||||
|
@ -638,11 +694,6 @@ describe("Bridge Tests", () => {
|
|||
);
|
||||
|
||||
// check balances before execute
|
||||
const walletBalanceBefore = await getNativeBalance(
|
||||
client,
|
||||
walletAddress,
|
||||
denom
|
||||
);
|
||||
const contractBalanceBefore = await getNativeBalance(
|
||||
client,
|
||||
mockBridgeIntegration,
|
||||
|
@ -667,33 +718,13 @@ describe("Bridge Tests", () => {
|
|||
// execute outbound transfer with signed vaa
|
||||
const receipt = await transactWithoutMemo(client, wallet, [submitVaa]);
|
||||
|
||||
// check wallet (relayer) balance change
|
||||
const walletBalanceAfter = await getNativeBalance(
|
||||
client,
|
||||
walletAddress,
|
||||
denom
|
||||
);
|
||||
const gasPaid = computeGasPaid(receipt);
|
||||
const walletExpectedChange = new Int(relayerFee).sub(gasPaid);
|
||||
|
||||
// due to rounding, we should expect the balances to reconcile
|
||||
// within 1 unit (equivalent to 1e-6 uluna). Best-case scenario
|
||||
// we end up with slightly more balance than expected
|
||||
const reconciled = walletBalanceAfter
|
||||
.minus(walletExpectedChange)
|
||||
.minus(walletBalanceBefore);
|
||||
expect(
|
||||
reconciled.greaterThanOrEqualTo("0") &&
|
||||
reconciled.lessThanOrEqualTo("1")
|
||||
).toBeTruthy();
|
||||
|
||||
// check contract balance change
|
||||
const contractBalanceAfter = await getNativeBalance(
|
||||
client,
|
||||
mockBridgeIntegration,
|
||||
denom
|
||||
);
|
||||
const contractExpectedChange = new Int(amount).sub(relayerFee);
|
||||
const contractExpectedChange = new Int(amount);
|
||||
expect(
|
||||
contractBalanceBefore
|
||||
.add(contractExpectedChange)
|
||||
|
|
Loading…
Reference in New Issue