@@ -20,6 +20,11 @@ pub use builder::StarknetBridgeClientBuilder;
2020mod builder;
2121pub mod error;
2222
23+ /// STRK native token contract address on Starknet.
24+ const STRK_TOKEN : Felt = Felt :: from_hex_unchecked (
25+ "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d" ,
26+ ) ;
27+
2328/// Event data extracted from a Starknet `InitTransfer` receipt.
2429#[ derive( Debug ) ]
2530pub struct StarknetInitTransferEvent {
@@ -228,7 +233,8 @@ impl StarknetBridgeClient {
228233
229234 /// Initiate a transfer from Starknet.
230235 ///
231- /// This issues a multicall: first ERC-20 `approve`, then `init_transfer`.
236+ /// This issues a multicall: ERC-20 `approve` for the transfer token (amount + fee),
237+ /// optionally ERC-20 `approve` for STRK (native_fee), then `init_transfer`.
232238 #[ tracing:: instrument( skip_all, name = "STARKNET INIT TRANSFER" ) ]
233239 #[ allow( clippy:: too_many_arguments) ]
234240 pub async fn init_transfer (
@@ -242,12 +248,33 @@ impl StarknetBridgeClient {
242248 ) -> Result < Felt > {
243249 let bridge = self . omni_bridge_address ( ) ?;
244250
245- // ERC-20 approve call (amount as u256 = [low, high])
246- let approve_call = Call {
247- to : token,
248- selector : selector ! ( "approve" ) ,
249- calldata : vec ! [ bridge, Self :: encode_u128( amount) , Felt :: ZERO ] ,
250- } ;
251+ let mut calls = Vec :: new ( ) ;
252+
253+ // Approve transfer token for amount + fee
254+ let token_total: u128 = amount. checked_add ( fee) . ok_or_else ( || {
255+ StarknetBridgeClientError :: InvalidArgument (
256+ "amount + fee overflows u128" . to_string ( ) ,
257+ )
258+ } ) ?;
259+
260+ if token_total > 0 {
261+ calls. push ( Call {
262+ to : token,
263+ selector : selector ! ( "approve" ) ,
264+ calldata : vec ! [ bridge, Self :: encode_u128( token_total) , Felt :: ZERO ] ,
265+ } ) ;
266+ }
267+
268+ // Approve STRK token for native_fee.
269+ // On Starknet there is no msg.value, so the bridge contract pulls the
270+ // native fee from the caller via ERC-20 transferFrom on STRK.
271+ if native_fee > 0 {
272+ calls. push ( Call {
273+ to : STRK_TOKEN ,
274+ selector : selector ! ( "approve" ) ,
275+ calldata : vec ! [ bridge, Self :: encode_u128( native_fee) , Felt :: ZERO ] ,
276+ } ) ;
277+ }
251278
252279 // init_transfer call
253280 let mut calldata = vec ! [
@@ -259,13 +286,13 @@ impl StarknetBridgeClient {
259286 calldata. extend ( Self :: encode_byte_array ( & recipient) ) ;
260287 calldata. extend ( Self :: encode_byte_array ( & message) ) ;
261288
262- let init_call = Call {
289+ calls . push ( Call {
263290 to : bridge,
264291 selector : selector ! ( "init_transfer" ) ,
265292 calldata,
266- } ;
293+ } ) ;
267294
268- self . send_and_wait ( vec ! [ approve_call , init_call ] ) . await
295+ self . send_and_wait ( calls ) . await
269296 }
270297
271298 /// Finalize a transfer to Starknet using a `SignTransferEvent` from Near.
0 commit comments