@@ -94,7 +94,7 @@ func updateAllocations(cCtx *cli.Context, p utils.Prompter) error {
9494
9595 allocationsToUpdate , err := generateAllocationsParams (ctx , elReader , config , logger )
9696 if err != nil {
97- return eigenSdkUtils .WrapError ("failed to generate allocations params" , err )
97+ return eigenSdkUtils .WrapError ("failed to generate Allocations params" , err )
9898 }
9999
100100 if config .broadcast {
@@ -120,7 +120,7 @@ func updateAllocations(cCtx *cli.Context, p utils.Prompter) error {
120120 receipt , err := eLWriter .ModifyAllocations (
121121 ctx ,
122122 config .operatorAddress ,
123- allocationsToUpdate .allocations ,
123+ allocationsToUpdate .Allocations ,
124124 contractIAVSDirectory.ISignatureUtilsSignatureWithSaltAndExpiry {
125125 Expiry : big .NewInt (0 ),
126126 },
@@ -143,14 +143,14 @@ func updateAllocations(cCtx *cli.Context, p utils.Prompter) error {
143143 // to claim. So we hardcode the gas limit to 150_000 so that we can
144144 // create unsigned tx without gas limit estimation from contract bindings
145145 if common .IsSmartContractAddress (config .operatorAddress , ethClient ) {
146- // Claimer is a smart contract
146+ // address is a smart contract
147147 noSendTxOpts .GasLimit = 150_000
148148 }
149149
150150 unsignedTx , err := contractBindings .AvsDirectory .ModifyAllocations (
151151 noSendTxOpts ,
152152 config .operatorAddress ,
153- allocationsToUpdate .allocations ,
153+ allocationsToUpdate .Allocations ,
154154 contractIAVSDirectory.ISignatureUtilsSignatureWithSaltAndExpiry {
155155 Expiry : big .NewInt (0 ),
156156 })
@@ -211,7 +211,7 @@ func generateAllocationsParams(
211211 elReader elChainReader ,
212212 config * updateConfig ,
213213 logger logging.Logger ,
214- ) (* bulkModifyAllocations , error ) {
214+ ) (* BulkModifyAllocations , error ) {
215215 allocations := make ([]contractIAVSDirectory.IAVSDirectoryMagnitudeAllocation , 0 )
216216 var allocatableMagnitudes map [gethcommon.Address ]uint64
217217
@@ -257,9 +257,9 @@ func generateAllocationsParams(
257257 }
258258 }
259259
260- return & bulkModifyAllocations {
261- allocations : allocations ,
262- allocatableMagnitudes : allocatableMagnitudes ,
260+ return & BulkModifyAllocations {
261+ Allocations : allocations ,
262+ AllocatableMagnitudes : allocatableMagnitudes ,
263263 }, nil
264264}
265265
@@ -272,19 +272,47 @@ func computeAllocations(
272272 if err != nil {
273273 return nil , nil , eigenSdkUtils .WrapError ("failed to parse allocations csv" , err )
274274 }
275+
276+ err = validateDataFromCSV (allocations )
277+ if err != nil {
278+ return nil , nil , eigenSdkUtils .WrapError ("failed to validate data from csv" , err )
279+ }
280+
275281 strategies := getUniqueStrategies (allocations )
276282 strategyTotalMagnitudes , err := parallelGetMagnitudes (strategies , operatorAddress , elReader )
277283 if err != nil {
278284 return nil , nil , eigenSdkUtils .WrapError ("failed to get total magnitudes" , err )
279285 }
286+
280287 allocatableMagnitudePerStrategy , err := parallelGetAllocatableMagnitudes (strategies , operatorAddress , elReader )
281288 if err != nil {
282289 return nil , nil , eigenSdkUtils .WrapError ("failed to get allocatable magnitudes" , err )
283290 }
291+
284292 magnitudeAllocations := convertAllocationsToMagnitudeAllocations (allocations , strategyTotalMagnitudes )
285293 return magnitudeAllocations , allocatableMagnitudePerStrategy , nil
286294}
287295
296+ func validateDataFromCSV (allocations []allocation ) error {
297+ // check for duplicated (avs_address,operator_set_id,strategy_address)
298+ tuples := make (map [string ]struct {})
299+
300+ for _ , alloc := range allocations {
301+ tuple := fmt .Sprintf ("%s_%d_%s" , alloc .AvsAddress .Hex (), alloc .OperatorSetId , alloc .StrategyAddress .Hex ())
302+ if _ , exists := tuples [tuple ]; exists {
303+ return fmt .Errorf (
304+ "duplicate combination found: avs_address=%s, operator_set_id=%d, strategy_address=%s" ,
305+ alloc .AvsAddress .Hex (),
306+ alloc .OperatorSetId ,
307+ alloc .StrategyAddress .Hex (),
308+ )
309+ }
310+ tuples [tuple ] = struct {}{}
311+ }
312+
313+ return nil
314+ }
315+
288316func parallelGetAllocatableMagnitudes (
289317 strategies []gethcommon.Address ,
290318 operatorAddress gethcommon.Address ,
@@ -451,7 +479,6 @@ func readAndValidateUpdateFlags(cCtx *cli.Context, logger logging.Logger) (*upda
451479 logger .Debugf ("Failed to get signer config: %s" , err )
452480 }
453481
454- // TODO(shrimalmadhur): Read bulk modify allocations
455482 csvFilePath := cCtx .String (flags .CSVFileFlag .Name )
456483 chainId := utils .NetworkNameToChainId (network )
457484
0 commit comments