@@ -37,7 +37,7 @@ const ALICE: AccountId = AccountId::new([0u8; 32]);
3737const BOB : AccountId = AccountId :: new ( [ 1u8 ; 32 ] ) ;
3838const INITIAL_BALANCE : u128 = 100 ;
3939const SEND_AMOUNT : u128 = 10 ;
40- const FEE_AMOUNT : u128 = 1 ;
40+ const FEE_AMOUNT : u128 = 2 ;
4141
4242#[ test]
4343fn report_outcome_notify_works ( ) {
@@ -1045,9 +1045,9 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works
10451045 assert_eq ! ( expected_asset. id, MultiLocation :: here( ) . into( ) ) ;
10461046
10471047 // reanchor according to test-case.
1048- let mut expected_fee_on_reserve = assets. get ( fee_index) . unwrap ( ) . clone ( ) ;
1049- expected_fee_on_reserve. reanchor ( & fee_reserve_location, context) . unwrap ( ) ;
10501048 let expected_dest_on_reserve = dest. reanchored ( & fee_reserve_location, context) . unwrap ( ) ;
1049+ let mut expected_fee_on_reserve = expected_fee. clone ( ) ;
1050+ expected_fee_on_reserve. reanchor ( & fee_reserve_location, context) . unwrap ( ) ;
10511051 expected_fee. reanchor ( & dest, context) . unwrap ( ) ;
10521052 expected_asset. reanchor ( & dest, context) . unwrap ( ) ;
10531053
@@ -1213,9 +1213,9 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve
12131213 assert_eq ! ( expected_asset. id, foreign_asset_id_multilocation. into( ) ) ;
12141214
12151215 // reanchor according to test-case.
1216- let mut expected_fee_on_reserve = assets. get ( fee_index) . unwrap ( ) . clone ( ) ;
1217- expected_fee_on_reserve. reanchor ( & fee_reserve_location, context) . unwrap ( ) ;
12181216 let expected_dest_on_reserve = dest. reanchored ( & fee_reserve_location, context) . unwrap ( ) ;
1217+ let mut expected_fee_on_reserve = expected_fee. clone ( ) ;
1218+ expected_fee_on_reserve. reanchor ( & fee_reserve_location, context) . unwrap ( ) ;
12191219 expected_fee. reanchor ( & dest, context) . unwrap ( ) ;
12201220 expected_asset. reanchor ( & dest, context) . unwrap ( ) ;
12211221
@@ -1632,7 +1632,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() {
16321632
16331633/// Test `reserve_transfer_assets` with destination asset reserve and teleported fee.
16341634///
1635- /// Transferring native asset (local reserve) to `FOREIGN_ASSET_RESERVE_PARA_ID`. Using
1635+ /// Transferring foreign asset (destination reserve) to `FOREIGN_ASSET_RESERVE_PARA_ID`. Using
16361636/// teleport-trusted USDT for fees.
16371637///
16381638/// ```nocompile
@@ -1816,11 +1816,223 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor
18161816
18171817/// Test `reserve_transfer_assets` with remote asset reserve and teleported fee.
18181818///
1819- /// Asserts that the sender's balance is decreased and the beneficiary's balance
1820- /// is increased. Verifies the correct message is sent and event is emitted.
1819+ /// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `USDT_PARA_ID`. Using
1820+ /// teleport-trusted USDT for fees.
1821+ ///
1822+ /// ```nocompile
1823+ /// | chain `A` | chain `C` | chain `B`
1824+ /// | Here (source) | FOREIGN_ASSET_RESERVE_PARA_ID | USDT_PARA_ID (destination)
1825+ /// | | `assets` reserve | `fees` (USDT) teleport-trust
1826+ /// |
1827+ /// | 1. `A` executes `InitiateTeleport(fees)` dest `C`
1828+ /// | \----------> `C` executes `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)`
1829+ /// |
1830+ /// | 2. `A` executes `InitiateTeleport(fees)` dest `B`
1831+ /// | \-------------------------------------------------> `B` executes:
1832+ /// | `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)`
1833+ /// |
1834+ /// | 3. `A` executes `InitiateReserveWithdraw(assets)` dest `B`
1835+ /// | --------------------------------------------------> `DepositAsset(assets)`
1836+ /// ```
18211837#[ test]
18221838fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works ( ) {
1823- // TODO
1839+ let usdt_chain = RelayLocation :: get ( ) . pushed_with_interior ( Parachain ( USDT_PARA_ID ) ) . unwrap ( ) ;
1840+ let usdt_chain_sovereign_account = SovereignAccountOf :: convert_location ( & usdt_chain) . unwrap ( ) ;
1841+ let usdt_id_multilocation = usdt_chain;
1842+ let usdt_initial_local_amount = 42 ;
1843+
1844+ let reserve_location = RelayLocation :: get ( )
1845+ . pushed_with_interior ( Parachain ( FOREIGN_ASSET_RESERVE_PARA_ID ) )
1846+ . unwrap ( ) ;
1847+ let foreign_asset_id_multilocation =
1848+ reserve_location. pushed_with_interior ( FOREIGN_ASSET_INNER_JUNCTION ) . unwrap ( ) ;
1849+ let foreign_asset_initial_amount = 142 ;
1850+ let reserve_sovereign_account =
1851+ SovereignAccountOf :: convert_location ( & reserve_location) . unwrap ( ) ;
1852+
1853+ // transfer destination is USDT chain (foreign asset needs to go through its reserve chain)
1854+ let dest = usdt_chain;
1855+ let assets: MultiAssets = vec ! [
1856+ // USDT for fees (is sufficient on local chain too)
1857+ ( usdt_id_multilocation, FEE_AMOUNT ) . into( ) ,
1858+ // foreign asset to transfer (not used for fees) - remote reserve
1859+ ( foreign_asset_id_multilocation, SEND_AMOUNT ) . into( ) ,
1860+ ]
1861+ . into ( ) ;
1862+ let fee_index = 0 ;
1863+ let asset_index = 1 ;
1864+
1865+ let context = UniversalLocation :: get ( ) ;
1866+ let mut expected_fee = assets. get ( fee_index) . unwrap ( ) . clone ( ) ;
1867+ let mut expected_asset = assets. get ( asset_index) . unwrap ( ) . clone ( ) ;
1868+
1869+ // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`.
1870+ assert_eq ! ( expected_fee. id, usdt_id_multilocation. into( ) ) ;
1871+ assert_eq ! ( expected_asset. id, foreign_asset_id_multilocation. into( ) ) ;
1872+
1873+ // reanchor according to test-case.
1874+ let expected_dest_on_reserve = dest. reanchored ( & reserve_location, context) . unwrap ( ) ;
1875+ let mut expected_fee_on_reserve = expected_fee. clone ( ) ;
1876+ let mut expected_asset_on_reserve = expected_asset. clone ( ) ;
1877+ expected_fee_on_reserve. reanchor ( & reserve_location, context) . unwrap ( ) ;
1878+ expected_asset_on_reserve. reanchor ( & reserve_location, context) . unwrap ( ) ;
1879+ expected_fee. reanchor ( & dest, context) . unwrap ( ) ;
1880+ expected_asset. reanchor ( & dest, context) . unwrap ( ) ;
1881+
1882+ // fees are split between the asset-reserve chain and the destination chain
1883+ crate :: Pallet :: < Test > :: halve_fungible_asset ( & mut expected_fee_on_reserve) . unwrap ( ) ;
1884+ crate :: Pallet :: < Test > :: halve_fungible_asset ( & mut expected_fee) . unwrap ( ) ;
1885+
1886+ let balances = vec ! [
1887+ ( ALICE , INITIAL_BALANCE ) ,
1888+ ( usdt_chain_sovereign_account. clone( ) , INITIAL_BALANCE ) ,
1889+ ( reserve_sovereign_account. clone( ) , INITIAL_BALANCE ) ,
1890+ ] ;
1891+ let beneficiary: MultiLocation =
1892+ Junction :: AccountId32 { network : None , id : ALICE . into ( ) } . into ( ) ;
1893+ let expected_beneficiary_on_reserve = beneficiary;
1894+
1895+ new_test_ext_with_balances ( balances) . execute_with ( || {
1896+ // create sufficient foreign asset USDT (0 total issuance)
1897+ assert_ok ! ( Assets :: force_create(
1898+ RuntimeOrigin :: root( ) ,
1899+ usdt_id_multilocation,
1900+ BOB ,
1901+ true ,
1902+ 1
1903+ ) ) ;
1904+ // USDT should have been teleported/reserve-transferred in, but for this test we just
1905+ // mint it locally.
1906+ assert_ok ! ( Assets :: mint(
1907+ RuntimeOrigin :: signed( BOB ) ,
1908+ usdt_id_multilocation,
1909+ ALICE ,
1910+ usdt_initial_local_amount
1911+ ) ) ;
1912+ // create non-sufficient foreign asset BLA (0 total issuance)
1913+ assert_ok ! ( Assets :: force_create(
1914+ RuntimeOrigin :: root( ) ,
1915+ foreign_asset_id_multilocation,
1916+ BOB ,
1917+ false ,
1918+ 1
1919+ ) ) ;
1920+ // foreign asset BLA should have been teleported/reserve-transferred in, but for this test
1921+ // we just mint it locally.
1922+ assert_ok ! ( Assets :: mint(
1923+ RuntimeOrigin :: signed( BOB ) ,
1924+ foreign_asset_id_multilocation,
1925+ ALICE ,
1926+ foreign_asset_initial_amount
1927+ ) ) ;
1928+ assert_eq ! ( Assets :: balance( usdt_id_multilocation, ALICE ) , usdt_initial_local_amount) ;
1929+ assert_eq ! ( Balances :: free_balance( ALICE ) , INITIAL_BALANCE ) ;
1930+
1931+ // do the transfer
1932+ assert_ok ! ( XcmPallet :: limited_reserve_transfer_assets(
1933+ RuntimeOrigin :: signed( ALICE ) ,
1934+ Box :: new( dest. into( ) ) ,
1935+ Box :: new( beneficiary. into( ) ) ,
1936+ Box :: new( assets. into( ) ) ,
1937+ fee_index as u32 ,
1938+ Unlimited ,
1939+ ) ) ;
1940+ assert ! ( matches!(
1941+ last_event( ) ,
1942+ RuntimeEvent :: XcmPallet ( crate :: Event :: Attempted { outcome: Outcome :: Complete ( _) } )
1943+ ) ) ;
1944+ // Alice native asset untouched
1945+ assert_eq ! ( Balances :: free_balance( ALICE ) , INITIAL_BALANCE ) ;
1946+ // Alice spent USDT for fees
1947+ assert_eq ! (
1948+ Assets :: balance( usdt_id_multilocation, ALICE ) ,
1949+ usdt_initial_local_amount - FEE_AMOUNT
1950+ ) ;
1951+ // Alice transferred BLA
1952+ assert_eq ! (
1953+ Assets :: balance( foreign_asset_id_multilocation, ALICE ) ,
1954+ foreign_asset_initial_amount - SEND_AMOUNT
1955+ ) ;
1956+ // Verify balances of USDT reserve parachain
1957+ assert_eq ! ( Balances :: free_balance( usdt_chain_sovereign_account. clone( ) ) , INITIAL_BALANCE ) ;
1958+ assert_eq ! ( Assets :: balance( usdt_id_multilocation, usdt_chain_sovereign_account) , 0 ) ;
1959+ // Verify balances of transferred-asset reserve parachain
1960+ assert_eq ! ( Balances :: free_balance( reserve_sovereign_account. clone( ) ) , INITIAL_BALANCE ) ;
1961+ assert_eq ! ( Assets :: balance( foreign_asset_id_multilocation, reserve_sovereign_account) , 0 ) ;
1962+ // Verify total and active issuance of USDT have decreased (teleported)
1963+ assert_eq ! (
1964+ Assets :: total_issuance( usdt_id_multilocation) ,
1965+ usdt_initial_local_amount - FEE_AMOUNT
1966+ ) ;
1967+ assert_eq ! (
1968+ Assets :: active_issuance( usdt_id_multilocation) ,
1969+ usdt_initial_local_amount - FEE_AMOUNT
1970+ ) ;
1971+ // Verify total and active issuance of foreign BLA asset have decreased (reserve-based
1972+ // (local-instance) asset was burned)
1973+ assert_eq ! (
1974+ Assets :: total_issuance( foreign_asset_id_multilocation) ,
1975+ foreign_asset_initial_amount - SEND_AMOUNT
1976+ ) ;
1977+ assert_eq ! (
1978+ Assets :: active_issuance( foreign_asset_id_multilocation) ,
1979+ foreign_asset_initial_amount - SEND_AMOUNT
1980+ ) ;
1981+
1982+ // Verify sent XCM program
1983+ assert_eq ! (
1984+ sent_xcm( ) ,
1985+ vec![
1986+ (
1987+ // first message is to prefund fees on `reserve`
1988+ reserve_location,
1989+ // fees are teleported to reserve chain
1990+ Xcm ( vec![
1991+ ReceiveTeleportedAsset ( expected_fee_on_reserve. clone( ) . into( ) ) ,
1992+ ClearOrigin ,
1993+ buy_limited_execution( expected_fee_on_reserve. clone( ) , Unlimited ) ,
1994+ DepositAsset {
1995+ assets: AllCounted ( 1 ) . into( ) ,
1996+ beneficiary: expected_beneficiary_on_reserve
1997+ } ,
1998+ ] )
1999+ ) ,
2000+ (
2001+ // second message is to prefund fees on `dest`
2002+ dest,
2003+ // fees are teleported to destination chain
2004+ Xcm ( vec![
2005+ ReceiveTeleportedAsset ( expected_fee. clone( ) . into( ) ) ,
2006+ ClearOrigin ,
2007+ buy_limited_execution( expected_fee. clone( ) , Unlimited ) ,
2008+ DepositAsset { assets: AllCounted ( 1 ) . into( ) , beneficiary } ,
2009+ ] )
2010+ ) ,
2011+ (
2012+ // third message is to transfer/deposit foreign assets on `dest` by going
2013+ // through `reserve` while paying using prefunded (teleported above) fees
2014+ reserve_location,
2015+ Xcm ( vec![
2016+ WithdrawAsset ( expected_asset_on_reserve. into( ) ) ,
2017+ ClearOrigin ,
2018+ buy_limited_execution( expected_fee_on_reserve, Unlimited ) ,
2019+ DepositReserveAsset {
2020+ assets: Wild ( AllCounted ( 1 ) ) ,
2021+ // final destination is `dest` as seen by `reserve`
2022+ dest: expected_dest_on_reserve,
2023+ // message sent onward to final `dest` to deposit/prefund fees
2024+ xcm: Xcm ( vec![
2025+ buy_limited_execution( expected_fee, Unlimited ) ,
2026+ DepositAsset { assets: AllCounted ( 1 ) . into( ) , beneficiary }
2027+ ] )
2028+ }
2029+ ] )
2030+ )
2031+ ]
2032+ ) ;
2033+ let versioned_sent = VersionedXcm :: from ( sent_xcm ( ) . into_iter ( ) . next ( ) . unwrap ( ) . 1 ) ;
2034+ let _check_v2_ok: xcm:: v2:: Xcm < ( ) > = versioned_sent. try_into ( ) . unwrap ( ) ;
2035+ } ) ;
18242036}
18252037
18262038/// Test local execution of XCM
0 commit comments