@@ -57,7 +57,7 @@ mod contract_xcm {
5757 . map_err ( |_| RuntimeError :: XcmExecuteFailed )
5858 }
5959
60- /// Transfer some funds on the relay chain via XCM from the contract's derivative
60+ /// Transfer some funds to the relay chain via XCM from the contract's derivative
6161 /// account to the caller's account.
6262 ///
6363 /// Fails if:
@@ -70,27 +70,88 @@ mod contract_xcm {
7070 value : Balance ,
7171 fee : Balance ,
7272 ) -> Result < ( ) , RuntimeError > {
73+ // The destination of the XCM message. Assuming we run the contract
74+ // on a parachain, the parent will be the relay chain.
7375 let destination: ink:: xcm:: v5:: Location = ink:: xcm:: v5:: Parent . into ( ) ;
76+
77+ // The asset to be sent, since we are sending the XCM to the relay chain,
78+ // this represents `value` amount of the relay chain's native asset.
7479 let asset: Asset = ( Here , value) . into ( ) ;
80+
81+ // The beneficiary of the asset.
82+ // Here, the beneficiary is the caller's account on the relay chain.
7583 let caller_account_id = self . env ( ) . to_account_id ( self . env ( ) . caller ( ) ) ;
7684 let beneficiary = AccountId32 {
7785 network : None ,
7886 id : caller_account_id. 0 ,
7987 } ;
8088
89+ // Create an XCM message
8190 let message: Xcm < ( ) > = Xcm :: builder ( )
91+ // Withdraw the asset from the origin (the sovereign account of the
92+ // contract on the relay chain)
8293 . withdraw_asset ( asset. clone ( ) )
94+
95+ // Buy execution to pay the fee on the relay chain
8396 . buy_execution ( ( Here , fee) , WeightLimit :: Unlimited )
97+
98+ // Deposit the asset to the caller's account on the relay chain
8499 . deposit_asset ( asset, beneficiary)
85100 . build ( ) ;
86101
102+ // Send the constructed XCM message to the relay chain.
87103 self . env ( )
88104 . xcm_send (
89105 & VersionedLocation :: V5 ( destination) ,
90106 & VersionedXcm :: V5 ( message) ,
91107 )
92108 . map_err ( |_| RuntimeError :: XcmSendFailed )
93109 }
110+
111+ #[ ink( message) ]
112+ pub fn reserve_transfer (
113+ & mut self ,
114+ amount : Balance ,
115+ fee : Balance ,
116+ ) -> Result < ( ) , RuntimeError > {
117+ // The beneficiary of the transfer.
118+ // Here, the beneficiary is the caller's account on the relay chain.
119+ let caller_account_id = self . env ( ) . to_account_id ( self . env ( ) . caller ( ) ) ;
120+ let beneficiary: Location = AccountId32 {
121+ network : None ,
122+ id : caller_account_id. 0 ,
123+ }
124+ . into ( ) ;
125+
126+ // Create an XCM message.
127+ let message: Xcm < ( ) > = Xcm :: builder_unsafe ( )
128+ // Withdraw the relay's native token derivative from the
129+ // contract's account.
130+ . withdraw_asset ( ( Parent , amount) )
131+
132+ // The `initiate_reserve_withdraw` instruction takes the
133+ // derivative token from the holding register and burns it.
134+ // It then sends the nested XCM to the reserve in this
135+ // example, the relay chain.
136+ // Upon receiving the XCM, the reserve will withdraw the
137+ // asset from our chain's sovereign account, and deposit
138+ // on the caller's account.
139+ . initiate_reserve_withdraw (
140+ All ,
141+ Parent ,
142+ Xcm :: builder_unsafe ( )
143+ . buy_execution ( ( Here , fee) , Unlimited )
144+ . deposit_asset ( All , beneficiary)
145+ . build ( ) ,
146+ )
147+ . build ( ) ;
148+
149+ let msg = VersionedXcm :: V5 ( message) ;
150+ let weight = self . env ( ) . xcm_weigh ( & msg) . expect ( "`xcm_weigh` failed" ) ;
151+ self . env ( )
152+ . xcm_execute ( & msg, weight)
153+ . map_err ( |_| RuntimeError :: XcmExecuteFailed )
154+ }
94155 }
95156
96157 #[ cfg( all( test, feature = "e2e-tests" ) ) ]
0 commit comments