Skip to content

Commit d1ab01b

Browse files
authored
Merge pull request #4905 from namada-net/mergify/bp/maint-201.0/pr-4790
Frontend MASP sustainability fee (backport #4790)
2 parents a33d557 + a7b976b commit d1ab01b

File tree

11 files changed

+1356
-45
lines changed

11 files changed

+1356
-45
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Added support for MASP frontend providers sustainability fees.
2+
([\#4790](https://github.com/anoma/namada/pull/4790))

.github/workflows/scripts/e2e.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"e2e::eth_bridge_tests::everything": 4,
3+
"e2e::ibc_tests::frontend_sus_fee": 350,
34
"e2e::ibc_tests::ibc_transfers": 414,
45
"e2e::ibc_tests::ibc_nft_transfers": 224,
56
"e2e::ibc_tests::pgf_over_ibc": 415,

crates/apps_lib/src/cli.rs

Lines changed: 125 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,9 @@ pub mod cmds {
318318
Self::parse_with_ctx(matches, TxShieldingTransfer);
319319
let tx_unshielding_transfer =
320320
Self::parse_with_ctx(matches, TxUnshieldingTransfer);
321-
let tx_ibc_transfer = Self::parse_with_ctx(matches, TxIbcTransfer);
321+
let tx_ibc_transfer = Self::parse_with_ctx(matches, |cmd| {
322+
TxIbcTransfer(Box::new(cmd))
323+
});
322324
let tx_osmosis_swap = Self::parse_with_ctx(matches, |cmd| {
323325
TxOsmosisSwap(Box::new(cmd))
324326
});
@@ -507,7 +509,7 @@ pub mod cmds {
507509
TxShieldedTransfer(TxShieldedTransfer),
508510
TxShieldingTransfer(TxShieldingTransfer),
509511
TxUnshieldingTransfer(TxUnshieldingTransfer),
510-
TxIbcTransfer(TxIbcTransfer),
512+
TxIbcTransfer(Box<TxIbcTransfer>),
511513
TxOsmosisSwap(Box<TxOsmosisSwap>),
512514
QueryResult(QueryResult),
513515
TxUpdateAccount(TxUpdateAccount),
@@ -3691,6 +3693,14 @@ pub mod args {
36913693
pub const TARGET: Arg<WalletAddress> = arg("target");
36923694
pub const TARGET_OPT: ArgOpt<WalletAddress> = arg_opt("target");
36933695
pub const TEMPLATES_PATH: Arg<PathBuf> = arg("templates-path");
3696+
// WARNING: use only for testing purposes, MASP frontend fees don't make
3697+
// sense when operating from the CLI
3698+
pub const __TEST_FRONTEND_SUS_FEE: ArgOpt<WalletTransferTarget> =
3699+
arg_opt("test-frontend-sus-fee");
3700+
// WARNING: use only for testing purposes, MASP frontend fees don't make
3701+
// sense when operating from the CLI
3702+
pub const __TEST_FRONTEND_SUS_FEE_IBC: ArgOpt<WalletPaymentAddr> =
3703+
arg_opt("test-frontend-sus-fee-ibc");
36943704
pub const TIMEOUT_HEIGHT: ArgOpt<u64> = arg_opt("timeout-height");
36953705
pub const TIMEOUT_SEC_OFFSET: ArgOpt<u64> = arg_opt("timeout-sec-offset");
36963706
pub const TM_ADDRESS_OPT: ArgOpt<String> = arg_opt("tm-address");
@@ -4928,11 +4938,11 @@ pub mod args {
49284938
ctx: &mut Context,
49294939
) -> Result<TxShieldingTransfer<SdkTypes>, Self::Error> {
49304940
let tx = self.tx.to_sdk(ctx)?;
4931-
let mut data = vec![];
4941+
let mut sources = vec![];
49324942
let chain_ctx = ctx.borrow_mut_chain_or_exit();
49334943

49344944
for transfer_data in self.sources {
4935-
data.push(TxTransparentSource {
4945+
sources.push(TxTransparentSource {
49364946
source: chain_ctx.get(&transfer_data.source),
49374947
token: chain_ctx.get(&transfer_data.token),
49384948
amount: transfer_data.amount,
@@ -4947,12 +4957,17 @@ pub mod args {
49474957
amount: transfer_data.amount,
49484958
});
49494959
}
4960+
let frontend_sus_fee =
4961+
self.frontend_sus_fee.map(|(target, percentage)| {
4962+
(chain_ctx.get(&target), percentage)
4963+
});
49504964

49514965
Ok(TxShieldingTransfer::<SdkTypes> {
49524966
tx,
4953-
sources: data,
4967+
sources,
49544968
targets,
49554969
tx_code_path: self.tx_code_path.to_path_buf(),
4970+
frontend_sus_fee,
49564971
})
49574972
}
49584973
}
@@ -4963,24 +4978,31 @@ pub mod args {
49634978
let source = SOURCE.parse(matches);
49644979
let target = PAYMENT_ADDRESS_TARGET.parse(matches);
49654980
let token = TOKEN.parse(matches);
4966-
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));
4981+
let raw_amount = AMOUNT.parse(matches);
4982+
let amount = InputAmount::Unvalidated(raw_amount);
49674983
let tx_code_path = PathBuf::from(TX_TRANSFER_WASM);
4968-
let data = vec![TxTransparentSource {
4969-
source,
4984+
let sources = vec![TxTransparentSource {
4985+
source: source.clone(),
49704986
token: token.clone(),
49714987
amount,
49724988
}];
49734989
let targets = vec![TxShieldedTarget {
49744990
target,
4975-
token,
4991+
token: token.clone(),
49764992
amount,
49774993
}];
4994+
let frontend_sus_fee =
4995+
__TEST_FRONTEND_SUS_FEE.parse(matches).map(|target| {
4996+
// Take a constant fee of 10% on top of the input amount
4997+
(target, Dec::new(1, 1).unwrap())
4998+
});
49784999

49795000
Self {
49805001
tx,
4981-
sources: data,
5002+
sources,
49825003
targets,
49835004
tx_code_path,
5005+
frontend_sus_fee,
49845006
}
49855007
}
49865008

@@ -5001,6 +5023,15 @@ pub mod args {
50015023
.def()
50025024
.help(wrap!("The amount to transfer in decimal.")),
50035025
)
5026+
.arg(
5027+
__TEST_FRONTEND_SUS_FEE
5028+
.def()
5029+
.help(wrap!(
5030+
"The optional address of the frontend provider \
5031+
that will take the masp sustainability fee."
5032+
))
5033+
.hide(true),
5034+
)
50045035
}
50055036
}
50065037

@@ -5033,6 +5064,12 @@ pub mod args {
50335064
amount: transfer_data.amount,
50345065
});
50355066
}
5067+
5068+
let frontend_sus_fee =
5069+
self.frontend_sus_fee.map(|(target, percentage)| {
5070+
(chain_ctx.get(&target), percentage)
5071+
});
5072+
50365073
let gas_spending_key =
50375074
self.gas_spending_key.map(|key| chain_ctx.get_cached(&key));
50385075

@@ -5042,6 +5079,7 @@ pub mod args {
50425079
gas_spending_key,
50435080
sources,
50445081
tx_code_path: self.tx_code_path.to_path_buf(),
5082+
frontend_sus_fee,
50455083
})
50465084
}
50475085
}
@@ -5052,26 +5090,34 @@ pub mod args {
50525090
let source = SPENDING_KEY_SOURCE.parse(matches);
50535091
let target = TARGET.parse(matches);
50545092
let token = TOKEN.parse(matches);
5055-
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));
5093+
let raw_amount = AMOUNT.parse(matches);
5094+
let amount = InputAmount::Unvalidated(raw_amount);
50565095
let tx_code_path = PathBuf::from(TX_TRANSFER_WASM);
5057-
let data = vec![TxTransparentTarget {
5058-
target,
5096+
let targets = vec![TxTransparentTarget {
5097+
target: target.clone(),
50595098
token: token.clone(),
50605099
amount,
50615100
}];
50625101
let sources = vec![TxShieldedSource {
5063-
source,
5064-
token,
5102+
source: source.clone(),
5103+
token: token.clone(),
50655104
amount,
50665105
}];
50675106
let gas_spending_key = GAS_SPENDING_KEY.parse(matches);
50685107

5108+
let frontend_sus_fee =
5109+
__TEST_FRONTEND_SUS_FEE.parse(matches).map(|target| {
5110+
// Take a constant fee of 10% on top of the input amount
5111+
(target, Dec::new(1, 1).unwrap())
5112+
});
5113+
50695114
Self {
50705115
tx,
50715116
sources,
5072-
targets: data,
5117+
targets,
50735118
gas_spending_key,
50745119
tx_code_path,
5120+
frontend_sus_fee,
50755121
}
50765122
}
50775123

@@ -5098,6 +5144,15 @@ pub mod args {
50985144
payment. When not provided the source spending key will \
50995145
be used."
51005146
)))
5147+
.arg(
5148+
__TEST_FRONTEND_SUS_FEE
5149+
.def()
5150+
.help(wrap!(
5151+
"The optional address of the frontend provider \
5152+
that will take the masp sustainability fee."
5153+
))
5154+
.hide(true),
5155+
)
51015156
}
51025157
}
51035158

@@ -5112,6 +5167,10 @@ pub mod args {
51125167
let chain_ctx = ctx.borrow_mut_chain_or_exit();
51135168
let gas_spending_key =
51145169
self.gas_spending_key.map(|key| chain_ctx.get_cached(&key));
5170+
let frontend_sus_fee =
5171+
self.frontend_sus_fee.map(|(target, percentage)| {
5172+
(chain_ctx.get(&target), percentage)
5173+
});
51155174

51165175
Ok(TxIbcTransfer::<SdkTypes> {
51175176
tx,
@@ -5128,6 +5187,7 @@ pub mod args {
51285187
ibc_memo: self.ibc_memo,
51295188
gas_spending_key,
51305189
tx_code_path: self.tx_code_path.to_path_buf(),
5190+
frontend_sus_fee,
51315191
})
51325192
}
51335193
}
@@ -5138,7 +5198,9 @@ pub mod args {
51385198
let source = TRANSFER_SOURCE.parse(matches);
51395199
let receiver = RECEIVER.parse(matches);
51405200
let token = TOKEN.parse(matches);
5141-
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));
5201+
5202+
let raw_amount = AMOUNT.parse(matches);
5203+
let amount = InputAmount::Unvalidated(raw_amount);
51425204
let port_id = PORT_ID.parse(matches);
51435205
let channel_id = CHANNEL_ID.parse(matches);
51445206
let timeout_height = TIMEOUT_HEIGHT.parse(matches);
@@ -5154,6 +5216,12 @@ pub mod args {
51545216
let ibc_memo = IBC_MEMO.parse(matches);
51555217
let gas_spending_key = GAS_SPENDING_KEY.parse(matches);
51565218
let tx_code_path = PathBuf::from(TX_IBC_WASM);
5219+
let frontend_sus_fee =
5220+
__TEST_FRONTEND_SUS_FEE.parse(matches).map(|target| {
5221+
// Take a constant fee of 10% on top of the input amount
5222+
(target, Dec::new(1, 1).unwrap())
5223+
});
5224+
51575225
Self {
51585226
tx,
51595227
source,
@@ -5169,6 +5237,7 @@ pub mod args {
51695237
ibc_memo,
51705238
gas_spending_key,
51715239
tx_code_path,
5240+
frontend_sus_fee,
51725241
}
51735242
}
51745243

@@ -5218,6 +5287,15 @@ pub mod args {
52185287
payment (if this is a shielded action). When not \
52195288
provided the source spending key will be used."
52205289
)))
5290+
.arg(
5291+
__TEST_FRONTEND_SUS_FEE
5292+
.def()
5293+
.help(wrap!(
5294+
"The optional address of the frontend provider \
5295+
that will take the masp sustainability fee."
5296+
))
5297+
.hide(true),
5298+
)
52215299
}
52225300
}
52235301

@@ -5244,6 +5322,7 @@ pub mod args {
52445322
route: self.route,
52455323
osmosis_lcd_rpc: self.osmosis_lcd_rpc,
52465324
osmosis_sqs_rpc: self.osmosis_sqs_rpc,
5325+
frontend_sus_fee: None,
52475326
})
52485327
}
52495328
}
@@ -5296,6 +5375,7 @@ pub mod args {
52965375
route,
52975376
osmosis_lcd_rpc,
52985377
osmosis_sqs_rpc,
5378+
frontend_sus_fee: None,
52995379
}
53005380
}
53015381

@@ -7210,6 +7290,9 @@ pub mod args {
72107290
) -> Result<GenIbcShieldingTransfer<SdkTypes>, Self::Error> {
72117291
let query = self.query.to_sdk(ctx)?;
72127292
let chain_ctx = ctx.borrow_chain_or_exit();
7293+
let frontend_sus_fee = self
7294+
.frontend_sus_fee
7295+
.map(|(target, amount)| (chain_ctx.get(&target), amount));
72137296

72147297
Ok(GenIbcShieldingTransfer::<SdkTypes> {
72157298
query,
@@ -7231,6 +7314,7 @@ pub mod args {
72317314
IbcShieldingTransferAsset::Address(chain_ctx.get(&addr))
72327315
}
72337316
},
7317+
frontend_sus_fee,
72347318
})
72357319
}
72367320
}
@@ -7239,9 +7323,10 @@ pub mod args {
72397323
fn parse(matches: &ArgMatches) -> Self {
72407324
let query = Query::parse(matches);
72417325
let output_folder = OUTPUT_FOLDER_PATH.parse(matches);
7242-
let target = TRANSFER_TARGET.parse(matches);
7326+
let target = PAYMENT_ADDRESS_TARGET.parse(matches);
72437327
let token = TOKEN_STR.parse(matches);
7244-
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));
7328+
let raw_amount = AMOUNT.parse(matches);
7329+
let amount = InputAmount::Unvalidated(raw_amount);
72457330
let expiration = EXPIRATION_OPT.parse(matches);
72467331
let port_id = PORT_ID.parse(matches);
72477332
let channel_id = CHANNEL_ID.parse(matches);
@@ -7254,6 +7339,12 @@ pub mod args {
72547339
None => TxExpiration::Default,
72557340
}
72567341
};
7342+
let frontend_sus_fee = __TEST_FRONTEND_SUS_FEE_IBC
7343+
.parse(matches)
7344+
.map(|payment_address| {
7345+
// Take a constant fee of 10% on top of the input amount
7346+
(payment_address, Dec::new(1, 1).unwrap())
7347+
});
72577348

72587349
Self {
72597350
query,
@@ -7266,6 +7357,7 @@ pub mod args {
72667357
channel_id,
72677358
token,
72687359
},
7360+
frontend_sus_fee,
72697361
}
72707362
}
72717363

@@ -7274,7 +7366,11 @@ pub mod args {
72747366
.arg(OUTPUT_FOLDER_PATH.def().help(wrap!(
72757367
"The output folder path where the artifact will be stored."
72767368
)))
7277-
.arg(TRANSFER_TARGET.def().help(wrap!("The target address.")))
7369+
.arg(
7370+
PAYMENT_ADDRESS_TARGET
7371+
.def()
7372+
.help(wrap!("The shielded target account address.")),
7373+
)
72787374
.arg(TOKEN.def().help(wrap!("The transfer token.")))
72797375
.arg(
72807376
AMOUNT
@@ -7307,6 +7403,15 @@ pub mod args {
73077403
.arg(CHANNEL_ID.def().help(wrap!(
73087404
"The channel ID via which the token is received."
73097405
)))
7406+
.arg(
7407+
__TEST_FRONTEND_SUS_FEE_IBC
7408+
.def()
7409+
.help(wrap!(
7410+
"The optional address of the frontend provider \
7411+
that will take the masp sustainability fee."
7412+
))
7413+
.hide(true),
7414+
)
73107415
}
73117416
}
73127417

crates/apps_lib/src/cli/client.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ impl CliApi {
100100
let namada = ctx.to_sdk(client, io);
101101
tx::submit_unshielding_transfer(&namada, args).await?;
102102
}
103-
Sub::TxIbcTransfer(TxIbcTransfer(args)) => {
103+
Sub::TxIbcTransfer(args) => {
104+
let TxIbcTransfer(args) = *args;
104105
let chain_ctx = ctx.borrow_mut_chain_or_exit();
105106
let ledger_address =
106107
chain_ctx.get(&args.tx.ledger_address);

0 commit comments

Comments
 (0)