Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 34ad3ab

Browse files
apopiakshawntabriziAndronik Ordian
authored
Fix TransactAsset Implementation (#3345)
* convert local AssetNotFound errors into XcmError::AssetNotFound aims allow the tuple implementation of TransactAsset to iterate properly * add more XcmError descriptions * adjust the rest of the TransactAsset tuple implementation to the behavior of can_check_in * fix copy paste errors * keep iterating tuple on Unimplemented error in TransactAsset * add tests for tuple implementation of TransactAsset * Update xcm/src/v0/traits.rs Co-authored-by: Andronik Ordian <[email protected]> Co-authored-by: Shawn Tabrizi <[email protected]> Co-authored-by: Andronik Ordian <[email protected]>
1 parent 5dac532 commit 34ad3ab

File tree

4 files changed

+120
-10
lines changed

4 files changed

+120
-10
lines changed

xcm/src/v0/traits.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@ use super::{MultiLocation, Xcm};
2424
#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug)]
2525
pub enum Error {
2626
Undefined,
27+
/// An arithmetic overflow happened.
2728
Overflow,
2829
/// The operation is intentionally unsupported.
2930
Unimplemented,
3031
UnhandledXcmVersion,
32+
/// The implementation does not handle a given XCM.
3133
UnhandledXcmMessage,
34+
/// The implementation does not handle an effect present in an XCM.
3235
UnhandledEffect,
3336
EscalationOfPrivilege,
3437
UntrustedReserveLocation,
@@ -43,10 +46,15 @@ pub enum Error {
4346
FailedToDecode,
4447
BadOrigin,
4548
ExceedsMaxMessageSize,
49+
/// An asset transaction (like withdraw or deposit) failed.
50+
/// See implementers of the `TransactAsset` trait for sources.
51+
/// Causes can include type conversion failures between id or balance types.
4652
FailedToTransactAsset(#[codec(skip)] &'static str),
4753
/// Execution of the XCM would potentially result in a greater weight used than the pre-specified
4854
/// weight limit. The amount that is potentially required is the parameter.
4955
WeightLimitReached(Weight),
56+
/// An asset wildcard was passed where it was not expected (e.g. as the asset to withdraw in a
57+
/// `WithdrawAsset` XCM).
5058
Wildcard,
5159
/// The case where an XCM message has specified a optional weight limit and the weight required for
5260
/// processing is too great.

xcm/xcm-builder/src/currency_adapter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl From<Error> for XcmError {
3737
fn from(e: Error) -> Self {
3838
use XcmError::FailedToTransactAsset;
3939
match e {
40-
Error::AssetNotFound => FailedToTransactAsset("AssetNotFound"),
40+
Error::AssetNotFound => XcmError::AssetNotFound,
4141
Error::AccountIdConversionFailed => FailedToTransactAsset("AccountIdConversionFailed"),
4242
Error::AmountToBalanceConversionFailed => FailedToTransactAsset("AmountToBalanceConversionFailed"),
4343
}

xcm/xcm-executor/src/traits/matches_fungibles.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl From<Error> for XcmError {
3333
fn from(e: Error) -> Self {
3434
use XcmError::FailedToTransactAsset;
3535
match e {
36-
Error::AssetNotFound => FailedToTransactAsset("AssetNotFound"),
36+
Error::AssetNotFound => XcmError::AssetNotFound,
3737
Error::AccountIdConversionFailed => FailedToTransactAsset("AccountIdConversionFailed"),
3838
Error::AmountToBalanceConversionFailed => FailedToTransactAsset("AmountToBalanceConversionFailed"),
3939
Error::AssetIdConversionFailed => FailedToTransactAsset("AssetIdConversionFailed"),

xcm/xcm-executor/src/traits/transact_asset.rs

Lines changed: 110 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl TransactAsset for Tuple {
103103
fn can_check_in(origin: &MultiLocation, what: &MultiAsset) -> XcmResult {
104104
for_tuples!( #(
105105
match Tuple::can_check_in(origin, what) {
106-
Err(XcmError::AssetNotFound) => (),
106+
Err(XcmError::AssetNotFound | XcmError::Unimplemented) => (),
107107
r => return r,
108108
}
109109
)* );
@@ -130,33 +130,42 @@ impl TransactAsset for Tuple {
130130

131131
fn deposit_asset(what: &MultiAsset, who: &MultiLocation) -> XcmResult {
132132
for_tuples!( #(
133-
match Tuple::deposit_asset(what, who) { o @ Ok(_) => return o, _ => () }
133+
match Tuple::deposit_asset(what, who) {
134+
Err(XcmError::AssetNotFound | XcmError::Unimplemented) => (),
135+
r => return r,
136+
}
134137
)* );
135138
log::trace!(
136139
target: "xcm::TransactAsset::deposit_asset",
137140
"did not deposit asset: what: {:?}, who: {:?}",
138141
what,
139142
who,
140143
);
141-
Err(XcmError::Unimplemented)
144+
Err(XcmError::AssetNotFound)
142145
}
143146

144147
fn withdraw_asset(what: &MultiAsset, who: &MultiLocation) -> Result<Assets, XcmError> {
145148
for_tuples!( #(
146-
match Tuple::withdraw_asset(what, who) { o @ Ok(_) => return o, _ => () }
149+
match Tuple::withdraw_asset(what, who) {
150+
Err(XcmError::AssetNotFound | XcmError::Unimplemented) => (),
151+
r => return r,
152+
}
147153
)* );
148154
log::trace!(
149155
target: "xcm::TransactAsset::withdraw_asset",
150156
"did not withdraw asset: what: {:?}, who: {:?}",
151-
what,
157+
what,
152158
who,
153159
);
154-
Err(XcmError::Unimplemented)
160+
Err(XcmError::AssetNotFound)
155161
}
156162

157163
fn transfer_asset(what: &MultiAsset, from: &MultiLocation, to: &MultiLocation) -> Result<Assets, XcmError> {
158164
for_tuples!( #(
159-
match Tuple::transfer_asset(what, from, to) { o @ Ok(_) => return o, _ => () }
165+
match Tuple::transfer_asset(what, from, to) {
166+
Err(XcmError::AssetNotFound | XcmError::Unimplemented) => (),
167+
r => return r,
168+
}
160169
)* );
161170
log::trace!(
162171
target: "xcm::TransactAsset::transfer_asset",
@@ -165,6 +174,99 @@ impl TransactAsset for Tuple {
165174
from,
166175
to,
167176
);
168-
Err(XcmError::Unimplemented)
177+
Err(XcmError::AssetNotFound)
178+
}
179+
}
180+
181+
#[cfg(test)]
182+
mod tests {
183+
use super::*;
184+
185+
pub struct UnimplementedTransactor;
186+
impl TransactAsset for UnimplementedTransactor {}
187+
188+
pub struct NotFoundTransactor;
189+
impl TransactAsset for NotFoundTransactor {
190+
fn can_check_in(_origin: &MultiLocation, _what: &MultiAsset) -> XcmResult {
191+
Err(XcmError::AssetNotFound)
192+
}
193+
194+
fn deposit_asset(_what: &MultiAsset, _who: &MultiLocation) -> XcmResult {
195+
Err(XcmError::AssetNotFound)
196+
}
197+
198+
fn withdraw_asset(_what: &MultiAsset, _who: &MultiLocation) -> Result<Assets, XcmError> {
199+
Err(XcmError::AssetNotFound)
200+
}
201+
202+
fn transfer_asset(_what: &MultiAsset, _from: &MultiLocation, _to: &MultiLocation) -> Result<Assets, XcmError> {
203+
Err(XcmError::AssetNotFound)
204+
}
205+
}
206+
207+
pub struct OverflowTransactor;
208+
impl TransactAsset for OverflowTransactor {
209+
fn can_check_in(_origin: &MultiLocation, _what: &MultiAsset) -> XcmResult {
210+
Err(XcmError::Overflow)
211+
}
212+
213+
fn deposit_asset(_what: &MultiAsset, _who: &MultiLocation) -> XcmResult {
214+
Err(XcmError::Overflow)
215+
}
216+
217+
fn withdraw_asset(_what: &MultiAsset, _who: &MultiLocation) -> Result<Assets, XcmError> {
218+
Err(XcmError::Overflow)
219+
}
220+
221+
fn transfer_asset(_what: &MultiAsset, _from: &MultiLocation, _to: &MultiLocation) -> Result<Assets, XcmError> {
222+
Err(XcmError::Overflow)
223+
}
224+
}
225+
226+
pub struct SuccessfulTransactor;
227+
impl TransactAsset for SuccessfulTransactor {
228+
fn can_check_in(_origin: &MultiLocation, _what: &MultiAsset) -> XcmResult {
229+
Ok(())
230+
}
231+
232+
fn deposit_asset(_what: &MultiAsset, _who: &MultiLocation) -> XcmResult {
233+
Ok(())
234+
}
235+
236+
fn withdraw_asset(_what: &MultiAsset, _who: &MultiLocation) -> Result<Assets, XcmError> {
237+
Ok(Assets::default())
238+
}
239+
240+
fn transfer_asset(_what: &MultiAsset, _from: &MultiLocation, _to: &MultiLocation) -> Result<Assets, XcmError> {
241+
Ok(Assets::default())
242+
}
243+
}
244+
245+
#[test]
246+
fn defaults_to_asset_not_found() {
247+
type MultiTransactor = (UnimplementedTransactor, NotFoundTransactor, UnimplementedTransactor);
248+
249+
assert_eq!(MultiTransactor::deposit_asset(&MultiAsset::All, &MultiLocation::Null), Err(XcmError::AssetNotFound));
250+
}
251+
252+
#[test]
253+
fn unimplemented_and_not_found_continue_iteration() {
254+
type MultiTransactor = (UnimplementedTransactor, NotFoundTransactor, SuccessfulTransactor);
255+
256+
assert_eq!(MultiTransactor::deposit_asset(&MultiAsset::All, &MultiLocation::Null), Ok(()));
257+
}
258+
259+
#[test]
260+
fn unexpected_error_stops_iteration() {
261+
type MultiTransactor = (OverflowTransactor, SuccessfulTransactor);
262+
263+
assert_eq!(MultiTransactor::deposit_asset(&MultiAsset::All, &MultiLocation::Null), Err(XcmError::Overflow));
264+
}
265+
266+
#[test]
267+
fn success_stops_iteration() {
268+
type MultiTransactor = (SuccessfulTransactor, OverflowTransactor);
269+
270+
assert_eq!(MultiTransactor::deposit_asset(&MultiAsset::All, &MultiLocation::Null), Ok(()));
169271
}
170272
}

0 commit comments

Comments
 (0)