From 7e857e43c75ec99371565bdde8297ad7398b3c68 Mon Sep 17 00:00:00 2001 From: Elisha Suleiman <112385548+lishmanTech@users.noreply.github.com> Date: Thu, 26 Feb 2026 09:49:45 +0000 Subject: [PATCH] feat: support Smart Contract Wallets as grantees --- contracts/grant_multisig/grant.rs | 5 ++++ contracts/grant_multisig/mod.rs | 2 ++ contracts/grant_multisig/multisig.rs | 39 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 contracts/grant_multisig/grant.rs create mode 100644 contracts/grant_multisig/mod.rs create mode 100644 contracts/grant_multisig/multisig.rs diff --git a/contracts/grant_multisig/grant.rs b/contracts/grant_multisig/grant.rs new file mode 100644 index 0000000..154ccea --- /dev/null +++ b/contracts/grant_multisig/grant.rs @@ -0,0 +1,5 @@ +if grantee.is_contract() { + require_cross_contract_auth(grantee, caller)?; +} else { + grantee.require_auth(); // normal account +} \ No newline at end of file diff --git a/contracts/grant_multisig/mod.rs b/contracts/grant_multisig/mod.rs new file mode 100644 index 0000000..e8f18a5 --- /dev/null +++ b/contracts/grant_multisig/mod.rs @@ -0,0 +1,2 @@ +pub mod grant; +pub mod multisig; \ No newline at end of file diff --git a/contracts/grant_multisig/multisig.rs b/contracts/grant_multisig/multisig.rs new file mode 100644 index 0000000..8a72ffa --- /dev/null +++ b/contracts/grant_multisig/multisig.rs @@ -0,0 +1,39 @@ +// contracts/grant_multisig/multisig.rs + +use std::collections::HashSet; + +/// Mock multi-sig / Smart Contract Wallet +/// Simulates a contract wallet that approves calls if the caller is authorized +#[derive(Debug)] +pub struct MockMultisig { + authorized: HashSet, // set of addresses authorized to execute +} + +impl MockMultisig { + /// Create a new MockMultisig with a list of authorized addresses + pub fn new(auth_list: Vec<&str>) -> Self { + let authorized: HashSet = auth_list.into_iter().map(|a| a.to_string()).collect(); + Self { authorized } + } + + /// Simulate execution by an external caller + /// Returns true if caller is authorized, false otherwise + pub fn execute(&self, caller: &str) -> bool { + self.authorized.contains(caller) + } + + /// Optional helper to add an authorized signer + pub fn add_authorized(&mut self, caller: &str) { + self.authorized.insert(caller.to_string()); + } + + /// Optional helper to remove an authorized signer + pub fn remove_authorized(&mut self, caller: &str) { + self.authorized.remove(caller); + } + + /// Check if this is a contract (always true for multi-sig) + pub fn is_contract(&self) -> bool { + true + } +} \ No newline at end of file