From e8f26e6748c537811342c4dd4b3837225db92a8b Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Thu, 5 Sep 2024 15:29:38 +0200 Subject: [PATCH] make register token relative --- bridges/snowbridge/pallets/system/src/lib.rs | 13 +- bridges/snowbridge/pallets/system/src/mock.rs | 6 +- .../snowbridge/pallets/system/src/tests.rs | 176 +++++++++++++++++- .../src/tests/snowbridge.rs | 8 +- .../src/bridge_to_ethereum_config.rs | 2 + .../src/bridge_to_ethereum_config.rs | 2 + 6 files changed, 200 insertions(+), 7 deletions(-) diff --git a/bridges/snowbridge/pallets/system/src/lib.rs b/bridges/snowbridge/pallets/system/src/lib.rs index 051e15c387ad..c0be7dcb6e03 100644 --- a/bridges/snowbridge/pallets/system/src/lib.rs +++ b/bridges/snowbridge/pallets/system/src/lib.rs @@ -173,6 +173,12 @@ pub mod pallet { type WeightInfo: WeightInfo; + /// This chain's Universal Location. + type UniversalLocation: Get; + + // The bridges configured Ethereum network with chain id. + type EthereumNetwork: Get; + #[cfg(feature = "runtime-benchmarks")] type Helper: BenchmarkHelper; } @@ -242,7 +248,6 @@ pub mod pallet { InvalidTokenTransferFees, InvalidPricingParameters, InvalidUpgradeParameters, - TokenExists, } /// The set of registered agents @@ -723,6 +728,12 @@ pub mod pallet { metadata: AssetMetadata, pays_fee: PaysFee, ) -> Result<(), DispatchError> { + let bridge_location = Location::new(2, [GlobalConsensus(T::EthereumNetwork::get())]); + let mut location = location.clone(); + location + .reanchor(&bridge_location, &T::UniversalLocation::get()) + .map_err(|_| Error::::LocationConversionFailed)?; + // Record the token id or fail if it has already been created let token_id = TokenIdOf::convert_location(&location) .ok_or(Error::::LocationConversionFailed)?; diff --git a/bridges/snowbridge/pallets/system/src/mock.rs b/bridges/snowbridge/pallets/system/src/mock.rs index 98bd3da9ab27..d8c905449d9a 100644 --- a/bridges/snowbridge/pallets/system/src/mock.rs +++ b/bridges/snowbridge/pallets/system/src/mock.rs @@ -170,6 +170,7 @@ parameter_types! { pub const RelayLocation: Location = Location::parent(); pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(1013)].into(); + pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 }; } pub const DOT: u128 = 10_000_000_000; @@ -177,8 +178,8 @@ pub const DOT: u128 = 10_000_000_000; parameter_types! { pub TreasuryAccount: AccountId = PalletId(*b"py/trsry").into_account_truncating(); pub Fee: u64 = 1000; - pub const RococoNetwork: NetworkId = NetworkId::Rococo; pub const InitialFunding: u128 = 1_000_000_000_000; + pub BridgeHubParaId: ParaId = ParaId::new(1002); pub AssetHubParaId: ParaId = ParaId::new(1000); pub TestParaId: u32 = 2000; pub Parameters: PricingParameters = PricingParameters { @@ -188,7 +189,6 @@ parameter_types! { multiplier: FixedU128::from_rational(4, 3) }; pub const InboundDeliveryCost: u128 = 1_000_000_000; - } #[cfg(feature = "runtime-benchmarks")] @@ -208,6 +208,8 @@ impl crate::Config for Test { type DefaultPricingParameters = Parameters; type WeightInfo = (); type InboundDeliveryCost = InboundDeliveryCost; + type UniversalLocation = UniversalLocation; + type EthereumNetwork = EthereumNetwork; #[cfg(feature = "runtime-benchmarks")] type Helper = (); } diff --git a/bridges/snowbridge/pallets/system/src/tests.rs b/bridges/snowbridge/pallets/system/src/tests.rs index ba016b9b4854..0745f435ba05 100644 --- a/bridges/snowbridge/pallets/system/src/tests.rs +++ b/bridges/snowbridge/pallets/system/src/tests.rs @@ -549,7 +549,7 @@ fn charge_fee_for_create_agent() { assert_ok!(EthereumSystem::create_agent(origin.clone())); let fee_charged = initial_sovereign_balance - Balances::balance(&sovereign_account); - assert_ok!(EthereumSystem::create_channel(origin, OperatingMode::Normal,)); + assert_ok!(EthereumSystem::create_channel(origin, OperatingMode::Normal)); // assert sovereign_balance decreased by (fee.base_fee + fee.delivery_fee) let message = Message { @@ -631,3 +631,177 @@ fn no_genesis_build_is_uninitialized() { assert!(!EthereumSystem::is_initialized(), "Ethereum initialized."); }); } + +#[test] +fn register_token_with_root_yeilds_success() { + new_test_ext(true).execute_with(|| { + let origin = RuntimeOrigin::root(); + let location = Location::new(1, []); + let versioned_location: Box = Box::new(location.clone().into()); + let asset_metadata = AssetMetadata { + decimals: 10, + name: b"Dot".to_vec().try_into().unwrap(), + symbol: b"DOT".to_vec().try_into().unwrap(), + }; + + assert_ok!(EthereumSystem::register_token(origin, versioned_location, asset_metadata)); + + let expected_token_id = + hex!("03b6054d0c576dd8391e34e1609cf398f68050c23009d19ce93c000922bcd852").into(); + let expected_location = Location::new(1, [GlobalConsensus(Kusama)]); + + System::assert_last_event(RuntimeEvent::EthereumSystem( + crate::Event::::RegisterToken { + location: expected_location.into(), + foreign_token_id: expected_token_id, + }, + )); + }); +} + +#[test] +fn register_token_with_relative_address_reanchors_to_ethereum_and_succeeds() { + new_test_ext(true).execute_with(|| { + let origin = RuntimeOrigin::root(); + let location = Location::new(1, []); + let versioned_location: Box = Box::new(location.clone().into()); + let asset_metadata = AssetMetadata { + decimals: 10, + name: b"Dot".to_vec().try_into().unwrap(), + symbol: b"DOT".to_vec().try_into().unwrap(), + }; + + assert_ok!(EthereumSystem::register_token(origin, versioned_location, asset_metadata)); + + let expected_token_id = + hex!("03b6054d0c576dd8391e34e1609cf398f68050c23009d19ce93c000922bcd852").into(); + let expected_location = Location::new(1, [GlobalConsensus(Kusama)]); + + System::assert_last_event(RuntimeEvent::EthereumSystem( + crate::Event::::RegisterToken { + location: expected_location.into(), + foreign_token_id: expected_token_id, + }, + )); + }); +} + +#[test] +fn register_token_with_complex_location_simplifies_and_succeeds() { + new_test_ext(true).execute_with(|| { + let origin = RuntimeOrigin::root(); + let location = Location::new(2, [GlobalConsensus(Kusama)]); + let versioned_location: Box = Box::new(location.clone().into()); + let asset_metadata = AssetMetadata { + decimals: 10, + name: b"Dot".to_vec().try_into().unwrap(), + symbol: b"DOT".to_vec().try_into().unwrap(), + }; + + assert_ok!(EthereumSystem::register_token(origin, versioned_location, asset_metadata)); + + let expected_token_id = + hex!("03b6054d0c576dd8391e34e1609cf398f68050c23009d19ce93c000922bcd852").into(); + let expected_location = Location::new(1, [GlobalConsensus(Kusama)]); + + System::assert_last_event(RuntimeEvent::EthereumSystem( + crate::Event::::RegisterToken { + location: expected_location.into(), + foreign_token_id: expected_token_id, + }, + )); + }); +} + +#[test] +fn register_token_with_doubled_bridged_polkadot_location_succeeds() { + new_test_ext(true).execute_with(|| { + let origin = RuntimeOrigin::root(); + let location = Location::new(2, [GlobalConsensus(Rococo)]); + let versioned_location: Box = Box::new(location.clone().into()); + let asset_metadata = AssetMetadata { + decimals: 10, + name: b"Dot".to_vec().try_into().unwrap(), + symbol: b"DOT".to_vec().try_into().unwrap(), + }; + + assert_ok!(EthereumSystem::register_token(origin, versioned_location, asset_metadata)); + + let expected_token_id = + hex!("62e8f33b7fb0e7e2d2276564061a2f3c7bcb612e733b8bf5733ea16cee0ecba6").into(); + let expected_location = Location::new(1, [GlobalConsensus(Rococo)]); + + System::assert_last_event(RuntimeEvent::EthereumSystem( + crate::Event::::RegisterToken { + location: expected_location.into(), + foreign_token_id: expected_token_id, + }, + )); + }); +} + +#[test] +fn register_token_with_ethereum_address_reanchors_to_relative_and_fails() { + new_test_ext(true).execute_with(|| { + let origin = RuntimeOrigin::root(); + let location = Location::new(2, [GlobalConsensus(Ethereum { chain_id: 11155111 })]); + let versioned_location: Box = Box::new(location.clone().into()); + let asset_metadata = AssetMetadata { + decimals: 10, + name: b"Dot".to_vec().try_into().unwrap(), + symbol: b"DOT".to_vec().try_into().unwrap(), + }; + + assert_noop!( + EthereumSystem::register_token(origin, versioned_location, asset_metadata), + Error::::LocationConversionFailed + ); + }); +} + +#[test] +fn register_token_with_double_bridged_ethereum_address_succeeds() { + new_test_ext(true).execute_with(|| { + let origin = RuntimeOrigin::root(); + const NETWORK: NetworkId = Ethereum { chain_id: 1 }; + let location = Location::new(2, [GlobalConsensus(NETWORK)]); + let versioned_location: Box = Box::new(location.clone().into()); + let asset_metadata = AssetMetadata { + decimals: 10, + name: b"Dot".to_vec().try_into().unwrap(), + symbol: b"DOT".to_vec().try_into().unwrap(), + }; + + assert_ok!(EthereumSystem::register_token(origin, versioned_location, asset_metadata)); + + let expected_token_id: H256 = + hex!("37fd94739deb1c2a8929b45a4f70ffcb52de8b54791609ee13ee0a2b33730269").into(); + let expected_location = Location::new(1, [GlobalConsensus(NETWORK)]); + + System::assert_last_event(RuntimeEvent::EthereumSystem( + crate::Event::::RegisterToken { + location: expected_location.into(), + foreign_token_id: expected_token_id, + }, + )); + }); +} + +#[test] +fn register_token_with_signed_yeilds_bad_origin() { + new_test_ext(true).execute_with(|| { + let origin = RuntimeOrigin::signed([14; 32].into()); + let location = Location::new(1, [Parachain(2000)]); + let versioned_location: Box = Box::new(location.clone().into()); + let asset_metadata = AssetMetadata { + decimals: 10, + name: b"Dot".to_vec().try_into().unwrap(), + symbol: b"DOT".to_vec().try_into().unwrap(), + }; + + assert_noop!( + EthereumSystem::register_token(origin, versioned_location, asset_metadata), + BadOrigin + ); + }); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs index dd2d1197db76..53e9cf149c4b 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs @@ -294,9 +294,11 @@ fn transfer_relay_token() { ); BridgeHubWestend::fund_accounts(vec![(assethub_sovereign.clone(), INITIAL_FUND)]); - let asset_id: Location = Location { parents: 1, interior: [GlobalConsensus(Westend)].into() }; + let asset_id: Location = Location { parents: 1, interior: [].into() }; + let expected_asset_id: Location = + Location { parents: 1, interior: [GlobalConsensus(Westend)].into() }; - let token_id = TokenIdOf::convert_location(&asset_id).unwrap(); + let expected_token_id = TokenIdOf::convert_location(&expected_asset_id).unwrap(); let ethereum_sovereign: AccountId = GlobalConsensusEthereumConvertsFor::<[u8; 32]>::convert_location(&Location::new( @@ -388,7 +390,7 @@ fn transfer_relay_token() { let message = VersionedMessage::V1(MessageV1 { chain_id: CHAIN_ID, command: Command::SendNativeToken { - token_id, + token_id: expected_token_id, destination: Destination::AccountId32 { id: AssetHubWestendReceiver::get().into() }, amount: TOKEN_AMOUNT, fee: XCM_FEE, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_ethereum_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_ethereum_config.rs index 26857d262c20..1e096f19ef80 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_ethereum_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_ethereum_config.rs @@ -188,6 +188,8 @@ impl snowbridge_pallet_system::Config for Runtime { type Helper = (); type DefaultPricingParameters = Parameters; type InboundDeliveryCost = EthereumInboundQueue; + type UniversalLocation = UniversalLocation; + type EthereumNetwork = EthereumNetwork; } #[cfg(feature = "runtime-benchmarks")] diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs index 621d39af5af0..fee9f9a2f610 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs @@ -188,6 +188,8 @@ impl snowbridge_pallet_system::Config for Runtime { type Helper = (); type DefaultPricingParameters = Parameters; type InboundDeliveryCost = EthereumInboundQueue; + type UniversalLocation = UniversalLocation; + type EthereumNetwork = EthereumNetwork; } #[cfg(feature = "runtime-benchmarks")]