@@ -32,7 +32,8 @@ use crate::{
32
32
msg:: { EurekaMsg , ExecuteMsg , InitMsg , PredictWrappedTokenResponse , QueryMsg } ,
33
33
state:: {
34
34
BATCH_EXECUTION_ACKS , CHANNEL_BALANCE , CONFIG , EXECUTING_PACKET , EXECUTING_PACKET_IS_BATCH ,
35
- EXECUTION_ACK , HASH_TO_FOREIGN_TOKEN , IN_FLIGHT_PACKET , TOKEN_MINTER , TOKEN_ORIGIN ,
35
+ EXECUTION_ACK , HASH_TO_FOREIGN_TOKEN , IN_FLIGHT_PACKET , MARKET_MAKER , TOKEN_MINTER ,
36
+ TOKEN_ORIGIN ,
36
37
} ,
37
38
ContractError ,
38
39
} ;
@@ -44,6 +45,7 @@ pub const TOKEN_INIT_REPLY_ID: u64 = 0xbeef;
44
45
pub const ESCROW_REPLY_ID : u64 = 0xcafe ;
45
46
pub const FORWARD_REPLY_ID : u64 = 0xbabe ;
46
47
pub const MULTIPLEX_REPLY_ID : u64 = 0xface ;
48
+ pub const MM_FILL_REPLY_ID : u64 = 0xdead ;
47
49
48
50
pub const ZKGM_TOKEN_MINTER_LABEL : & str = "zkgm-token-minter" ;
49
51
@@ -177,6 +179,13 @@ pub fn execute(
177
179
) ,
178
180
}
179
181
}
182
+ ExecuteMsg :: InternalBatch { messages } => {
183
+ if info. sender != env. contract . address {
184
+ Err ( ContractError :: OnlySelf )
185
+ } else {
186
+ Ok ( Response :: new ( ) . add_messages ( messages) )
187
+ }
188
+ }
180
189
ExecuteMsg :: InternalExecutePacket {
181
190
caller,
182
191
packet,
@@ -777,6 +786,7 @@ fn execute_internal(
777
786
deps,
778
787
env,
779
788
info,
789
+ caller,
780
790
packet,
781
791
relayer,
782
792
relayer_msg,
@@ -1072,10 +1082,11 @@ fn execute_batch(
1072
1082
fn execute_fungible_asset_order (
1073
1083
deps : DepsMut ,
1074
1084
env : Env ,
1075
- _info : MessageInfo ,
1085
+ info : MessageInfo ,
1086
+ caller : Addr ,
1076
1087
packet : Packet ,
1077
1088
relayer : Addr ,
1078
- _relayer_msg : Bytes ,
1089
+ relayer_msg : Bytes ,
1079
1090
_salt : H256 ,
1080
1091
path : U256 ,
1081
1092
order : FungibleAssetOrder ,
@@ -1112,7 +1123,7 @@ fn execute_fungible_asset_order(
1112
1123
let base_covers_quote = base_amount >= quote_amount;
1113
1124
let fee_amount = base_amount. saturating_sub ( quote_amount) ;
1114
1125
1115
- let mut messages = Vec :: < SubMsg > :: new ( ) ;
1126
+ let mut messages = Vec :: new ( ) ;
1116
1127
1117
1128
// Protocol Fill - If the quote token matches the wrapped version of the base token and base amount >= quote amount
1118
1129
if quote_token_str == wrapped_denom && base_covers_quote {
@@ -1126,7 +1137,7 @@ fn execute_fungible_asset_order(
1126
1137
) ?;
1127
1138
1128
1139
// Create the token with metadata
1129
- messages. push ( SubMsg :: new ( make_wasm_msg (
1140
+ messages. push ( SubMsg :: reply_never ( make_wasm_msg (
1130
1141
WrappedTokenMsg :: CreateDenom {
1131
1142
subdenom : wrapped_denom. clone ( ) ,
1132
1143
metadata : Metadata {
@@ -1154,7 +1165,7 @@ fn execute_fungible_asset_order(
1154
1165
1155
1166
// Mint the quote amount to the receiver
1156
1167
if quote_amount > 0 {
1157
- messages. push ( SubMsg :: new ( make_wasm_msg (
1168
+ messages. push ( SubMsg :: reply_never ( make_wasm_msg (
1158
1169
WrappedTokenMsg :: MintTokens {
1159
1170
denom : wrapped_denom. clone ( ) ,
1160
1171
amount : quote_amount. into ( ) ,
@@ -1167,7 +1178,7 @@ fn execute_fungible_asset_order(
1167
1178
1168
1179
// Mint any fee to the relayer
1169
1180
if fee_amount > 0 {
1170
- messages. push ( SubMsg :: new ( make_wasm_msg (
1181
+ messages. push ( SubMsg :: reply_never ( make_wasm_msg (
1171
1182
WrappedTokenMsg :: MintTokens {
1172
1183
denom : wrapped_denom,
1173
1184
amount : fee_amount. into ( ) ,
@@ -1191,7 +1202,7 @@ fn execute_fungible_asset_order(
1191
1202
1192
1203
// Transfer the quote amount to the receiver
1193
1204
if quote_amount > 0 {
1194
- messages. push ( SubMsg :: new ( make_wasm_msg (
1205
+ messages. push ( SubMsg :: reply_never ( make_wasm_msg (
1195
1206
LocalTokenMsg :: Unescrow {
1196
1207
denom : quote_token_str. clone ( ) ,
1197
1208
recipient : receiver. into_string ( ) ,
@@ -1204,7 +1215,7 @@ fn execute_fungible_asset_order(
1204
1215
1205
1216
// Transfer any fee to the relayer
1206
1217
if fee_amount > 0 {
1207
- messages. push ( SubMsg :: new ( make_wasm_msg (
1218
+ messages. push ( SubMsg :: reply_never ( make_wasm_msg (
1208
1219
LocalTokenMsg :: Unescrow {
1209
1220
denom : quote_token_str,
1210
1221
recipient : relayer. into_string ( ) ,
@@ -1217,14 +1228,42 @@ fn execute_fungible_asset_order(
1217
1228
}
1218
1229
// Market Maker Fill - Any party can fill the order by providing the quote token
1219
1230
else {
1220
- // Return a special acknowledgement that indicates this order needs a market maker
1221
- return Ok ( Response :: new ( ) . add_message ( wasm_execute (
1222
- env. contract . address ,
1223
- & ExecuteMsg :: InternalWriteAck {
1224
- ack : ACK_ERR_ONLY_MAKER . into ( ) ,
1225
- } ,
1226
- vec ! [ ] ,
1227
- ) ?) ) ;
1231
+ if quote_amount > 0 {
1232
+ MARKET_MAKER . save ( deps. storage , & relayer_msg) ?;
1233
+ messages. push ( SubMsg :: reply_always (
1234
+ wasm_execute (
1235
+ & env. contract . address ,
1236
+ & ExecuteMsg :: InternalBatch {
1237
+ messages : vec ! [
1238
+ // Make sure the marker provide the funds
1239
+ make_wasm_msg(
1240
+ LocalTokenMsg :: Escrow {
1241
+ from: caller. to_string( ) ,
1242
+ denom: quote_token_str. clone( ) ,
1243
+ recipient: minter. to_string( ) ,
1244
+ amount: quote_amount. into( ) ,
1245
+ } ,
1246
+ & minter,
1247
+ info. funds,
1248
+ ) ?,
1249
+ // Release the funds to the user
1250
+ make_wasm_msg(
1251
+ LocalTokenMsg :: Unescrow {
1252
+ denom: quote_token_str,
1253
+ recipient: receiver. to_string( ) ,
1254
+ amount: quote_amount. into( ) ,
1255
+ } ,
1256
+ minter,
1257
+ vec![ ] ,
1258
+ ) ?,
1259
+ ] ,
1260
+ } ,
1261
+ vec ! [ ] ,
1262
+ ) ?,
1263
+ MM_FILL_REPLY_ID ,
1264
+ ) ) ;
1265
+ }
1266
+ return Ok ( Response :: new ( ) . add_submessages ( messages) ) ;
1228
1267
}
1229
1268
1230
1269
// Return success acknowledgement with protocol fill type
@@ -1411,26 +1450,53 @@ pub fn reply(deps: DepsMut, env: Env, reply: Reply) -> Result<Response, Contract
1411
1450
// eureka mode of multiplex operations.
1412
1451
MULTIPLEX_REPLY_ID => {
1413
1452
// Extract the acknowledgement from the reply
1414
- if let SubMsgResult :: Ok ( reply_data) = reply. result {
1415
- #[ allow( deprecated) ]
1416
- let acknowledgement = reply_data. data . unwrap_or_default ( ) ;
1453
+ match reply. result {
1454
+ SubMsgResult :: Ok ( reply_data) => {
1455
+ #[ allow( deprecated) ]
1456
+ let acknowledgement = reply_data. data . unwrap_or_default ( ) ;
1417
1457
1418
- // If the acknowledgement is empty, we can't proceed
1419
- if acknowledgement. is_empty ( ) {
1420
- return Err ( ContractError :: AsyncMultiplexUnsupported ) ;
1421
- }
1458
+ // If the acknowledgement is empty, we can't proceed
1459
+ if acknowledgement. is_empty ( ) {
1460
+ return Err ( ContractError :: AsyncMultiplexUnsupported ) ;
1461
+ }
1422
1462
1463
+ Ok ( Response :: new ( ) . add_message ( wasm_execute (
1464
+ env. contract . address ,
1465
+ & ExecuteMsg :: InternalWriteAck {
1466
+ ack : Vec :: from ( acknowledgement) . into ( ) ,
1467
+ } ,
1468
+ vec ! [ ] ,
1469
+ ) ?) )
1470
+ }
1471
+ SubMsgResult :: Err ( error) => Err ( ContractError :: MultiplexError { error } ) ,
1472
+ }
1473
+ }
1474
+ MM_FILL_REPLY_ID => match reply. result {
1475
+ SubMsgResult :: Ok ( _) => {
1476
+ let market_maker = MARKET_MAKER . load ( deps. storage ) ?;
1477
+ MARKET_MAKER . remove ( deps. storage ) ;
1423
1478
Ok ( Response :: new ( ) . add_message ( wasm_execute (
1424
1479
env. contract . address ,
1425
1480
& ExecuteMsg :: InternalWriteAck {
1426
- ack : Vec :: from ( acknowledgement) . into ( ) ,
1481
+ ack : FungibleAssetOrderAck {
1482
+ fill_type : FILL_TYPE_MARKETMAKER ,
1483
+ market_maker : Vec :: from ( market_maker) . into ( ) ,
1484
+ }
1485
+ . abi_encode_params ( )
1486
+ . into ( ) ,
1427
1487
} ,
1428
1488
vec ! [ ] ,
1429
1489
) ?) )
1430
- } else {
1431
- Err ( ContractError :: AsyncMultiplexUnsupported )
1432
1490
}
1433
- }
1491
+ // Leave a chance for another MM to fill by telling the top level handler to revert.
1492
+ SubMsgResult :: Err ( _) => Ok ( Response :: new ( ) . add_message ( wasm_execute (
1493
+ env. contract . address ,
1494
+ & ExecuteMsg :: InternalWriteAck {
1495
+ ack : ACK_ERR_ONLY_MAKER . into ( ) ,
1496
+ } ,
1497
+ vec ! [ ] ,
1498
+ ) ?) ) ,
1499
+ } ,
1434
1500
// For any other reply ID, we don't know how to handle it, so we return an error.
1435
1501
// This is a safety measure to ensure we don't silently ignore unexpected replies,
1436
1502
// which could indicate a bug in the contract or an attempt to exploit it.
0 commit comments