Skip to content

Commit

Permalink
feat: add max uo per sender permission
Browse files Browse the repository at this point in the history
  • Loading branch information
dancoombs committed Feb 25, 2025
1 parent 79e0dc6 commit 87ace2e
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 5 deletions.
5 changes: 4 additions & 1 deletion crates/builder/src/bundle_proposer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3328,7 +3328,10 @@ mod tests {
aggregator: None,
da_gas_data: Default::default(),
filter_id: None,
perms: UserOperationPermissions { trusted: *trusted },
perms: UserOperationPermissions {
trusted: *trusted,
..Default::default()
},
})
.collect();

Expand Down
1 change: 1 addition & 0 deletions crates/pool/proto/op_pool/op_pool.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ message UserOperation {

message UserOperationPermissions {
bool trusted = 1;
optional uint64 max_allowed_in_pool_for_sender = 2;
}

// Protocol Buffer representation of an 7702 authorization tuple. See the official
Expand Down
44 changes: 40 additions & 4 deletions crates/pool/src/mempool/uo_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,14 +641,18 @@ where

// Check sender count in mempool. If sender has too many operations, must be staked
{
let sender_allowed_count = pool_op
.perms
.max_allowed_in_pool_for_sender
.unwrap_or(self.config.same_sender_mempool_count);

let state = self.state.read();
if !pool_op.account_is_staked
&& to_replace.is_none()
&& state.pool.address_count(&pool_op.uo.sender())
>= self.config.same_sender_mempool_count
&& state.pool.address_count(&pool_op.uo.sender()) >= sender_allowed_count
{
return Err(MempoolError::MaxOperationsReached(
self.config.same_sender_mempool_count,
sender_allowed_count,
Entity::account(pool_op.uo.sender()),
));
}
Expand Down Expand Up @@ -2229,7 +2233,10 @@ mod tests {
#[tokio::test]
async fn test_trusted_uo() {
let config = default_config();
let perms = UserOperationPermissions { trusted: true };
let perms = UserOperationPermissions {
trusted: true,
..Default::default()
};

let op = create_trusted_op(Address::random(), 0, 0);
let pool = create_pool_with_config(config, vec![op.clone()]);
Expand All @@ -2238,6 +2245,35 @@ mod tests {
.unwrap();
}

#[tokio::test]
async fn test_max_allowed_in_pool_for_sender() {
let config = default_config();
let perms = UserOperationPermissions {
max_allowed_in_pool_for_sender: Some(2),
..Default::default()
};
let sender = Address::random();

let op1 = create_op(sender, 1, 100, None);
let op2 = create_op(sender, 2, 100, None);
let op3 = create_op(sender, 3, 100, None);

let pool = create_pool_with_config(config, vec![op1.clone(), op2.clone(), op3.clone()]);
pool.add_operation(OperationOrigin::Local, op1.op, perms.clone())
.await
.unwrap();
pool.add_operation(OperationOrigin::Local, op2.op, perms.clone())
.await
.unwrap();
let err = pool
.add_operation(OperationOrigin::Local, op3.op, perms)
.await
.err()
.unwrap();

assert!(matches!(err, MempoolError::MaxOperationsReached(2, _)));
}

#[derive(Clone, Debug)]
struct OpWithErrors {
op: UserOperationVariant,
Expand Down
6 changes: 6 additions & 0 deletions crates/pool/src/server/remote/protos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,9 @@ impl From<UserOperationPermissions> for RundlerUserOperationPermissions {
fn from(permissions: UserOperationPermissions) -> Self {
Self {
trusted: permissions.trusted,
max_allowed_in_pool_for_sender: permissions
.max_allowed_in_pool_for_sender
.map(|c| c as usize),
}
}
}
Expand All @@ -584,6 +587,9 @@ impl From<RundlerUserOperationPermissions> for UserOperationPermissions {
fn from(permissions: RundlerUserOperationPermissions) -> Self {
Self {
trusted: permissions.trusted,
max_allowed_in_pool_for_sender: permissions
.max_allowed_in_pool_for_sender
.map(|c| c as u64),
}
}
}
5 changes: 5 additions & 0 deletions crates/rpc/src/types/permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// You should have received a copy of the GNU General Public License along with Rundler.
// If not, see https://www.gnu.org/licenses/.

use alloy_primitives::U64;
use rundler_types::{chain::ChainSpec, UserOperationPermissions};
use serde::{Deserialize, Serialize};

Expand All @@ -23,12 +24,16 @@ pub(crate) struct RpcUserOperationPermissions {
/// Whether the user operation is trusted, allowing the bundler to skip untrusted simulation
#[serde(default)]
pub(crate) trusted: bool,
/// The maximum sender allowed in the pool
#[serde(default)]
pub(crate) max_allowed_in_pool_for_sender: Option<U64>,
}

impl FromRpc<RpcUserOperationPermissions> for UserOperationPermissions {
fn from_rpc(rpc: RpcUserOperationPermissions, _chain_spec: &ChainSpec) -> Self {
UserOperationPermissions {
trusted: rpc.trusted,
max_allowed_in_pool_for_sender: rpc.max_allowed_in_pool_for_sender.map(|c| c.to()),
}
}
}
2 changes: 2 additions & 0 deletions crates/types/src/user_operation/permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@
pub struct UserOperationPermissions {
/// Whether the user operation is trusted, allowing the bundler to skip untrusted simulation
pub trusted: bool,
/// The maximum number of user operations allowed for a sender in the mempool
pub max_allowed_in_pool_for_sender: Option<usize>,
}

0 comments on commit 87ace2e

Please sign in to comment.