From 9fa14b549e47f2251887f7ea47b4dd4329e14378 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 22 Dec 2024 18:02:54 +0200 Subject: [PATCH 1/3] payable attribute - allow `#[payable]` --- framework/derive/src/parse/attributes/payable_attr.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/derive/src/parse/attributes/payable_attr.rs b/framework/derive/src/parse/attributes/payable_attr.rs index 73293719d0..bdc38d8800 100644 --- a/framework/derive/src/parse/attributes/payable_attr.rs +++ b/framework/derive/src/parse/attributes/payable_attr.rs @@ -27,7 +27,8 @@ impl PayableAttribute { fn extract_token_identifier(attr: &syn::Attribute) -> Option { match attr.meta.clone() { syn::Meta::Path(_) => { - panic!("attribute needs 1 string argument: Replace with #[payable(\"*\")] or #[payable(\"EGLD\")]") + // #[payable] + Some("*".to_owned()) }, syn::Meta::List(list) => { let mut iter = list.tokens.into_iter(); From 0fad48a14d429b93223b36e854409d7fbcb4715f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 22 Dec 2024 18:03:38 +0200 Subject: [PATCH 2/3] payable attribute - `#[payable]` in examples --- .../bonding-curve-contract/src/bonding_curve_contract.rs | 6 +++--- .../examples/crowdfunding-esdt/src/crowdfunding_esdt.rs | 2 +- contracts/examples/digital-cash/src/pay_fee_and_fund.rs | 4 ++-- contracts/examples/digital-cash/src/signature_operations.rs | 2 +- .../esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs | 2 +- contracts/examples/fractional-nfts/src/fractional_nfts.rs | 4 ++-- contracts/examples/lottery-esdt/src/lottery.rs | 2 +- contracts/examples/multisig/src/multisig.rs | 2 +- contracts/examples/nft-minter/src/nft_module.rs | 2 +- contracts/examples/nft-subscription/src/lib.rs | 6 +++--- contracts/examples/order-book/pair/src/lib.rs | 4 ++-- .../rewards-distribution/src/rewards_distribution.rs | 4 ++-- contracts/examples/seed-nft-minter/src/nft_module.rs | 2 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/contracts/examples/bonding-curve-contract/src/bonding_curve_contract.rs b/contracts/examples/bonding-curve-contract/src/bonding_curve_contract.rs index 6ab29068d3..490eb4bb42 100644 --- a/contracts/examples/bonding-curve-contract/src/bonding_curve_contract.rs +++ b/contracts/examples/bonding-curve-contract/src/bonding_curve_contract.rs @@ -20,13 +20,13 @@ pub trait Contract: #[init] fn init(&self) {} - #[payable("*")] + #[payable] #[endpoint(sellToken)] fn sell_token_endpoint(&self) { self.sell_token::>(); } - #[payable("*")] + #[payable] #[endpoint(buyToken)] fn buy_token_endpoint( &self, @@ -42,7 +42,7 @@ pub trait Contract: } #[endpoint(deposit)] - #[payable("*")] + #[payable] fn deposit_endpoint(&self, payment_token: OptionalValue) { self.deposit::>(payment_token) } diff --git a/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs b/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs index d47e256f08..1c7e3acebd 100644 --- a/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs +++ b/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs @@ -29,7 +29,7 @@ pub trait Crowdfunding { } #[endpoint] - #[payable("*")] + #[payable] fn fund(&self) { let (token, _, payment) = self.call_value().egld_or_single_esdt().into_tuple(); diff --git a/contracts/examples/digital-cash/src/pay_fee_and_fund.rs b/contracts/examples/digital-cash/src/pay_fee_and_fund.rs index edff9df18e..3815ea38cc 100644 --- a/contracts/examples/digital-cash/src/pay_fee_and_fund.rs +++ b/contracts/examples/digital-cash/src/pay_fee_and_fund.rs @@ -5,7 +5,7 @@ use crate::{constants::*, helpers, storage}; #[multiversx_sc::module] pub trait PayFeeAndFund: storage::StorageModule + helpers::HelpersModule { #[endpoint(payFeeAndFundESDT)] - #[payable("*")] + #[payable] fn pay_fee_and_fund_esdt(&self, address: ManagedAddress, valability: u64) { let mut payments = self.call_value().all_esdt_transfers().clone(); let fee = EgldOrEsdtTokenPayment::from(payments.get(0).clone()); @@ -32,7 +32,7 @@ pub trait PayFeeAndFund: storage::StorageModule + helpers::HelpersModule { } #[endpoint] - #[payable("*")] + #[payable] fn fund(&self, address: ManagedAddress, valability: u64) { require!(!self.deposit(&address).is_empty(), FEES_NOT_COVERED_ERR_MSG); let deposit_mapper = self.deposit(&address).get(); diff --git a/contracts/examples/digital-cash/src/signature_operations.rs b/contracts/examples/digital-cash/src/signature_operations.rs index 9c68951f05..2c31701a00 100644 --- a/contracts/examples/digital-cash/src/signature_operations.rs +++ b/contracts/examples/digital-cash/src/signature_operations.rs @@ -92,7 +92,7 @@ pub trait SignatureOperationsModule: storage::StorageModule + helpers::HelpersMo } #[endpoint] - #[payable("*")] + #[payable] fn forward( &self, address: ManagedAddress, diff --git a/contracts/examples/esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs b/contracts/examples/esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs index 5967c8feaa..b885ec371f 100644 --- a/contracts/examples/esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs +++ b/contracts/examples/esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs @@ -43,7 +43,7 @@ pub trait EsdtTransferWithFee { self.tx().to(ToCaller).payment(fees).transfer(); } - #[payable("*")] + #[payable] #[endpoint] fn transfer(&self, address: ManagedAddress) { require!( diff --git a/contracts/examples/fractional-nfts/src/fractional_nfts.rs b/contracts/examples/fractional-nfts/src/fractional_nfts.rs index 2b9844449a..fea51e2431 100644 --- a/contracts/examples/fractional-nfts/src/fractional_nfts.rs +++ b/contracts/examples/fractional-nfts/src/fractional_nfts.rs @@ -47,7 +47,7 @@ pub trait FractionalNfts: default_issue_callbacks::DefaultIssueCallbacksModule { .async_call_and_exit(); } - #[payable("*")] + #[payable] #[endpoint(fractionalizeNFT)] fn fractionalize_nft( &self, @@ -97,7 +97,7 @@ pub trait FractionalNfts: default_issue_callbacks::DefaultIssueCallbacksModule { .transfer(); } - #[payable("*")] + #[payable] #[endpoint(unFractionalizeNFT)] fn unfractionalize_nft(&self) { let fractional_payment = self.call_value().single_esdt(); diff --git a/contracts/examples/lottery-esdt/src/lottery.rs b/contracts/examples/lottery-esdt/src/lottery.rs index 5c573ef651..026710d5c7 100644 --- a/contracts/examples/lottery-esdt/src/lottery.rs +++ b/contracts/examples/lottery-esdt/src/lottery.rs @@ -166,7 +166,7 @@ pub trait Lottery { } #[endpoint] - #[payable("*")] + #[payable] fn buy_ticket(&self, lottery_name: ManagedBuffer) { let (token_identifier, payment) = self.call_value().egld_or_single_fungible_esdt(); diff --git a/contracts/examples/multisig/src/multisig.rs b/contracts/examples/multisig/src/multisig.rs index d1e177df02..4c32bb8f0a 100644 --- a/contracts/examples/multisig/src/multisig.rs +++ b/contracts/examples/multisig/src/multisig.rs @@ -49,7 +49,7 @@ pub trait Multisig: } /// Allows the contract to receive funds even if it is marked as unpayable in the protocol. - #[payable("*")] + #[payable] #[endpoint] fn deposit(&self) {} diff --git a/contracts/examples/nft-minter/src/nft_module.rs b/contracts/examples/nft-minter/src/nft_module.rs index ab4fd22504..6629c22d11 100644 --- a/contracts/examples/nft-minter/src/nft_module.rs +++ b/contracts/examples/nft-minter/src/nft_module.rs @@ -59,7 +59,7 @@ pub trait NftModule { // endpoints - #[payable("*")] + #[payable] #[endpoint(buyNft)] fn buy_nft(&self, nft_nonce: u64) { let payment = self.call_value().egld_or_single_esdt(); diff --git a/contracts/examples/nft-subscription/src/lib.rs b/contracts/examples/nft-subscription/src/lib.rs index 210a20020f..beca5ac5bf 100644 --- a/contracts/examples/nft-subscription/src/lib.rs +++ b/contracts/examples/nft-subscription/src/lib.rs @@ -46,7 +46,7 @@ pub trait NftSubscription: .transfer(); } - #[payable("*")] + #[payable] #[endpoint] fn update_attributes(&self, attributes: ManagedBuffer) { let payment = self.call_value().single_esdt(); @@ -65,7 +65,7 @@ pub trait NftSubscription: .transfer(); } - #[payable("*")] + #[payable] #[endpoint] fn renew(&self, duration: u64) { let payment = self.call_value().single_esdt(); @@ -84,7 +84,7 @@ pub trait NftSubscription: .transfer(); } - #[payable("*")] + #[payable] #[endpoint] fn cancel(&self) { let payment = self.call_value().single_esdt(); diff --git a/contracts/examples/order-book/pair/src/lib.rs b/contracts/examples/order-book/pair/src/lib.rs index 69e3a9f8c5..d1e8a2aa21 100644 --- a/contracts/examples/order-book/pair/src/lib.rs +++ b/contracts/examples/order-book/pair/src/lib.rs @@ -24,7 +24,7 @@ pub trait Pair: self.second_token_id().set_if_empty(&second_token_id); } - #[payable("*")] + #[payable] #[endpoint(createBuyOrder)] fn create_buy_order_endpoint(&self, params: OrderInputParams) { self.require_global_op_not_ongoing(); @@ -34,7 +34,7 @@ pub trait Pair: self.create_order(payment, params, common::OrderType::Buy); } - #[payable("*")] + #[payable] #[endpoint(createSellOrder)] fn create_sell_order_endpoint(&self, params: OrderInputParams) { self.require_global_op_not_ongoing(); diff --git a/contracts/examples/rewards-distribution/src/rewards_distribution.rs b/contracts/examples/rewards-distribution/src/rewards_distribution.rs index ecbf2b7d7c..48ba549a9e 100644 --- a/contracts/examples/rewards-distribution/src/rewards_distribution.rs +++ b/contracts/examples/rewards-distribution/src/rewards_distribution.rs @@ -57,7 +57,7 @@ pub trait RewardsDistribution: self.brackets().set(brackets); } - #[payable("*")] + #[payable] #[endpoint(depositRoyalties)] fn deposit_royalties(&self) { let payment = self.call_value().egld_or_single_esdt(); @@ -247,7 +247,7 @@ pub trait RewardsDistribution: ); } - #[payable("*")] + #[payable] #[endpoint(claimRewards)] fn claim_rewards( &self, diff --git a/contracts/examples/seed-nft-minter/src/nft_module.rs b/contracts/examples/seed-nft-minter/src/nft_module.rs index 3580ecedb5..8c271e5686 100644 --- a/contracts/examples/seed-nft-minter/src/nft_module.rs +++ b/contracts/examples/seed-nft-minter/src/nft_module.rs @@ -38,7 +38,7 @@ pub trait NftModule: // endpoints - #[payable("*")] + #[payable] #[endpoint(buyNft)] fn buy_nft(&self, nft_nonce: u64) { let payment = self.call_value().egld_or_single_esdt(); From 1e0d401281a34464b2b86e82786f3c3cf629f0f7 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 22 Dec 2024 18:10:09 +0200 Subject: [PATCH 3/3] payable attribute - refactoring --- .../derive/src/parse/attributes/payable_attr.rs | 8 ++++---- framework/derive/src/parse/method_parse.rs | 4 ++-- framework/derive/src/parse/payable_parse.rs | 14 +++++--------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/framework/derive/src/parse/attributes/payable_attr.rs b/framework/derive/src/parse/attributes/payable_attr.rs index bdc38d8800..6c0241848f 100644 --- a/framework/derive/src/parse/attributes/payable_attr.rs +++ b/framework/derive/src/parse/attributes/payable_attr.rs @@ -3,7 +3,7 @@ use crate::parse::attributes::util::{clean_string, is_first_char_numeric}; use super::attr_names::*; pub struct PayableAttribute { - pub identifier: Option, + pub identifier: String, } impl PayableAttribute { @@ -24,11 +24,11 @@ impl PayableAttribute { /// Current implementation only works with 1 token name. /// Might be extended in the future. -fn extract_token_identifier(attr: &syn::Attribute) -> Option { +fn extract_token_identifier(attr: &syn::Attribute) -> String { match attr.meta.clone() { syn::Meta::Path(_) => { // #[payable] - Some("*".to_owned()) + "*".to_owned() }, syn::Meta::List(list) => { let mut iter = list.tokens.into_iter(); @@ -61,7 +61,7 @@ fn extract_token_identifier(attr: &syn::Attribute) -> Option { iter.next().is_none(), "too many tokens in attribute argument" ); - Some(ticker) + ticker }, syn::Meta::NameValue(_) => panic!( "attribute can not be name value. attribute needs 1 string argument: \"*\" or \"EGLD\"" diff --git a/framework/derive/src/parse/method_parse.rs b/framework/derive/src/parse/method_parse.rs index e299912cdd..b5fa90b54d 100644 --- a/framework/derive/src/parse/method_parse.rs +++ b/framework/derive/src/parse/method_parse.rs @@ -16,7 +16,7 @@ use super::{ process_title_attribute, process_upgrade_attribute, process_view_attribute, }; pub struct MethodAttributesPass1 { - pub method_name: String, + pub _method_name: String, pub payable: MethodPayableMetadata, pub only_owner: bool, pub only_admin: bool, @@ -34,7 +34,7 @@ pub fn process_method(m: &syn::TraitItemFn, trait_attributes: &TraitProperties) }; let mut first_pass_data = MethodAttributesPass1 { - method_name: m.sig.ident.to_string(), + _method_name: m.sig.ident.to_string(), payable: MethodPayableMetadata::NotPayable, only_owner: trait_attributes.only_owner, only_admin: trait_attributes.only_admin, diff --git a/framework/derive/src/parse/payable_parse.rs b/framework/derive/src/parse/payable_parse.rs index 91deba4509..99e6c8e17b 100644 --- a/framework/derive/src/parse/payable_parse.rs +++ b/framework/derive/src/parse/payable_parse.rs @@ -5,15 +5,11 @@ pub fn process_payable_attribute( attr: &syn::Attribute, pass_1_data: &mut MethodAttributesPass1, ) -> bool { - PayableAttribute::parse(attr).map(|payable_attr| { - if let Some(identifier) = payable_attr.identifier { - pass_1_data.payable = parse_payable_identifier(identifier.as_str()); - } else { - panic!( - "Endpoint `payable` attribute requires one argument. Replace with `#[payable(\"*\")]` or `#[payable(\"EGLD\")]`. Method name: {}", - &pass_1_data.method_name); - } - }).is_some() + PayableAttribute::parse(attr) + .map(|payable_attr| { + pass_1_data.payable = parse_payable_identifier(&payable_attr.identifier); + }) + .is_some() } fn parse_payable_identifier(identifier: &str) -> MethodPayableMetadata {