33
44use alloy:: primitives:: U256 ;
55use alloy:: sol;
6+ use alloy:: sol_types:: SolCall ;
67use anyhow:: { Context , Result } ;
78use clap:: { Args , Subcommand } ;
8- use polymarket_client_sdk_v2:: types:: { Address , address} ;
9- use polymarket_client_sdk_v2:: { POLYGON , contract_config} ;
9+ use polymarket_client_sdk_v2:: types:: Address ;
1010
1111use crate :: auth;
1212use crate :: output:: OutputFormat ;
1313use crate :: output:: approve:: { ApprovalStatus , print_approval_status, print_tx_result} ;
1414
15- /// Polygon USDC (same address as `USDC_ADDRESS_STR`; `address!` requires a literal).
16- const USDC_ADDRESS : Address = address ! ( "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" ) ;
15+ use super :: {
16+ COLLATERAL_SYMBOL , CONDITIONAL_TOKENS , CTF_COLLATERAL_ADAPTER , CTF_EXCHANGE , NEG_RISK_ADAPTER ,
17+ NEG_RISK_CTF_COLLATERAL_ADAPTER , NEG_RISK_CTF_EXCHANGE , proxy,
18+ } ;
1719
1820sol ! {
1921 #[ sol( rpc) ]
@@ -49,101 +51,132 @@ pub enum ApproveCommand {
4951struct ApprovalTarget {
5052 name : & ' static str ,
5153 address : Address ,
54+ needs_collateral_allowance : bool ,
55+ needs_ctf_operator : bool ,
5256}
5357
5458fn approval_targets ( ) -> Result < Vec < ApprovalTarget > > {
55- let config = contract_config ( POLYGON , false ) . context ( "No contract config for Polygon" ) ?;
56- let neg_risk_config =
57- contract_config ( POLYGON , true ) . context ( "No neg-risk contract config for Polygon" ) ?;
58-
59- let mut targets = vec ! [
59+ Ok ( vec ! [
6060 ApprovalTarget {
6161 name: "CTF Exchange" ,
62- address: config. exchange,
62+ address: CTF_EXCHANGE ,
63+ needs_collateral_allowance: true ,
64+ needs_ctf_operator: true ,
6365 } ,
6466 ApprovalTarget {
6567 name: "Neg Risk Exchange" ,
66- address: neg_risk_config. exchange,
68+ address: NEG_RISK_CTF_EXCHANGE ,
69+ needs_collateral_allowance: true ,
70+ needs_ctf_operator: true ,
6771 } ,
68- ] ;
69-
70- if let Some ( adapter) = neg_risk_config. neg_risk_adapter {
71- targets. push ( ApprovalTarget {
72+ ApprovalTarget {
7273 name: "Neg Risk Adapter" ,
73- address : adapter,
74- } ) ;
75- }
76-
77- Ok ( targets)
74+ address: NEG_RISK_ADAPTER ,
75+ needs_collateral_allowance: true ,
76+ needs_ctf_operator: true ,
77+ } ,
78+ ApprovalTarget {
79+ name: "Conditional Tokens" ,
80+ address: CONDITIONAL_TOKENS ,
81+ needs_collateral_allowance: true ,
82+ needs_ctf_operator: false ,
83+ } ,
84+ ApprovalTarget {
85+ name: "CTF Collateral Adapter" ,
86+ address: CTF_COLLATERAL_ADAPTER ,
87+ needs_collateral_allowance: true ,
88+ needs_ctf_operator: true ,
89+ } ,
90+ ApprovalTarget {
91+ name: "Neg Risk CTF Collateral Adapter" ,
92+ address: NEG_RISK_CTF_COLLATERAL_ADAPTER ,
93+ needs_collateral_allowance: true ,
94+ needs_ctf_operator: true ,
95+ } ,
96+ ] )
7897}
7998
8099pub async fn execute (
81100 args : ApproveArgs ,
82101 output : OutputFormat ,
83102 private_key : Option < & str > ,
103+ signature_type : Option < & str > ,
84104) -> Result < ( ) > {
85105 match args. command {
86- ApproveCommand :: Check { address } => check ( address, private_key, output) . await ,
87- ApproveCommand :: Set => set ( private_key, output) . await ,
106+ ApproveCommand :: Check { address } => {
107+ check ( address, private_key, signature_type, output) . await
108+ }
109+ ApproveCommand :: Set => set ( private_key, signature_type, output) . await ,
88110 }
89111}
90112
91113async fn check (
92114 address_arg : Option < Address > ,
93115 private_key : Option < & str > ,
116+ signature_type : Option < & str > ,
94117 output : OutputFormat ,
95118) -> Result < ( ) > {
96119 let owner: Address = if let Some ( addr) = address_arg {
97120 addr
121+ } else if proxy:: is_proxy_mode ( signature_type) ? {
122+ proxy:: derive_proxy_address ( private_key) ?
98123 } else {
99124 let signer = auth:: resolve_signer ( private_key) ?;
100125 polymarket_client_sdk_v2:: auth:: Signer :: address ( & signer)
101126 } ;
102127
103128 let provider = auth:: create_readonly_provider ( ) . await ?;
104- let config = contract_config ( POLYGON , false ) . context ( "No contract config for Polygon" ) ?;
105-
106- let usdc = IERC20 :: new ( USDC_ADDRESS , provider. clone ( ) ) ;
107- let ctf = IERC1155 :: new ( config. conditional_tokens , provider. clone ( ) ) ;
129+ let collateral = IERC20 :: new ( super :: COLLATERAL_ADDRESS , provider. clone ( ) ) ;
130+ let ctf = IERC1155 :: new ( CONDITIONAL_TOKENS , provider. clone ( ) ) ;
108131
109132 let targets = approval_targets ( ) ?;
110133 let mut statuses = Vec :: new ( ) ;
111134
112135 for target in & targets {
113- let ( usdc_allowance, usdc_error) = match usdc. allowance ( owner, target. address ) . call ( ) . await
114- {
115- Ok ( val) => ( val, None ) ,
116- Err ( e) => ( U256 :: ZERO , Some ( e. to_string ( ) ) ) ,
136+ let ( collateral_allowance, collateral_error) = if target. needs_collateral_allowance {
137+ match collateral. allowance ( owner, target. address ) . call ( ) . await {
138+ Ok ( val) => ( val, None ) ,
139+ Err ( e) => ( U256 :: ZERO , Some ( e. to_string ( ) ) ) ,
140+ }
141+ } else {
142+ ( U256 :: ZERO , None )
117143 } ;
118144
119- let ( ctf_approved, ctf_error) =
145+ let ( ctf_approved, ctf_error) = if target . needs_ctf_operator {
120146 match ctf. isApprovedForAll ( owner, target. address ) . call ( ) . await {
121- Ok ( val) => ( val, None ) ,
122- Err ( e) => ( false , Some ( e. to_string ( ) ) ) ,
123- } ;
147+ Ok ( val) => ( Some ( val) , None ) ,
148+ Err ( e) => ( Some ( false ) , Some ( e. to_string ( ) ) ) ,
149+ }
150+ } else {
151+ ( None , None )
152+ } ;
124153
125154 statuses. push ( ApprovalStatus {
126155 contract_name : target. name . to_string ( ) ,
127156 contract_address : format ! ( "{}" , target. address) ,
128- usdc_allowance ,
157+ collateral_allowance ,
129158 ctf_approved,
130- usdc_error ,
159+ collateral_error ,
131160 ctf_error,
132161 } ) ;
133162 }
134163
135164 print_approval_status ( & statuses, & output)
136165}
137166
138- async fn set ( private_key : Option < & str > , output : OutputFormat ) -> Result < ( ) > {
139- let provider = auth:: create_provider ( private_key) . await ?;
140- let config = contract_config ( POLYGON , false ) . context ( "No contract config for Polygon" ) ?;
141-
142- let usdc = IERC20 :: new ( USDC_ADDRESS , provider. clone ( ) ) ;
143- let ctf = IERC1155 :: new ( config. conditional_tokens , provider. clone ( ) ) ;
144-
167+ async fn set (
168+ private_key : Option < & str > ,
169+ signature_type : Option < & str > ,
170+ output : OutputFormat ,
171+ ) -> Result < ( ) > {
172+ let use_proxy = proxy:: is_proxy_mode ( signature_type) ?;
145173 let targets = approval_targets ( ) ?;
146- let total = targets. len ( ) * 2 ;
174+ let total = targets
175+ . iter ( )
176+ . map ( |target| {
177+ usize:: from ( target. needs_collateral_allowance ) + usize:: from ( target. needs_ctf_operator )
178+ } )
179+ . sum ( ) ;
147180
148181 if matches ! ( output, OutputFormat :: Table ) {
149182 println ! ( "Approving contracts...\n " ) ;
@@ -153,52 +186,56 @@ async fn set(private_key: Option<&str>, output: OutputFormat) -> Result<()> {
153186 let mut step = 0 ;
154187
155188 for target in & targets {
156- step += 1 ;
157- let label = format ! ( "USDC \u{2192} {}" , target. name) ;
158- let tx_hash = usdc
159- . approve ( target. address , U256 :: MAX )
160- . send ( )
161- . await
162- . context ( format ! ( "Failed to send USDC approval for {}" , target. name) ) ?
163- . watch ( )
164- . await
165- . context ( format ! (
166- "Failed to confirm USDC approval for {}" ,
167- target. name
168- ) ) ?;
169-
170- match output {
171- OutputFormat :: Table => print_tx_result ( step, total, & label, tx_hash) ,
172- OutputFormat :: Json => results. push ( serde_json:: json!( {
173- "step" : step,
174- "type" : "erc20" ,
175- "contract" : target. name,
176- "tx_hash" : format!( "{tx_hash}" ) ,
177- } ) ) ,
189+ if target. needs_collateral_allowance {
190+ step += 1 ;
191+ let label = format ! ( "{COLLATERAL_SYMBOL} \u{2192} {}" , target. name) ;
192+ let calldata = IERC20 :: approveCall {
193+ spender : target. address ,
194+ value : U256 :: MAX ,
195+ }
196+ . abi_encode ( ) ;
197+ let ( tx_hash, _) =
198+ proxy:: send_call ( private_key, use_proxy, super :: COLLATERAL_ADDRESS , calldata)
199+ . await
200+ . context ( format ! (
201+ "Failed {COLLATERAL_SYMBOL} approval for {}" ,
202+ target. name
203+ ) ) ?;
204+
205+ match output {
206+ OutputFormat :: Table => print_tx_result ( step, total, & label, tx_hash) ,
207+ OutputFormat :: Json => results. push ( serde_json:: json!( {
208+ "step" : step,
209+ "type" : "erc20" ,
210+ "asset" : COLLATERAL_SYMBOL ,
211+ "contract" : target. name,
212+ "tx_hash" : format!( "{tx_hash}" ) ,
213+ } ) ) ,
214+ }
178215 }
179216
180- step += 1 ;
181- let label = format ! ( "CTF \u{2192} {}" , target . name ) ;
182- let tx_hash = ctf
183- . setApprovalForAll ( target . address , true )
184- . send ( )
185- . await
186- . context ( format ! ( "Failed to send CTF approval for {}" , target . name ) ) ?
187- . watch ( )
188- . await
189- . context ( format ! (
190- "Failed to confirm CTF approval for {}" ,
191- target. name
192- ) ) ? ;
193-
194- match output {
195- OutputFormat :: Table => print_tx_result ( step , total , & label , tx_hash ) ,
196- OutputFormat :: Json => results . push ( serde_json :: json! ( {
197- "step ": step ,
198- "type ": "erc1155" ,
199- "contract ": target . name ,
200- "tx_hash" : format! ( "{tx_hash}" ) ,
201- } ) ) ,
217+ if target . needs_ctf_operator {
218+ step += 1 ;
219+ let label = format ! ( "CTF \u{2192} {}" , target . name ) ;
220+ let calldata = IERC1155 :: setApprovalForAllCall {
221+ operator : target . address ,
222+ approved : true ,
223+ }
224+ . abi_encode ( ) ;
225+ let ( tx_hash , _ ) =
226+ proxy :: send_call ( private_key , use_proxy , CONDITIONAL_TOKENS , calldata )
227+ . await
228+ . context ( format ! ( "Failed CTF approval for {}" , target. name) ) ? ;
229+
230+ match output {
231+ OutputFormat :: Table => print_tx_result ( step , total , & label , tx_hash ) ,
232+ OutputFormat :: Json => results . push ( serde_json :: json! ( {
233+ "step" : step ,
234+ "type ": "erc1155" ,
235+ "contract ": target . name ,
236+ "tx_hash ": format! ( "{tx_hash}" ) ,
237+ } ) ) ,
238+ }
202239 }
203240 }
204241
0 commit comments