diff --git a/e2e/test.sh b/e2e/test.sh index 92a9fb72..a50d6df6 100755 --- a/e2e/test.sh +++ b/e2e/test.sh @@ -1,6 +1,7 @@ #!/bin/bash SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # source: https://stackoverflow.com/a/246128/3437868 WORKSPACE_DIR=$(cd $SCRIPT_DIR/.. && pwd) +echo "sudo rm -rf $WORKSPACE_DIR/artifacts" sudo rm -rf $WORKSPACE_DIR/artifacts $WORKSPACE_DIR/ts-relayer-tests/build.sh echo "running tests..." diff --git a/external-wasms/cw721_incoming_proxy.wasm b/external-wasms/cw721_incoming_proxy.wasm index e07d7308..08286f24 100644 Binary files a/external-wasms/cw721_incoming_proxy.wasm and b/external-wasms/cw721_incoming_proxy.wasm differ diff --git a/packages/ics721-types/src/types.rs b/packages/ics721-types/src/types.rs index 11f01cda..a4070bb0 100644 --- a/packages/ics721-types/src/types.rs +++ b/packages/ics721-types/src/types.rs @@ -4,12 +4,6 @@ use serde::{Deserialize, Serialize}; use crate::ibc::NonFungibleTokenPacketData; -#[cw_serde] -pub struct Ics721ReceiveIbcPacketMsg { - pub packet: IbcPacket, - pub data: NonFungibleTokenPacketData, -} - #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug, PartialEq)] #[allow(clippy::derive_partial_eq_without_eq)] #[schemars(crate = "cosmwasm_schema::schemars")] @@ -74,4 +68,9 @@ pub enum ReceiverExecuteMsg { /// Being called as a status update of the transfer. (source side) /// Note - Failing this message will NOT fail the transfer, its just a status update. Ics721AckCallback(Ics721AckCallbackMsg), + + Ics721ReceivePacketMsg { + packet: IbcPacket, + data: NonFungibleTokenPacketData, + } } diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index fe0c1c69..414d05c1 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -19,8 +19,7 @@ use crate::{ }; use ics721_types::{ ibc::NonFungibleTokenPacketData, - token_types::{Class, ClassId, Token, TokenId}, - types::Ics721ReceiveIbcPacketMsg, + token_types::{Class, ClassId, Token, TokenId}, types::ReceiverExecuteMsg, }; /// Every incoming token has some associated action. @@ -62,13 +61,13 @@ pub(crate) fn receive_ibc_packet( let incoming_proxy_msg = match INCOMING_PROXY.load(deps.storage).ok().flatten() { Some(incoming_proxy) => { - let msg = Ics721ReceiveIbcPacketMsg { + let msg = to_json_binary(&ReceiverExecuteMsg::Ics721ReceivePacketMsg { packet: packet.clone(), data: data.clone(), - }; + })?; Some(WasmMsg::Execute { contract_addr: incoming_proxy.to_string(), - msg: to_json_binary(&msg)?, + msg, funds: vec![], }) } diff --git a/ts-relayer-tests/build.sh b/ts-relayer-tests/build.sh index bcef98c7..66276c45 100755 --- a/ts-relayer-tests/build.sh +++ b/ts-relayer-tests/build.sh @@ -1,4 +1,7 @@ #!/bin/bash +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # source: https://stackoverflow.com/a/246128/3437868 +ARTIFACTS_DIR="$SCRIPT_DIR/../artifacts" +EXTERNAL_WASMS_DIR="$SCRIPT_DIR/../external-wasms" ## Compiles an optimizes the local contracts for testing with ## ts-relayer. @@ -13,9 +16,9 @@ docker run --rm -v "$(pwd)":/code --platform linux/amd64 \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ cosmwasm/workspace-optimizer:0.15.0 -mkdir -p ./ts-relayer-tests/internal -cp ./artifacts/*.wasm ./ts-relayer-tests/internal -cp ./external-wasms/*.wasm ./ts-relayer-tests/internal +mkdir -p $SCRIPT_DIR/internal +cp $ARTIFACTS_DIR/*.wasm $SCRIPT_DIR/internal +cp $EXTERNAL_WASMS_DIR/*.wasm $SCRIPT_DIR/internal echo "done. avaliable wasm blobs:" ls ./ts-relayer-tests/internal diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index 8f276f82..27ea73c1 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -181,7 +181,7 @@ const standardSetup = async (t: ExecutionContext) => { t.pass(); }; -test.serial("transfer NFT", async (t) => { +test.serial("transfer NFT: wasmd -> osmo", async (t) => { await standardSetup(t); const { @@ -213,7 +213,7 @@ test.serial("transfer NFT", async (t) => { }, }; - t.log("transfering to osmo chain"); + t.log(`transfering to osmo chain via ${channel.channel.src.channelId}`); const transferResponse = await sendNft( wasmClient, @@ -235,8 +235,6 @@ test.serial("transfer NFT", async (t) => { tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); t.is(wasmIcs721, tokenOwner.owner); - t.context.channel.channel.dest.channelId; - const osmoClassId = `${t.context.channel.channel.dest.portId}/${t.context.channel.channel.dest.channelId}/${t.context.wasmCw721}`; const osmoCw721 = await osmoClient.sign.queryContractSmart(osmoIcs721, { nft_contract: { class_id: osmoClassId }, @@ -246,6 +244,72 @@ test.serial("transfer NFT", async (t) => { t.is(osmoAddr, tokenOwner.owner); }); +test.serial.only( + "transfer NFT with incoming proxy: osmo -> wasmd", + async (t) => { + await standardSetup(t); + + const { + wasmClient, + wasmAddr, + wasmIcs721, + osmoClient, + osmoAddr, + osmoCw721, + osmoIcs721, + channel, + } = t.context; + + t.log(JSON.stringify(osmoClient, undefined, 2)); + const tokenId = "1"; + await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); + // assert token is minted + let tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoAddr, tokenOwner.owner); + + const ibcMsg = { + receiver: wasmAddr, + channel_id: channel.channel.dest.channelId, + timeout: { + block: { + revision: 1, + height: 90000, + }, + }, + }; + + t.log(`transfering to wasm chain via ${channel.channel.dest.channelId}`); + + const transferResponse = await sendNft( + osmoClient, + osmoCw721, + osmoIcs721, + ibcMsg, + tokenId + ); + t.truthy(transferResponse); + + t.log("relaying packets"); + + const info = await channel.link.relayAll(); + + // Verify we got a success + assertAckSuccess(info.acksFromA); + + // assert NFT on chain A is locked/owned by ICS contract + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoIcs721, tokenOwner.owner); + + const wasmClassId = `${t.context.channel.channel.src.portId}/${t.context.channel.channel.src.channelId}/${t.context.osmoCw721}`; + const wasmCw721 = await wasmClient.sign.queryContractSmart(wasmIcs721, { + nft_contract: { class_id: wasmClassId }, + }); + + tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); + t.is(wasmAddr, tokenOwner.owner); + } +); + test.serial("malicious NFT", async (t) => { await standardSetup(t);