42
42
43
43
mod tests;
44
44
45
- use sp_std:: prelude:: * ;
45
+ use sp_std:: { prelude:: * , marker :: PhantomData , ops :: { Deref , DerefMut } } ;
46
46
use sp_io:: hashing:: blake2_256;
47
47
use frame_support:: {
48
- decl_module, decl_storage, decl_event, decl_error, ensure,
48
+ Parameter , decl_module, decl_storage, decl_event, decl_error, ensure,
49
49
traits:: { Get , Currency , ReservableCurrency , BalanceStatus } ,
50
50
weights:: Weight ,
51
51
dispatch:: DispatchResult ,
@@ -55,37 +55,98 @@ use codec::{Encode, Decode};
55
55
use sp_runtime:: RuntimeDebug ;
56
56
57
57
/// Pending atomic swap operation.
58
- #[ derive( Clone , RuntimeDebug , Eq , PartialEq , Encode , Decode ) ]
59
- pub struct PendingSwap < AccountId , Balance , BlockNumber > {
58
+ #[ derive( Clone , Eq , PartialEq , RuntimeDebug , Encode , Decode ) ]
59
+ pub struct PendingSwap < T : Trait > {
60
60
/// Source of the swap.
61
- pub source : AccountId ,
62
- /// Balance value of the swap.
63
- pub balance : Balance ,
61
+ pub source : T :: AccountId ,
62
+ /// Action of this swap.
63
+ pub action : T :: SwapAction ,
64
64
/// End block of the lock.
65
- pub end_block : BlockNumber ,
65
+ pub end_block : T :: BlockNumber ,
66
66
}
67
67
68
- /// Balance type from the pallet's point of view .
69
- pub type BalanceFor < T > = << T as Trait > :: Currency as Currency < < T as frame_system :: Trait > :: AccountId > > :: Balance ;
68
+ /// Hashed proof type .
69
+ pub type HashedProof = [ u8 ; 32 ] ;
70
70
71
- /// AccountId type from the pallet's point of view.
72
- pub type AccountIdFor < T > = <T as frame_system:: Trait >:: AccountId ;
71
+ /// Definition of a pending atomic swap action. It contains the following three phrases:
72
+ ///
73
+ /// - **Reserve**: reserve the resources needed for a swap. This is to make sure that **Claim**
74
+ /// succeeds with best efforts.
75
+ /// - **Claim**: claim any resources reserved in the first phrase.
76
+ /// - **Cancel**: cancel any resources reserved in the first phrase.
77
+ pub trait SwapAction < T : Trait > {
78
+ /// Reserve the resources needed for the swap, from the given `source`. The reservation is
79
+ /// allowed to fail. If that is the case, the the full swap creation operation is cancelled.
80
+ fn reserve ( & self , source : & T :: AccountId ) -> DispatchResult ;
81
+ /// Claim the reserved resources, with `source` and `target`. Returns whether the claim
82
+ /// succeeds.
83
+ fn claim ( & self , source : & T :: AccountId , target : & T :: AccountId ) -> bool ;
84
+ /// Weight for executing the operation.
85
+ fn weight ( & self ) -> Weight ;
86
+ /// Cancel the resources reserved in `source`.
87
+ fn cancel ( & self , source : & T :: AccountId ) ;
88
+ }
73
89
74
- /// BlockNumber type from the pallet's point of view.
75
- pub type BlockNumberFor < T > = <T as frame_system:: Trait >:: BlockNumber ;
90
+ /// A swap action that only allows transferring balances.
91
+ #[ derive( Clone , RuntimeDebug , Eq , PartialEq , Encode , Decode ) ]
92
+ pub struct BalanceSwapAction < T : Trait , C : ReservableCurrency < T :: AccountId > > {
93
+ value : <C as Currency < <T as frame_system:: Trait >:: AccountId > >:: Balance ,
94
+ _marker : PhantomData < C > ,
95
+ }
76
96
77
- /// PendingSwap type from the pallet's point of view.
78
- pub type PendingSwapFor < T > = PendingSwap < AccountIdFor < T > , BalanceFor < T > , BlockNumberFor < T > > ;
97
+ impl < T : Trait , C > BalanceSwapAction < T , C > where
98
+ C : ReservableCurrency < T :: AccountId > ,
99
+ {
100
+ /// Create a new swap action value of balance.
101
+ pub fn new ( value : <C as Currency < <T as frame_system:: Trait >:: AccountId > >:: Balance ) -> Self {
102
+ Self { value, _marker : PhantomData }
103
+ }
104
+ }
79
105
80
- /// Hashed proof type.
81
- pub type HashedProof = [ u8 ; 32 ] ;
106
+ impl < T : Trait , C > Deref for BalanceSwapAction < T , C > where
107
+ C : ReservableCurrency < T :: AccountId > ,
108
+ {
109
+ type Target = <C as Currency < <T as frame_system:: Trait >:: AccountId > >:: Balance ;
110
+
111
+ fn deref ( & self ) -> & Self :: Target {
112
+ & self . value
113
+ }
114
+ }
115
+
116
+ impl < T : Trait , C > DerefMut for BalanceSwapAction < T , C > where
117
+ C : ReservableCurrency < T :: AccountId > ,
118
+ {
119
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
120
+ & mut self . value
121
+ }
122
+ }
123
+
124
+ impl < T : Trait , C > SwapAction < T > for BalanceSwapAction < T , C > where
125
+ C : ReservableCurrency < T :: AccountId > ,
126
+ {
127
+ fn reserve ( & self , source : & T :: AccountId ) -> DispatchResult {
128
+ C :: reserve ( & source, self . value )
129
+ }
130
+
131
+ fn claim ( & self , source : & T :: AccountId , target : & T :: AccountId ) -> bool {
132
+ C :: repatriate_reserved ( source, target, self . value , BalanceStatus :: Free ) . is_ok ( )
133
+ }
134
+
135
+ fn weight ( & self ) -> Weight {
136
+ T :: DbWeight :: get ( ) . reads_writes ( 1 , 1 )
137
+ }
138
+
139
+ fn cancel ( & self , source : & T :: AccountId ) {
140
+ C :: unreserve ( source, self . value ) ;
141
+ }
142
+ }
82
143
83
144
/// Atomic swap's pallet configuration trait.
84
145
pub trait Trait : frame_system:: Trait {
85
146
/// The overarching event type.
86
147
type Event : From < Event < Self > > + Into < <Self as frame_system:: Trait >:: Event > ;
87
- /// The currency mechanism .
88
- type Currency : ReservableCurrency < Self :: AccountId > ;
148
+ /// Swap action .
149
+ type SwapAction : SwapAction < Self > + Parameter ;
89
150
/// Limit of proof size.
90
151
///
91
152
/// Atomic swap is only atomic if once the proof is revealed, both parties can submit the proofs
@@ -103,7 +164,7 @@ decl_storage! {
103
164
trait Store for Module <T : Trait > as AtomicSwap {
104
165
pub PendingSwaps : double_map
105
166
hasher( twox_64_concat) T :: AccountId , hasher( blake2_128_concat) HashedProof
106
- => Option <PendingSwapFor <T >>;
167
+ => Option <PendingSwap <T >>;
107
168
}
108
169
}
109
170
@@ -121,6 +182,8 @@ decl_error! {
121
182
AlreadyClaimed ,
122
183
/// Swap does not exist.
123
184
NotExist ,
185
+ /// Claim action mismatch.
186
+ ClaimActionMismatch ,
124
187
/// Duration has not yet passed for the swap to be cancelled.
125
188
DurationNotPassed ,
126
189
}
@@ -129,14 +192,13 @@ decl_error! {
129
192
decl_event ! (
130
193
/// Event of atomic swap pallet.
131
194
pub enum Event <T > where
132
- Balance = BalanceFor <T >,
133
- AccountId = AccountIdFor <T >,
134
- PendingSwap = PendingSwapFor <T >,
195
+ AccountId = <T as system:: Trait >:: AccountId ,
196
+ PendingSwap = PendingSwap <T >,
135
197
{
136
198
/// Swap created.
137
199
NewSwap ( AccountId , HashedProof , PendingSwap ) ,
138
200
/// Swap claimed. The last parameter indicates whether the execution succeeds.
139
- SwapClaimed ( AccountId , HashedProof , Balance , bool ) ,
201
+ SwapClaimed ( AccountId , HashedProof , bool ) ,
140
202
/// Swap cancelled.
141
203
SwapCancelled ( AccountId , HashedProof ) ,
142
204
}
@@ -164,22 +226,22 @@ decl_module! {
164
226
#[ weight = T :: DbWeight :: get( ) . reads_writes( 1 , 1 ) . saturating_add( 40_000_000 ) ]
165
227
fn create_swap(
166
228
origin,
167
- target: AccountIdFor < T > ,
229
+ target: T :: AccountId ,
168
230
hashed_proof: HashedProof ,
169
- balance : BalanceFor < T > ,
170
- duration: BlockNumberFor < T > ,
231
+ action : T :: SwapAction ,
232
+ duration: T :: BlockNumber ,
171
233
) {
172
234
let source = ensure_signed( origin) ?;
173
235
ensure!(
174
236
!PendingSwaps :: <T >:: contains_key( & target, hashed_proof) ,
175
237
Error :: <T >:: AlreadyExist
176
238
) ;
177
239
178
- T :: Currency :: reserve( & source, balance ) ?;
240
+ action . reserve( & source) ?;
179
241
180
242
let swap = PendingSwap {
181
243
source,
182
- balance ,
244
+ action ,
183
245
end_block: frame_system:: Module :: <T >:: block_number( ) + duration,
184
246
} ;
185
247
PendingSwaps :: <T >:: insert( target. clone( ) , hashed_proof. clone( ) , swap. clone( ) ) ;
@@ -194,13 +256,17 @@ decl_module! {
194
256
/// The dispatch origin for this call must be _Signed_.
195
257
///
196
258
/// - `proof`: Revealed proof of the claim.
197
- #[ weight = T :: DbWeight :: get( ) . reads_writes( 2 , 2 )
259
+ /// - `action`: Action defined in the swap, it must match the entry in blockchain. Otherwise
260
+ /// the operation fails. This is used for weight calculation.
261
+ #[ weight = T :: DbWeight :: get( ) . reads_writes( 1 , 1 )
198
262
. saturating_add( 40_000_000 )
199
263
. saturating_add( ( proof. len( ) as Weight ) . saturating_mul( 100 ) )
264
+ . saturating_add( action. weight( ) )
200
265
]
201
266
fn claim_swap(
202
267
origin,
203
268
proof: Vec <u8 >,
269
+ action: T :: SwapAction ,
204
270
) -> DispatchResult {
205
271
ensure!(
206
272
proof. len( ) <= T :: ProofLimit :: get( ) as usize ,
@@ -212,18 +278,14 @@ decl_module! {
212
278
213
279
let swap = PendingSwaps :: <T >:: get( & target, hashed_proof)
214
280
. ok_or( Error :: <T >:: InvalidProof ) ?;
281
+ ensure!( swap. action == action, Error :: <T >:: ClaimActionMismatch ) ;
215
282
216
- let succeeded = T :: Currency :: repatriate_reserved(
217
- & swap. source,
218
- & target,
219
- swap. balance,
220
- BalanceStatus :: Free ,
221
- ) . is_ok( ) ;
283
+ let succeeded = swap. action. claim( & swap. source, & target) ;
222
284
223
285
PendingSwaps :: <T >:: remove( target. clone( ) , hashed_proof. clone( ) ) ;
224
286
225
287
Self :: deposit_event(
226
- RawEvent :: SwapClaimed ( target, hashed_proof, swap . balance , succeeded)
288
+ RawEvent :: SwapClaimed ( target, hashed_proof, succeeded)
227
289
) ;
228
290
229
291
Ok ( ( ) )
@@ -238,7 +300,7 @@ decl_module! {
238
300
#[ weight = T :: DbWeight :: get( ) . reads_writes( 1 , 1 ) . saturating_add( 40_000_000 ) ]
239
301
fn cancel_swap(
240
302
origin,
241
- target: AccountIdFor < T > ,
303
+ target: T :: AccountId ,
242
304
hashed_proof: HashedProof ,
243
305
) {
244
306
let source = ensure_signed( origin) ?;
@@ -254,10 +316,7 @@ decl_module! {
254
316
Error :: <T >:: DurationNotPassed ,
255
317
) ;
256
318
257
- T :: Currency :: unreserve(
258
- & swap. source,
259
- swap. balance,
260
- ) ;
319
+ swap. action. cancel( & swap. source) ;
261
320
PendingSwaps :: <T >:: remove( & target, hashed_proof. clone( ) ) ;
262
321
263
322
Self :: deposit_event(
0 commit comments