11package chainio
22
33import (
4+ "context"
5+ "fmt"
6+ "math/big"
7+ "time"
48
59 "github.com/Layr-Labs/eigensdk-go/chainio/clients"
610 "github.com/Layr-Labs/eigensdk-go/chainio/clients/avsregistry"
711 "github.com/Layr-Labs/eigensdk-go/chainio/clients/eth"
812 "github.com/Layr-Labs/eigensdk-go/logging"
913 "github.com/Layr-Labs/eigensdk-go/signer"
14+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
1015 "github.com/ethereum/go-ethereum/common"
16+ "github.com/ethereum/go-ethereum/core/types"
1117 servicemanager "github.com/yetanotherco/aligned_layer/contracts/bindings/AlignedLayerServiceManager"
1218 "github.com/yetanotherco/aligned_layer/core/config"
1319)
@@ -18,6 +24,7 @@ type AvsWriter struct {
1824 logger logging.Logger
1925 Signer signer.Signer
2026 Client eth.Client
27+ ClientFallback eth.Client
2128}
2229
2330func NewAvsWriterFromConfig (baseConfig * config.BaseConfig , ecdsaConfig * config.EcdsaConfig ) (* AvsWriter , error ) {
@@ -59,22 +66,27 @@ func NewAvsWriterFromConfig(baseConfig *config.BaseConfig, ecdsaConfig *config.E
5966 logger : baseConfig .Logger ,
6067 Signer : privateKeySigner ,
6168 Client : baseConfig .EthRpcClient ,
69+ ClientFallback : baseConfig .EthRpcClientFallback ,
6270 }, nil
6371}
6472
65-
66- func (w * AvsWriter ) SendAggregatedResponse (batchMerkleRoot [32 ]byte , senderAddress [20 ]byte , nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature ) (* common.Hash , error ) {
73+ func (w * AvsWriter ) SendAggregatedResponse (batchIdentifierHash [32 ]byte , batchMerkleRoot [32 ]byte , senderAddress [20 ]byte , nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature ) (* common.Hash , error ) {
6774 txOpts := * w .Signer .GetTxOpts ()
6875 txOpts .NoSend = true // simulate the transaction
6976 tx , err := w .AvsContractBindings .ServiceManager .RespondToTaskV2 (& txOpts , batchMerkleRoot , senderAddress , nonSignerStakesAndSignature )
7077 if err != nil {
7178 // Retry with fallback
7279 tx , err = w .AvsContractBindings .ServiceManagerFallback .RespondToTaskV2 (& txOpts , batchMerkleRoot , senderAddress , nonSignerStakesAndSignature )
7380 if err != nil {
74- return nil , err
81+ return nil , fmt . Errorf ( "transaction simulation failed: %v" , err )
7582 }
7683 }
7784
85+ err = w .checkRespondToTaskFeeLimit (tx , txOpts , batchIdentifierHash , senderAddress )
86+ if err != nil {
87+ return nil , err
88+ }
89+
7890 // Send the transaction
7991 txOpts .NoSend = false
8092 txOpts .GasLimit = tx .Gas () * 110 / 100 // Add 10% to the gas limit
@@ -91,3 +103,82 @@ func (w *AvsWriter) SendAggregatedResponse(batchMerkleRoot [32]byte, senderAddre
91103
92104 return & txHash , nil
93105}
106+
107+ func (w * AvsWriter ) checkRespondToTaskFeeLimit (tx * types.Transaction , txOpts bind.TransactOpts , batchIdentifierHash [32 ]byte , senderAddress [20 ]byte ) error {
108+ aggregatorAddress := txOpts .From
109+ simulatedCost := new (big.Int ).Mul (new (big.Int ).SetUint64 (tx .Gas ()), tx .GasPrice ())
110+ w .logger .Info ("Simulated cost" , "cost" , simulatedCost )
111+
112+ // Get RespondToTaskFeeLimit
113+ batchState , err := w .AvsContractBindings .ServiceManager .BatchesState (& bind.CallOpts {}, batchIdentifierHash )
114+ if err != nil {
115+ // Retry with fallback
116+ batchState , err = w .AvsContractBindings .ServiceManagerFallback .BatchesState (& bind.CallOpts {}, batchIdentifierHash )
117+ if err != nil {
118+ // Fallback also failed
119+ // Proceed to check values against simulated costs
120+ w .logger .Error ("Failed to get batch state" , "error" , err )
121+ w .logger .Info ("Proceeding with simulated cost checks" )
122+
123+ return w .compareBalances (simulatedCost , aggregatorAddress , senderAddress )
124+ }
125+ }
126+ // At this point, batchState was successfully retrieved
127+ // Proceed to check values against RespondToTaskFeeLimit
128+ respondToTaskFeeLimit := batchState .RespondToTaskFeeLimit
129+ w .logger .Info ("Batch RespondToTaskFeeLimit" , "RespondToTaskFeeLimit" , respondToTaskFeeLimit )
130+
131+ if respondToTaskFeeLimit .Cmp (simulatedCost ) < 0 {
132+ return fmt .Errorf ("cost of transaction is higher than Batch.RespondToTaskFeeLimit" )
133+ }
134+
135+ return w .compareBalances (respondToTaskFeeLimit , aggregatorAddress , senderAddress )
136+ }
137+
138+ func (w * AvsWriter ) compareBalances (amount * big.Int , aggregatorAddress common.Address , senderAddress [20 ]byte ) error {
139+ if err := w .compareAggregatorBalance (amount , aggregatorAddress ); err != nil {
140+ return err
141+ }
142+ if err := w .compareBatcherBalance (amount , senderAddress ); err != nil {
143+ return err
144+ }
145+ return nil
146+ }
147+
148+ func (w * AvsWriter ) compareAggregatorBalance (amount * big.Int , aggregatorAddress common.Address ) error {
149+ ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
150+ defer cancel ()
151+ // Get Agg wallet balance
152+ aggregatorBalance , err := w .Client .BalanceAt (ctx , aggregatorAddress , nil )
153+ if err != nil {
154+ aggregatorBalance , err = w .ClientFallback .BalanceAt (ctx , aggregatorAddress , nil )
155+ if err != nil {
156+ // Ignore and continue.
157+ w .logger .Error ("failed to get aggregator balance: %v" , err )
158+ return nil
159+ }
160+ }
161+ w .logger .Info ("Aggregator balance" , "balance" , aggregatorBalance )
162+ if aggregatorBalance .Cmp (amount ) < 0 {
163+ return fmt .Errorf ("cost is higher than Aggregator balance" )
164+ }
165+ return nil
166+ }
167+
168+ func (w * AvsWriter ) compareBatcherBalance (amount * big.Int , senderAddress [20 ]byte ) error {
169+ // Get batcher balance
170+ batcherBalance , err := w .AvsContractBindings .ServiceManager .BatchersBalances (& bind.CallOpts {}, senderAddress )
171+ if err != nil {
172+ batcherBalance , err = w .AvsContractBindings .ServiceManagerFallback .BatchersBalances (& bind.CallOpts {}, senderAddress )
173+ if err != nil {
174+ // Ignore and continue.
175+ w .logger .Error ("Failed to get batcherBalance" , "error" , err )
176+ return nil
177+ }
178+ }
179+ w .logger .Info ("Batcher balance" , "balance" , batcherBalance )
180+ if batcherBalance .Cmp (amount ) < 0 {
181+ return fmt .Errorf ("cost is higher than Batcher balance" )
182+ }
183+ return nil
184+ }
0 commit comments