@@ -200,6 +200,11 @@ func buildExecuteOperationv2Cmd(lggr logger.Logger, domain cldf_domain.Domain, p
200200 if err != nil {
201201 return fmt .Errorf ("error converting proposal to executable: %w" , err )
202202 }
203+ inspector , err := getInspectorFromChainSelector (* cfg )
204+ if err != nil {
205+ return fmt .Errorf ("failed to get inspector: %w" , err )
206+ }
207+
203208 if cfg .fork {
204209 lggr .Info ("Fork mode is on, all transactions will be executed on a forked chain" )
205210 }
@@ -213,6 +218,23 @@ func buildExecuteOperationv2Cmd(lggr logger.Logger, domain cldf_domain.Domain, p
213218 return fmt .Errorf ("operation %d is not for chain %d" , index , cfg .chainSelector )
214219 }
215220
221+ opCount , err := inspector .GetOpCount (cmd .Context (), cfg .proposal .ChainMetadata [types .ChainSelector (cfg .chainSelector )].MCMAddress )
222+ if err != nil {
223+ return fmt .Errorf ("failed to get opcount for chain %d: %w" , cfg .chainSelector , err )
224+ }
225+ txNonce , err := executable .TxNonce (index )
226+ if err != nil {
227+ return fmt .Errorf ("failed to get TxNonce for chain %d: %w" , cfg .chainSelector , err )
228+ }
229+ if txNonce < opCount {
230+ lggr .Infow ("operation already executed" , "index" , index , "txNonce" , txNonce , "opCount" , opCount )
231+ return nil
232+ }
233+ if txNonce > opCount {
234+ lggr .Warnw ("txNonce too large" , "index" , index , "txNonce" , txNonce , "opCount" , opCount )
235+ return fmt .Errorf ("txNonce too large (%d; expected %d)" , txNonce , opCount )
236+ }
237+
216238 tx , err := executable .Execute (cmd .Context (), index )
217239 if err != nil {
218240 err = cldf .DecodeErr (bindings .ManyChainMultiSigABI , err )
@@ -1177,6 +1199,11 @@ func executeChainCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2, sk
11771199 if err != nil {
11781200 return fmt .Errorf ("error converting proposal to executable: %w" , err )
11791201 }
1202+ inspector , err := getInspectorFromChainSelector (* cfg )
1203+ if err != nil {
1204+ return fmt .Errorf ("failed to get inspector: %w" , err )
1205+ }
1206+
11801207 if cfg .fork {
11811208 lggr .Info ("Fork mode is on, all transactions will be executed on a forked chain" )
11821209 }
@@ -1187,6 +1214,23 @@ func executeChainCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2, sk
11871214 continue
11881215 }
11891216
1217+ opCount , err := inspector .GetOpCount (ctx , cfg .proposal .ChainMetadata [types .ChainSelector (cfg .chainSelector )].MCMAddress )
1218+ if err != nil {
1219+ return fmt .Errorf ("failed to get opcount for chain %d: %w" , cfg .chainSelector , err )
1220+ }
1221+ txNonce , err := executable .TxNonce (i )
1222+ if err != nil {
1223+ return fmt .Errorf ("failed to get TxNonce for chain %d: %w" , cfg .chainSelector , err )
1224+ }
1225+ if txNonce < opCount {
1226+ lggr .Infow ("operation already executed" , "index" , i , "txNonce" , txNonce , "opCount" , opCount )
1227+ continue
1228+ }
1229+ if txNonce > opCount {
1230+ lggr .Warnw ("txNonce too large" , "index" , i , "txNonce" , txNonce , "opCount" , opCount )
1231+ break
1232+ }
1233+
11901234 tx , err := executable .Execute (ctx , i )
11911235 if err != nil {
11921236 lggr .Errorf ("error executing operation %d: %s" , i , err )
@@ -1229,6 +1273,27 @@ func setRootCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2) error {
12291273 lggr .Info ("Fork mode is on, all transactions will be executed on a forked chain" )
12301274 }
12311275
1276+ inspector , err := getInspectorFromChainSelector (* cfg )
1277+ if err != nil {
1278+ return fmt .Errorf ("failed to get inspector: %w" , err )
1279+ }
1280+
1281+ proposalMerkleTree , err := cfg .proposal .MerkleTree ()
1282+ if err != nil {
1283+ return fmt .Errorf ("failed to compute the proposal's merkle tree: %w" , err )
1284+ }
1285+
1286+ mcmAddress := cfg .proposal .ChainMetadata [types .ChainSelector (cfg .chainSelector )].MCMAddress
1287+ mcmRoot , _ , err := inspector .GetRoot (ctx , mcmAddress )
1288+ if err != nil {
1289+ return fmt .Errorf ("failed to get the merkle tree root from the MCM contract (%v): %w" , mcmAddress , err )
1290+ }
1291+
1292+ if mcmRoot == proposalMerkleTree .Root {
1293+ lggr .Infof ("Root %v already set in MCM contract %v" , mcmRoot , mcmAddress )
1294+ return nil
1295+ }
1296+
12321297 executable , err := createExecutable (cfg )
12331298 if err != nil {
12341299 return fmt .Errorf ("error converting proposal to executable: %w" , err )
0 commit comments