@@ -2764,3 +2764,108 @@ pub fn encode_usdc_paymaster_data(
2764
2764
2765
2765
data
2766
2766
}
2767
+
2768
+ /// Creates the ABI-encoded calldata for an ERC20 `permit` call.
2769
+ /// This is used when the TBA needs to call permit on-chain (since TBAs can't sign off-chain)
2770
+ ///
2771
+ /// # Arguments
2772
+ /// * `owner` - The address that owns the tokens (the TBA in this case)
2773
+ /// * `spender` - The address to grant allowance to (e.g., the paymaster)
2774
+ /// * `value` - The amount of tokens to approve
2775
+ /// * `deadline` - The deadline timestamp for the permit
2776
+ ///
2777
+ /// # Returns
2778
+ /// A `Vec<u8>` containing the ABI-encoded calldata for the permit function
2779
+ pub fn create_erc20_permit_calldata (
2780
+ owner : EthAddress ,
2781
+ spender : EthAddress ,
2782
+ value : U256 ,
2783
+ deadline : U256 ,
2784
+ ) -> Vec < u8 > {
2785
+ // For on-chain permit calls by the TBA, we don't need nonce, v, r, s
2786
+ // The TBA will call permit() directly as the owner
2787
+ // This creates calldata for: permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
2788
+ // But for TBA on-chain calls, v=0, r=0, s=0 works because the TBA IS the owner
2789
+
2790
+ use alloy_sol_types:: SolCall ;
2791
+
2792
+ // Define the permit function call
2793
+ // Note: Using the standard ERC20Permit interface
2794
+ sol ! {
2795
+ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) ;
2796
+ }
2797
+
2798
+ let call = permitCall {
2799
+ owner,
2800
+ spender,
2801
+ value,
2802
+ deadline,
2803
+ v : 0 , // Dummy values for on-chain call
2804
+ r : B256 :: ZERO ,
2805
+ s : B256 :: ZERO ,
2806
+ } ;
2807
+
2808
+ call. abi_encode ( )
2809
+ }
2810
+
2811
+ /// Creates a multicall calldata that combines permit + another operation
2812
+ /// This is useful for TBAs to approve and use tokens in a single transaction
2813
+ pub fn create_multicall_permit_and_execute (
2814
+ token_address : EthAddress ,
2815
+ permit_spender : EthAddress ,
2816
+ permit_amount : U256 ,
2817
+ permit_deadline : U256 ,
2818
+ execute_target : EthAddress ,
2819
+ execute_calldata : Vec < u8 > ,
2820
+ execute_value : U256 ,
2821
+ ) -> Vec < u8 > {
2822
+ // Create permit calldata
2823
+ let permit_calldata = create_erc20_permit_calldata (
2824
+ EthAddress :: ZERO , // Will be replaced by TBA address when executed
2825
+ permit_spender,
2826
+ permit_amount,
2827
+ permit_deadline,
2828
+ ) ;
2829
+
2830
+ // For TBA execute, we need to create two execute calls:
2831
+ // 1. Execute permit on token contract
2832
+ // 2. Execute the actual operation
2833
+
2834
+ // This would need to be wrapped in a multicall or batch execute
2835
+ // The exact implementation depends on the TBA's interface
2836
+
2837
+ // For now, return just the permit calldata
2838
+ // In practice, this would be combined with the execute calldata
2839
+ permit_calldata
2840
+ }
2841
+
2842
+ /// Encode paymaster data for USDC payment with on-chain permit (for TBAs)
2843
+ /// This version doesn't include a permit signature since TBAs will call permit on-chain
2844
+ pub fn encode_usdc_paymaster_data_for_tba (
2845
+ paymaster : EthAddress ,
2846
+ token_address : EthAddress ,
2847
+ max_cost : U256 ,
2848
+ ) -> Vec < u8 > {
2849
+ // Start with paymaster address (20 bytes)
2850
+ let mut data = Vec :: new ( ) ;
2851
+ data. extend_from_slice ( paymaster. as_slice ( ) ) ;
2852
+
2853
+ // Add paymaster-specific data for Circle's TokenPaymaster v0.8
2854
+ // For TBAs, we might need a different mode or the paymaster needs to support on-chain permits
2855
+
2856
+ // Mode byte (1 for on-chain approval mode, if supported)
2857
+ // Note: This depends on Circle's paymaster implementation
2858
+ // Mode 0 = permit signature mode (for EOAs)
2859
+ // Mode 1 = assume pre-existing approval (for smart contracts)
2860
+ data. push ( 1u8 ) ;
2861
+
2862
+ // Token address (USDC)
2863
+ data. extend_from_slice ( token_address. as_slice ( ) ) ;
2864
+
2865
+ // Max cost amount
2866
+ data. extend_from_slice ( & max_cost. to_be_bytes :: < 32 > ( ) ) ;
2867
+
2868
+ // No signature needed for on-chain approval mode
2869
+
2870
+ data
2871
+ }
0 commit comments