Skip to content

Commit

Permalink
add native support for transfer_with_fee
Browse files Browse the repository at this point in the history
  • Loading branch information
gitofdeepanshu committed Oct 11, 2023
1 parent fb9a30e commit 7990808
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 17 deletions.
44 changes: 31 additions & 13 deletions precompiles/xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,36 +582,54 @@ where

// Read call arguments
let currency_address = input.read::<Address>()?;
let amount_of_tokens = input
let amount_of_tokens: u128 = input
.read::<U256>()?
.try_into()
.map_err(|_| revert("error converting amount_of_tokens, maybe value too large"))?;
let fee = input
let fee: u128 = input
.read::<U256>()?
.try_into()
.map_err(|_| revert("can't convert fee"))?;

let destination = input.read::<MultiLocation>()?;
let weight = input.read::<WeightV2>()?;

let asset_id = Runtime::address_to_asset_id(currency_address.into())
.ok_or(revert("Failed to resolve fee asset id from address"))?;
let dest_weight_limit = if weight.is_zero() {
WeightLimit::Unlimited
} else {
WeightLimit::Limited(weight.get_weight())
};

log::trace!(target: "xcm-precompile::transfer_with_fee", "Raw arguments: currency_address: {:?}, amount_of_tokens: {:?}, destination: {:?}, \
weight: {:?}, calculated asset_id: {:?}",
currency_address, amount_of_tokens, destination, weight, asset_id);
let call = {
if currency_address == Address::from(NATIVE_ADDRESS) {
log::trace!(target: "xcm-precompile::transfer_with_fee", "Raw arguments: currency_address: {:?} (this is native token), amount_of_tokens: {:?}, destination: {:?}, \
weight: {:?}, fee {:?}",
currency_address, amount_of_tokens, destination, weight, fee );

let call = orml_xtokens::Call::<Runtime>::transfer_with_fee {
currency_id: asset_id.into(),
amount: amount_of_tokens,
fee,
dest: Box::new(VersionedMultiLocation::V3(destination)),
dest_weight_limit,
orml_xtokens::Call::<Runtime>::transfer_multiasset_with_fee {
asset: Box::new(VersionedMultiAsset::V3(
(MultiLocation::here(), amount_of_tokens).into(),
)),
fee: Box::new(VersionedMultiAsset::V3((MultiLocation::here(), fee).into())),
dest: Box::new(VersionedMultiLocation::V3(destination)),
dest_weight_limit,
}
} else {
let asset_id = Runtime::address_to_asset_id(currency_address.into())
.ok_or(revert("Failed to resolve fee asset id from address"))?;

log::trace!(target: "xcm-precompile::transfer_with_fee", "Raw arguments: currency_address: {:?}, amount_of_tokens: {:?}, destination: {:?}, \
weight: {:?}, calculated asset_id: {:?}, fee: {:?}",
currency_address, amount_of_tokens, destination, weight, asset_id, fee);

orml_xtokens::Call::<Runtime>::transfer_with_fee {
currency_id: asset_id.into(),
amount: amount_of_tokens.into(),
fee: fee.into(),
dest: Box::new(VersionedMultiLocation::V3(destination)),
dest_weight_limit,
}
}
};

let origin = Some(Runtime::AddressMapping::into_account_id(
Expand Down
105 changes: 101 additions & 4 deletions precompiles/xcm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,59 @@ mod xcm_old_interface_test {
.expect_no_logs()
.execute_reverts(|output| {
let error_string = String::from_utf8_lossy(output);
if error_string.contains("AssetIndexNonExistent") {
return true;
}
false
error_string.contains("AssetIndexNonExistent")
});
});
}

#[test]
fn sanity_checks_for_parameters() {
ExtBuilder::default().build().execute_with(|| {
// parachain id resolution failure
precompiles()
.prepare_test(
TestAccount::Alice,
PRECOMPILE_ADDRESS,
EvmDataWriter::new_with_selector(Action::AssetsWithdrawNative)
.write(vec![Address::from(Runtime::asset_id_to_address(1u128))])
.write(vec![U256::from(42000u64)])
.write(H256::repeat_byte(0xF1))
.write(false)
.write(U256::from(u64::MAX)) // parachain id should be u32
.write(U256::from(0_u64))
.build(),
)
.expect_no_logs()
.execute_reverts(|output| {
output == b"error converting parachain_id, maybe value too large"
});

// more than 2 assets can not be sent
precompiles()
.prepare_test(
TestAccount::Alice,
PRECOMPILE_ADDRESS,
EvmDataWriter::new_with_selector(Action::AssetsWithdrawNative)
.write(vec![
Address::from(H160::repeat_byte(0xF1)),
Address::from(H160::repeat_byte(0xF2)),
Address::from(H160::repeat_byte(0xF3)),
])
.write(vec![
U256::from(42000u64),
U256::from(42000u64),
U256::from(42000u64),
])
.write(H256::repeat_byte(0xF1))
.write(false)
.write(U256::from(1_u64)) // parachain id should be
.write(U256::from(0_u64))
.build(),
)
.expect_no_logs()
.execute_reverts(|output| {
let error_string = String::from_utf8_lossy(output);
error_string.contains("Array has more than max items allowed")
});
});
}
Expand Down Expand Up @@ -523,6 +572,54 @@ mod xcm_new_interface_test {
});
}

#[test]
fn xtokens_transfer_with_fee_works_for_native_asset() {
let weight = WeightV2::from(3_000_000_000u64, 1024);
let parent_destination = MultiLocation {
parents: 1,
interior: Junctions::X1(Junction::AccountId32 {
network: None,
id: [1u8; 32],
}),
};

ExtBuilder::default().build().execute_with(|| {
// sending native token to relay
precompiles()
.prepare_test(
TestAccount::Alice,
PRECOMPILE_ADDRESS,
EvmDataWriter::new_with_selector(Action::XtokensTransferWithFee)
.write(Address::from(NATIVE_ADDRESS)) // zero address by convention
.write(U256::from(42000u64))
.write(U256::from(50))
.write(parent_destination)
.write(weight.clone())
.build(),
)
.expect_no_logs()
.execute_returns(EvmDataWriter::new().write(true).build());

let expected_asset: MultiAsset = MultiAsset {
id: AssetId::Concrete(Here.into()),
fun: Fungibility::Fungible(42000),
};
let expected_fee: MultiAsset = MultiAsset {
id: AssetId::Concrete(Here.into()),
fun: Fungibility::Fungible(50),
};
let expected: crate::mock::RuntimeEvent =
mock::RuntimeEvent::Xtokens(XtokensEvent::TransferredMultiAssets {
sender: TestAccount::Alice.into(),
assets: vec![expected_asset.clone(), expected_fee.clone()].into(),
fee: expected_fee,
dest: parent_destination,
})
.into();
assert!(events().contains(&expected));
});
}

#[test]
fn transfer_multiasset_works() {
let weight = WeightV2::from(3_000_000_000u64, 1024);
Expand Down

0 comments on commit 7990808

Please sign in to comment.