Skip to content

Commit

Permalink
Merge pull request #1241 from multiversx/allow-multiple-var-args
Browse files Browse the repository at this point in the history
(dis)allow multiple var args
  • Loading branch information
andrei-marinica authored Oct 13, 2023
2 parents 43cdfd4 + 729f2ac commit fbd7cf4
Show file tree
Hide file tree
Showing 24 changed files with 176 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use random::*;

#[multiversx_sc::contract]
pub trait KittyOwnership {
#[allow_multiple_var_args]
#[init]
fn init(
&self,
Expand Down
3 changes: 3 additions & 0 deletions contracts/examples/lottery-esdt/src/lottery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub trait Lottery {
#[init]
fn init(&self) {}

#[allow_multiple_var_args]
#[endpoint]
fn start(
&self,
Expand All @@ -43,6 +44,7 @@ pub trait Lottery {
);
}

#[allow_multiple_var_args]
#[endpoint(createLotteryPool)]
fn create_lottery_pool(
&self,
Expand All @@ -69,6 +71,7 @@ pub trait Lottery {
);
}

#[allow_multiple_var_args]
#[allow(clippy::too_many_arguments)]
fn start_lottery(
&self,
Expand Down
2 changes: 2 additions & 0 deletions contracts/examples/multisig/src/multisig_propose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub trait MultisigProposeModule: crate::multisig_state::MultisigStateModule {
/// Can send EGLD without calling anything.
/// Can call smart contract endpoints directly.
/// Doesn't really work with builtin functions.
#[allow_multiple_var_args]
#[endpoint(proposeTransferExecute)]
fn propose_transfer_execute(
&self,
Expand All @@ -92,6 +93,7 @@ pub trait MultisigProposeModule: crate::multisig_state::MultisigStateModule {
/// Can use ESDTTransfer/ESDTNFTTransfer/MultiESDTTransfer to send tokens, while also optionally calling endpoints.
/// Works well with builtin functions.
/// Cannot simply send EGLD directly without calling anything.
#[allow_multiple_var_args]
#[endpoint(proposeAsyncCall)]
fn propose_async_call(
&self,
Expand Down
1 change: 1 addition & 0 deletions contracts/examples/nft-minter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub trait NftMinter: nft_module::NftModule {
#[init]
fn init(&self) {}

#[allow_multiple_var_args]
#[allow(clippy::too_many_arguments)]
#[allow(clippy::redundant_closure)]
#[only_owner]
Expand Down
1 change: 1 addition & 0 deletions contracts/examples/ping-pong-egld/src/ping_pong.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub trait PingPong {
/// `duration_in_seconds` - how much time (in seconds) until contract expires.
/// `opt_activation_timestamp` - optionally specify the contract to only actvivate at a later date.
/// `max_funds` - optional funding cap, no more funds than this can be added to the contract.
#[allow_multiple_var_args]
#[init]
fn init(
&self,
Expand Down
1 change: 1 addition & 0 deletions contracts/examples/seed-nft-minter/src/seed_nft_minter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub trait SeedNftMinter:
self.init_distribution(distribution);
}

#[allow_multiple_var_args]
#[only_owner]
#[endpoint(createNft)]
fn create_nft(
Expand Down
1 change: 1 addition & 0 deletions contracts/feature-tests/basic-features/src/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub trait EchoTypes {
nz
}

#[allow_multiple_var_args]
#[view]
fn echo_some_args_ignore_others(
&self,
Expand Down
1 change: 1 addition & 0 deletions contracts/feature-tests/composability/vault/src/vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ pub trait Vault {
.unwrap_or_else(|_| sc_panic!("ESDT transfer failed"));
}

#[allow_multiple_var_args]
#[label("promises-endpoint")]
#[payable("*")]
#[endpoint]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub trait Lottery {
self.set_erc20_contract_address(&erc20_contract_address);
}

#[allow_multiple_var_args]
#[endpoint]
fn start(
&self,
Expand All @@ -45,6 +46,7 @@ pub trait Lottery {
)
}

#[allow_multiple_var_args]
#[endpoint(createLotteryPool)]
fn create_lottery_pool(
&self,
Expand All @@ -67,6 +69,7 @@ pub trait Lottery {
)
}

#[allow_multiple_var_args]
#[allow(clippy::too_many_arguments)]
fn start_lottery(
&self,
Expand Down
1 change: 1 addition & 0 deletions framework/base/src/abi/endpoint_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub struct EndpointAbi {
pub payable_in_tokens: &'static [&'static str],
pub inputs: Vec<InputAbi>,
pub outputs: OutputAbis,
pub allow_multiple_var_args: bool,
}

impl EndpointAbi {
Expand Down
1 change: 1 addition & 0 deletions framework/base/src/external_view_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ pub fn external_view_contract_constructor_abi() -> EndpointAbi {
multi_arg: false,
}].to_vec(),
outputs: OutputAbis::new(),
allow_multiple_var_args: false
}
}
5 changes: 5 additions & 0 deletions framework/derive/src/generate/abi_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fn generate_endpoint_snippet(
only_admin: bool,
mutability: EndpointMutabilityMetadata,
endpoint_type: EndpointTypeMetadata,
allow_multiple_var_args: bool,
) -> proc_macro2::TokenStream {
let endpoint_docs = &m.docs;
let rust_method_name = m.name.to_string();
Expand Down Expand Up @@ -65,6 +66,7 @@ fn generate_endpoint_snippet(
inputs: multiversx_sc::types::heap::Vec::new(),
outputs: multiversx_sc::types::heap::Vec::new(),
labels: &[ #(#label_names),* ],
allow_multiple_var_args: #allow_multiple_var_args,
};
#(#input_snippets)*
#output_snippet
Expand All @@ -84,6 +86,7 @@ fn generate_endpoint_snippets(contract: &ContractTrait) -> Vec<proc_macro2::Toke
false,
EndpointMutabilityMetadata::Mutable,
EndpointTypeMetadata::Init,
m.is_allow_multiple_var_args(),
);
Some(quote! {
#endpoint_def
Expand All @@ -98,6 +101,7 @@ fn generate_endpoint_snippets(contract: &ContractTrait) -> Vec<proc_macro2::Toke
endpoint_metadata.only_admin,
endpoint_metadata.mutability.clone(),
EndpointTypeMetadata::Endpoint,
endpoint_metadata.allow_multiple_var_args,
);
Some(quote! {
#endpoint_def
Expand All @@ -112,6 +116,7 @@ fn generate_endpoint_snippets(contract: &ContractTrait) -> Vec<proc_macro2::Toke
false,
EndpointMutabilityMetadata::Mutable,
EndpointTypeMetadata::PromisesCallback,
m.is_allow_multiple_var_args(),
);
Some(quote! {
#endpoint_def
Expand Down
1 change: 1 addition & 0 deletions framework/derive/src/model/argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ pub struct TraitProperties {
pub only_owner: bool,
pub only_admin: bool,
pub only_user_account: bool,
pub allow_multiple_var_args: bool,
}
3 changes: 3 additions & 0 deletions framework/derive/src/model/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::{EndpointMutabilityMetadata, MethodPayableMetadata};
#[derive(Clone, Debug)]
pub struct InitMetadata {
pub payable: MethodPayableMetadata,
pub allow_multiple_var_args: bool,
}

#[derive(Clone, Debug)]
Expand All @@ -13,11 +14,13 @@ pub struct EndpointMetadata {
pub only_admin: bool,
pub only_user_account: bool,
pub mutability: EndpointMutabilityMetadata,
pub allow_multiple_var_args: bool,
}

#[derive(Clone, Debug)]
pub struct CallbackMetadata {
pub callback_name: syn::Ident,
pub allow_multiple_var_args: bool,
}

/// Method visibility from the point of view of the smart contract
Expand Down
13 changes: 13 additions & 0 deletions framework/derive/src/model/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,17 @@ impl Method {
PublicRole::Private => MethodPayableMetadata::NotPayable,
}
}

pub fn is_allow_multiple_var_args(&self) -> bool {
match &self.public_role {
PublicRole::Init(init_metadata) => init_metadata.allow_multiple_var_args,
PublicRole::Endpoint(endpoint_metadata) => endpoint_metadata.allow_multiple_var_args,
PublicRole::Callback(callback_metadata)
| PublicRole::CallbackPromise(callback_metadata) => {
callback_metadata.allow_multiple_var_args
},
PublicRole::CallbackRaw => true,
PublicRole::Private => false,
}
}
}
1 change: 1 addition & 0 deletions framework/derive/src/parse/attributes/attr_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ pub(super) static ATTR_STORAGE_IS_EMPTY: &str = "storage_is_empty";
pub(super) static ATTR_STORAGE_CLEAR: &str = "storage_clear";
pub(super) static ATTR_PROXY: &str = "proxy";
pub(super) static ATTR_LABEL: &str = "label";
pub(super) static ATTR_ALLOW_MULTIPLE_VAR_ARGS: &str = "allow_multiple_var_args";
4 changes: 4 additions & 0 deletions framework/derive/src/parse/attributes/endpoint_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ pub fn is_proxy(attr: &syn::Attribute) -> bool {
is_attribute_with_no_args(attr, ATTR_PROXY)
}

pub fn is_allow_multiple_var_args(attr: &syn::Attribute) -> bool {
is_attribute_with_no_args(attr, ATTR_ALLOW_MULTIPLE_VAR_ARGS)
}

#[derive(Clone, Debug)]
pub struct EndpointAttribute {
pub endpoint_name: Option<syn::Ident>,
Expand Down
4 changes: 4 additions & 0 deletions framework/derive/src/parse/attributes/trait_argument_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ pub fn is_only_owner_prop(attr: &syn::Attribute) -> bool {
pub fn is_only_admin_prop(attr: &syn::Attribute) -> bool {
is_attribute_with_no_args(attr, PROP_ADMIN_OWNER)
}

pub fn is_allow_multiple_var_args_prop(attr: &syn::Attribute) -> bool {
is_attribute_with_no_args(attr, PROP_ALLOW_MULTIPLE_VAR_ARGS)
}
1 change: 1 addition & 0 deletions framework/derive/src/parse/attributes/trait_prop_names.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub(super) static PROP_ONLY_OWNER: &str = "only_owner";
pub(super) static PROP_ADMIN_OWNER: &str = "only_admin";
pub(super) static PROP_ALLOW_MULTIPLE_VAR_ARGS: &str = "allow_multiple_var_args";
24 changes: 21 additions & 3 deletions framework/derive/src/parse/endpoint_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::model::{

use super::{
attributes::{
is_callback_raw, is_init, is_only_admin, is_only_owner, is_only_user_account,
CallbackAttribute, EndpointAttribute, ExternalViewAttribute, LabelAttribute,
OutputNameAttribute, PromisesCallbackAttribute, ViewAttribute,
is_allow_multiple_var_args, is_callback_raw, is_init, is_only_admin, is_only_owner,
is_only_user_account, CallbackAttribute, EndpointAttribute, ExternalViewAttribute,
LabelAttribute, OutputNameAttribute, PromisesCallbackAttribute, ViewAttribute,
},
MethodAttributesPass1,
};
Expand All @@ -27,13 +27,26 @@ pub fn process_init_attribute(
check_single_role(&*method);
method.public_role = PublicRole::Init(InitMetadata {
payable: pass_1_data.payable.clone(),
allow_multiple_var_args: pass_1_data.allow_multiple_var_args,
});
true
} else {
false
}
}

pub fn process_allow_multiple_var_args_attribute(
attr: &syn::Attribute,
pass_1_data: &mut MethodAttributesPass1,
) -> bool {
let is_allow_multiple_var_args = is_allow_multiple_var_args(attr);
if is_allow_multiple_var_args {
pass_1_data.allow_multiple_var_args = true;
}

is_allow_multiple_var_args
}

pub fn process_only_owner_attribute(
attr: &syn::Attribute,
pass_1_data: &mut MethodAttributesPass1,
Expand Down Expand Up @@ -86,6 +99,7 @@ pub fn process_endpoint_attribute(
only_admin: pass_1_data.only_admin,
only_user_account: pass_1_data.only_user_account,
mutability: EndpointMutabilityMetadata::Mutable,
allow_multiple_var_args: pass_1_data.allow_multiple_var_args,
});
})
.is_some()
Expand All @@ -110,6 +124,7 @@ pub fn process_view_attribute(
only_admin: pass_1_data.only_admin,
only_user_account: pass_1_data.only_user_account,
mutability: EndpointMutabilityMetadata::Readonly,
allow_multiple_var_args: pass_1_data.allow_multiple_var_args,
});
})
.is_some()
Expand All @@ -134,6 +149,7 @@ pub fn process_external_view_attribute(
only_admin: pass_1_data.only_admin,
only_user_account: pass_1_data.only_user_account,
mutability: EndpointMutabilityMetadata::Readonly,
allow_multiple_var_args: pass_1_data.allow_multiple_var_args,
});
})
.is_some()
Expand All @@ -159,6 +175,7 @@ pub fn process_callback_attribute(attr: &syn::Attribute, method: &mut Method) ->
};
method.public_role = PublicRole::Callback(CallbackMetadata {
callback_name: callback_ident,
allow_multiple_var_args: method.is_allow_multiple_var_args(),
});
})
.is_some()
Expand All @@ -174,6 +191,7 @@ pub fn process_promises_callback_attribute(attr: &syn::Attribute, method: &mut M
};
method.public_role = PublicRole::CallbackPromise(CallbackMetadata {
callback_name: callback_ident,
allow_multiple_var_args: method.is_allow_multiple_var_args(),
});
})
.is_some()
Expand Down
14 changes: 9 additions & 5 deletions framework/derive/src/parse/method_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@ use super::{
process_storage_get_attribute, process_storage_is_empty_attribute,
process_storage_mapper_attribute, process_storage_set_attribute,
},
extract_method_args, process_callback_attribute, process_callback_raw_attribute,
process_endpoint_attribute, process_external_view_attribute, process_init_attribute,
process_label_names_attribute, process_only_admin_attribute, process_only_owner_attribute,
process_only_user_account_attribute, process_output_names_attribute, process_payable_attribute,
process_promises_callback_attribute, process_view_attribute,
extract_method_args, process_allow_multiple_var_args_attribute, process_callback_attribute,
process_callback_raw_attribute, process_endpoint_attribute, process_external_view_attribute,
process_init_attribute, process_label_names_attribute, process_only_admin_attribute,
process_only_owner_attribute, process_only_user_account_attribute,
process_output_names_attribute, process_payable_attribute, process_promises_callback_attribute,
process_view_attribute,
};
pub struct MethodAttributesPass1 {
pub method_name: String,
pub payable: MethodPayableMetadata,
pub only_owner: bool,
pub only_admin: bool,
pub only_user_account: bool,
pub allow_multiple_var_args: bool,
}

pub fn process_method(m: &syn::TraitItemMethod, trait_attributes: &TraitProperties) -> Method {
Expand All @@ -36,6 +38,7 @@ pub fn process_method(m: &syn::TraitItemMethod, trait_attributes: &TraitProperti
only_owner: trait_attributes.only_owner,
only_admin: trait_attributes.only_admin,
only_user_account: trait_attributes.only_user_account,
allow_multiple_var_args: trait_attributes.allow_multiple_var_args,
};
let mut first_pass_unprocessed_attributes = Vec::new();

Expand Down Expand Up @@ -90,6 +93,7 @@ fn process_attribute_first_pass(
|| process_only_owner_attribute(attr, first_pass_data)
|| process_only_admin_attribute(attr, first_pass_data)
|| process_only_user_account_attribute(attr, first_pass_data)
|| process_allow_multiple_var_args_attribute(attr, first_pass_data)
}

fn process_attributes_second_pass(
Expand Down
12 changes: 12 additions & 0 deletions framework/derive/src/parse/trait_argument_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fn process_trait_attribute(
) -> bool {
process_only_owner_argument(attr, trait_arg_metadata)
|| process_only_admin_argument(attr, trait_arg_metadata)
|| process_allow_multiple_var_args_argument(attr, trait_arg_metadata)
}

fn process_only_owner_argument(attr: &syn::Attribute, arg_metadata: &mut TraitProperties) -> bool {
Expand All @@ -37,3 +38,14 @@ fn process_only_admin_argument(attr: &syn::Attribute, arg_metadata: &mut TraitPr
}
has_attr
}

fn process_allow_multiple_var_args_argument(
attr: &syn::Attribute,
arg_metadata: &mut TraitProperties,
) -> bool {
let has_attr = is_allow_multiple_var_args_prop(attr);
if has_attr {
arg_metadata.allow_multiple_var_args = true;
}
has_attr
}
Loading

0 comments on commit fbd7cf4

Please sign in to comment.