diff --git a/.circleci/config.yml b/.circleci/config.yml index 0175fab180..421d8ae534 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -472,7 +472,7 @@ jobs: working_directory: ./integration - run: name: Run polymesh-api integration tests against the previous version. - command: cargo nextest run --locked + command: cargo nextest run --features previous_release --locked working_directory: ./integration no_output_timeout: 30m - run: @@ -486,7 +486,7 @@ jobs: working_directory: ./integration - run: name: Run polymesh-api integration tests against the upgraded chain. - command: cargo nextest run --locked + command: cargo nextest run --features current_release --locked working_directory: ./integration no_output_timeout: 30m integration-test: diff --git a/integration/Cargo.toml b/integration/Cargo.toml index 62f3a48985..dbe964b37e 100644 --- a/integration/Cargo.toml +++ b/integration/Cargo.toml @@ -15,6 +15,9 @@ edition = "2021" [features] default = [] +previous_release = [] +current_release = [] + [dependencies] anyhow = "1" log = "0.4" diff --git a/integration/tests/multisig_permissions.rs b/integration/tests/multisig_permissions.rs index 732883962b..e81ec58024 100644 --- a/integration/tests/multisig_permissions.rs +++ b/integration/tests/multisig_permissions.rs @@ -712,3 +712,123 @@ async fn ms_remove_payer_via_payer() -> Result<()> { Ok(()) } + +/// Test transaction fees for a MS when the primary key of the paying DID has a subsidy. +#[tokio::test] +#[cfg(feature = "current_release")] +async fn ms_subsidy_payer() -> Result<()> { + let mut tester = PolymeshTester::new().await?; + let users = tester + .users(&["MultiSigSubsidyPayer", "Subsidizer"]) + .await?; + let mut did = users[0].clone(); + let mut subsidizer = users[1].clone(); + + // Create a subsidy for the paying did's primary key. + // The subsidy is created with a POLYX limit of 10. + let mut res = tester + .api + .call() + .relayer() + .set_paying_key(did.primary_key.account(), 10 * ONE_POLYX)? + .execute(&mut subsidizer) + .await?; + // Get the authorization ID of the new subsidy. + let auth_id = get_auth_id(&mut res) + .await? + .expect("Missing SetPayingKey auth id"); + + // Accept the subsidy authorization as the primary key. + let mut res = tester + .api + .call() + .relayer() + .accept_paying_key(auth_id)? + .execute(&mut did.primary_key) + .await?; + res.ok().await?; + + // Use the primary key of did1 to create a MS and join it do did1 as a secondary key. + let whole = PermissionsBuilder::whole(); + let mut ms = MuliSigState::create_and_join_creator( + &mut tester, + &did.primary_key, + 3, + 2, + false, + Some(whole.into()), + ) + .await?; + + // Should be able to execute proposals now. + let remark_call = tester.api.call().system().remark(vec![])?; + let mut res = ms.run_proposal(remark_call).await?; + res.ok().await?; + + Ok(()) +} + +/// Test subsidy transaction fees for a MS. +#[tokio::test] +#[cfg(feature = "current_release")] +async fn ms_subsidy() -> Result<()> { + let mut tester = PolymeshTester::new().await?; + let users = tester.users(&["MultiSigSubsidy", "Subsidizer"]).await?; + let did = users[0].clone(); + let mut subsidizer = users[1].clone(); + + // Use the primary key of did1 to create a MS and join it do did1 as a secondary key. + let whole = PermissionsBuilder::whole(); + let mut ms = MuliSigState::create_and_join_creator( + &mut tester, + &did.primary_key, + 3, + 2, + false, + Some(whole.into()), + ) + .await?; + + // Create a subsidy for the MS with a POLYX limit of 0. + let mut res = tester + .api + .call() + .relayer() + .set_paying_key(ms.account.clone(), 0)? + .execute(&mut subsidizer) + .await?; + // Get the authorization ID of the new subsidy. + let auth_id = get_auth_id(&mut res) + .await? + .expect("Missing SetPayingKey auth id"); + + // Accept the subsidy authorization as the MS. + let accept_subsidy_call = tester.api.call().relayer().accept_paying_key(auth_id)?; + let mut res = ms.run_proposal(accept_subsidy_call).await?; + res.ok().await?; + + // Remove the paying did via the payer. + let mut res = ms.remove_payer_via_payer().await?; + res.wait_in_block().await?; + + // The MS shouldn't be able to pay tx fees anymore, because the subsidy is zero. + let remark_call = tester.api.call().system().remark(vec![])?; + let res = ms.run_proposal(remark_call).await; + assert!(res.is_err()); + + // The subsidizer increases the POLYX limit to 10. + tester + .api + .call() + .relayer() + .update_polyx_limit(ms.account.clone(), 10 * ONE_POLYX)? + .execute(&mut subsidizer) + .await?; + + // Should be able to execute proposals now. + let remark_call = tester.api.call().system().remark(vec![])?; + let mut res = ms.run_proposal(remark_call).await?; + res.ok().await?; + + Ok(()) +} diff --git a/pallets/runtime/common/src/runtime.rs b/pallets/runtime/common/src/runtime.rs index f0e08fcfc1..d45844d19e 100644 --- a/pallets/runtime/common/src/runtime.rs +++ b/pallets/runtime/common/src/runtime.rs @@ -332,6 +332,7 @@ macro_rules! misc_pallet_impls { RuntimeCall::Identity(_) => true, RuntimeCall::Nft(_) => true, RuntimeCall::Staking(_) => true, + RuntimeCall::MultiSig(_) => true, // Allow non-nested batch calls. RuntimeCall::Utility(call) if nested == false => match call { // Limit batch size to 7. diff --git a/polymesh_schema.json b/polymesh_schema.json index 7250ef6f52..4a767a3efa 100644 --- a/polymesh_schema.json +++ b/polymesh_schema.json @@ -391,7 +391,8 @@ "authorization_data": "AuthorizationData", "authorized_by": "IdentityId", "expiry": "Option", - "auth_id": "u64" + "auth_id": "u64", + "count": "u32" }, "AuthorizationData": { "_enum": {