From 24d040f18e1abefd252c4ab80bd17752f4e26660 Mon Sep 17 00:00:00 2001 From: owen-eth Date: Mon, 26 Jan 2026 19:34:45 -0500 Subject: [PATCH 1/4] initial fastswap api logic --- tools/preconf-rpc/fastswap/fastswap.go | 755 ++++++++++++++++++++ tools/preconf-rpc/fastswap/fastswap_test.go | 700 ++++++++++++++++++ tools/preconf-rpc/main.go | 59 ++ tools/preconf-rpc/service/service.go | 34 + 4 files changed, 1548 insertions(+) create mode 100644 tools/preconf-rpc/fastswap/fastswap.go create mode 100644 tools/preconf-rpc/fastswap/fastswap_test.go diff --git a/tools/preconf-rpc/fastswap/fastswap.go b/tools/preconf-rpc/fastswap/fastswap.go new file mode 100644 index 000000000..6ac23c4e5 --- /dev/null +++ b/tools/preconf-rpc/fastswap/fastswap.go @@ -0,0 +1,755 @@ +package fastswap + +import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "log/slog" + "math/big" + "net/http" + "strconv" + "strings" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/primev/mev-commit/tools/preconf-rpc/sender" +) + +// ============ Types ============ + +// Intent mirrors the Solidity Intent struct from FastSettlementV3. +type Intent struct { + User common.Address `json:"user"` + InputToken common.Address `json:"inputToken"` + OutputToken common.Address `json:"outputToken"` + InputAmt *big.Int `json:"inputAmt"` + UserAmtOut *big.Int `json:"userAmtOut"` + Recipient common.Address `json:"recipient"` + Deadline *big.Int `json:"deadline"` + Nonce *big.Int `json:"nonce"` +} + +// SwapCall mirrors the Solidity SwapCall struct. +type SwapCall struct { + To common.Address `json:"to"` + Value *big.Int `json:"value"` + Data []byte `json:"data"` +} + +// SwapRequest is the HTTP request body for the /fastswap endpoint. +type SwapRequest struct { + Intent Intent `json:"intent"` + Signature []byte `json:"signature"` // EIP-712 Permit2 signature +} + +// SwapResult is the HTTP response for /fastswap. +type SwapResult struct { + TxHash string `json:"txHash,omitempty"` // Transaction hash (when submitted) + OutputAmount string `json:"outputAmount"` + GasLimit uint64 `json:"gasLimit"` + Status string `json:"status"` // "success", "error" + Error string `json:"error,omitempty"` +} + +// ETHSwapRequest is the HTTP request body for /fastswap/eth (user-submitted ETH swaps). +// User swaps native ETH for an ERC20 token and submits the transaction themselves. +type ETHSwapRequest struct { + OutputToken common.Address `json:"outputToken"` + InputAmt *big.Int `json:"inputAmt"` // ETH amount in wei + UserAmtOut *big.Int `json:"userAmtOut"` // minAmountOut from dapp quote + Sender common.Address `json:"sender"` // User address (also recipient) + Deadline *big.Int `json:"deadline"` // Unix timestamp +} + +// ETHSwapResponse is the response for /fastswap/eth containing unsigned tx data. +type ETHSwapResponse struct { + To string `json:"to"` // FastSettlementV3 contract address + Data string `json:"data"` // Hex-encoded calldata (0x-prefixed) + Value string `json:"value"` // ETH value to send (same as inputAmt) + ChainID uint64 `json:"chainId"` // Chain ID for the transaction + GasLimit uint64 `json:"gasLimit"` // Estimated gas limit + Status string `json:"status"` // "success", "error" + Error string `json:"error,omitempty"` +} + +// BarterResponse represents the parsed response from Barter API. +type BarterResponse struct { + To common.Address `json:"to"` + GasLimit string `json:"gasLimit"` + Value string `json:"value"` + Data string `json:"data"` + Route struct { + OutputAmount string `json:"outputAmount"` + GasEstimation uint64 `json:"gasEstimation"` + BlockNumber uint64 `json:"blockNumber"` + } `json:"route"` +} + +// barterRequest is the request body for the Barter API. +type barterRequest struct { + Source string `json:"source"` + Target string `json:"target"` + SellAmount string `json:"sellAmount"` + Recipient string `json:"recipient"` + Origin string `json:"origin"` + MinReturn string `json:"minReturn"` + Deadline string `json:"deadline"` + SourceFee *sourceFee `json:"sourceFee,omitempty"` +} + +type sourceFee struct { + Amount string `json:"amount"` + Recipient string `json:"recipient"` +} + +// IntentTuple is a struct that matches the ABI tuple for Intent. +type IntentTuple struct { + User common.Address + InputToken common.Address + OutputToken common.Address + InputAmt *big.Int + UserAmtOut *big.Int + Recipient common.Address + Deadline *big.Int + Nonce *big.Int +} + +// SwapCallTuple is a struct that matches the ABI tuple for SwapCall. +type SwapCallTuple struct { + To common.Address + Value *big.Int + Data []byte +} + +// ============ Service ============ + +// Mainnet WETH address +var mainnetWETH = common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") + +// Signer interface for signing transactions +type Signer interface { + SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) + GetAddress() common.Address +} + +// TxEnqueuer interface for enqueuing transactions to be sent +type TxEnqueuer interface { + Enqueue(ctx context.Context, tx *sender.Transaction) error +} + +// BlockTracker interface for getting nonce and gas pricing +type BlockTracker interface { + AccountNonce(ctx context.Context, account common.Address) (uint64, error) + NextBaseFee() *big.Int +} + +// Service handles FastSwap operations. +type Service struct { + barterBaseURL string + barterAPIKey string + settlementAddr common.Address + chainID uint64 + logger *slog.Logger + httpClient *http.Client + // Path 1 executor submission dependencies (set via SetExecutorDeps) + signer Signer + txEnqueuer TxEnqueuer + blockTracker BlockTracker +} + +// NewService creates a new FastSwap service. +// For Path 1 executor submission, call SetExecutorDeps after creation. +func NewService( + barterBaseURL string, + barterAPIKey string, + settlementAddr common.Address, + chainID uint64, + logger *slog.Logger, +) *Service { + return &Service{ + barterBaseURL: barterBaseURL, + barterAPIKey: barterAPIKey, + settlementAddr: settlementAddr, + chainID: chainID, + logger: logger, + httpClient: &http.Client{ + Timeout: 30 * time.Second, + }, + } +} + +// SetExecutorDeps sets the dependencies needed for Path 1 executor transaction submission. +// This is called after TxSender is created since there's a circular dependency. +func (s *Service) SetExecutorDeps(signer Signer, txEnqueuer TxEnqueuer, blockTracker BlockTracker) { + s.signer = signer + s.txEnqueuer = txEnqueuer + s.blockTracker = blockTracker +} + +// ============ ABI ============ + +// FastSettlementV3 ABI for executeWithPermit (executor path) +const executeWithPermitABI = `[{ + "inputs": [ + { + "components": [ + {"internalType": "address", "name": "user", "type": "address"}, + {"internalType": "address", "name": "inputToken", "type": "address"}, + {"internalType": "address", "name": "outputToken", "type": "address"}, + {"internalType": "uint256", "name": "inputAmt", "type": "uint256"}, + {"internalType": "uint256", "name": "userAmtOut", "type": "uint256"}, + {"internalType": "address", "name": "recipient", "type": "address"}, + {"internalType": "uint256", "name": "deadline", "type": "uint256"}, + {"internalType": "uint256", "name": "nonce", "type": "uint256"} + ], + "internalType": "struct IFastSettlementV3.Intent", + "name": "intent", + "type": "tuple" + }, + {"internalType": "bytes", "name": "signature", "type": "bytes"}, + { + "components": [ + {"internalType": "address", "name": "to", "type": "address"}, + {"internalType": "uint256", "name": "value", "type": "uint256"}, + {"internalType": "bytes", "name": "data", "type": "bytes"} + ], + "internalType": "struct IFastSettlementV3.SwapCall", + "name": "swapData", + "type": "tuple" + } + ], + "name": "executeWithPermit", + "outputs": [ + {"internalType": "uint256", "name": "received", "type": "uint256"}, + {"internalType": "uint256", "name": "surplus", "type": "uint256"} + ], + "stateMutability": "nonpayable", + "type": "function" +}]` + +// FastSettlementV3 ABI for executeWithETH (user ETH swap path) +const executeWithETHABI = `[{ + "inputs": [ + { + "components": [ + {"internalType": "address", "name": "user", "type": "address"}, + {"internalType": "address", "name": "inputToken", "type": "address"}, + {"internalType": "address", "name": "outputToken", "type": "address"}, + {"internalType": "uint256", "name": "inputAmt", "type": "uint256"}, + {"internalType": "uint256", "name": "userAmtOut", "type": "uint256"}, + {"internalType": "address", "name": "recipient", "type": "address"}, + {"internalType": "uint256", "name": "deadline", "type": "uint256"}, + {"internalType": "uint256", "name": "nonce", "type": "uint256"} + ], + "internalType": "struct IFastSettlementV3.Intent", + "name": "intent", + "type": "tuple" + }, + { + "components": [ + {"internalType": "address", "name": "to", "type": "address"}, + {"internalType": "uint256", "name": "value", "type": "uint256"}, + {"internalType": "bytes", "name": "data", "type": "bytes"} + ], + "internalType": "struct IFastSettlementV3.SwapCall", + "name": "swapData", + "type": "tuple" + } + ], + "name": "executeWithETH", + "outputs": [ + {"internalType": "uint256", "name": "received", "type": "uint256"}, + {"internalType": "uint256", "name": "surplus", "type": "uint256"} + ], + "stateMutability": "payable", + "type": "function" +}]` + +var ( + executeWithPermitABIParsed abi.ABI + executeWithETHABIParsed abi.ABI +) + +func init() { + var err error + executeWithPermitABIParsed, err = abi.JSON(strings.NewReader(executeWithPermitABI)) + if err != nil { + panic(fmt.Sprintf("failed to parse executeWithPermit ABI: %v", err)) + } + executeWithETHABIParsed, err = abi.JSON(strings.NewReader(executeWithETHABI)) + if err != nil { + panic(fmt.Sprintf("failed to parse executeWithETH ABI: %v", err)) + } +} + +// ============ Barter API ============ + +// callBarter is the shared HTTP call logic for calling the Barter swap API. +func (s *Service) callBarter(ctx context.Context, reqBody barterRequest, logDescription string) (*BarterResponse, error) { + bodyBytes, err := json.Marshal(reqBody) + if err != nil { + return nil, fmt.Errorf("marshal barter request: %w", err) + } + + req, err := http.NewRequestWithContext( + ctx, + http.MethodPost, + fmt.Sprintf("%s/swap", s.barterBaseURL), + bytes.NewReader(bodyBytes), + ) + if err != nil { + return nil, fmt.Errorf("create barter request: %w", err) + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.barterAPIKey)) + + s.logger.Debug("calling Barter API", + "type", logDescription, + "url", req.URL.String(), + "source", reqBody.Source, + "target", reqBody.Target, + "sellAmount", reqBody.SellAmount, + ) + + resp, err := s.httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("barter API request failed: %w", err) + } + defer func() { _ = resp.Body.Close() }() + + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("read barter response: %w", err) + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("barter API error (status %d): %s", resp.StatusCode, string(respBody)) + } + + var barterResp BarterResponse + if err := json.Unmarshal(respBody, &barterResp); err != nil { + return nil, fmt.Errorf("unmarshal barter response: %w", err) + } + + s.logger.Info("Barter API response", + "type", logDescription, + "to", barterResp.To.Hex(), + "outputAmount", barterResp.Route.OutputAmount, + "gasLimit", barterResp.GasLimit, + ) + + return &barterResp, nil +} + +// CallBarterAPI calls the Barter swap API with the given intent (Path 1). +func (s *Service) CallBarterAPI(ctx context.Context, intent Intent) (*BarterResponse, error) { + // IMPORTANT: Recipient must be the settlement contract, not the user's recipient. + // The contract receives the swap output, then distributes: + // - userAmtOut → intent.Recipient + // - surplus → treasury + reqBody := barterRequest{ + Source: intent.InputToken.Hex(), + Target: intent.OutputToken.Hex(), + SellAmount: intent.InputAmt.String(), + Recipient: s.settlementAddr.Hex(), + Origin: intent.User.Hex(), + MinReturn: intent.UserAmtOut.String(), + Deadline: intent.Deadline.String(), + } + return s.callBarter(ctx, reqBody, "executor-swap") +} + +// ============ Transaction Builder ============ + +// BuildExecuteTx constructs the calldata for FastSettlementV3.execute. +func (s *Service) BuildExecuteTx(intent Intent, signature []byte, barter *BarterResponse) ([]byte, error) { + // Decode swap data from Barter response + swapData, err := hex.DecodeString(strings.TrimPrefix(barter.Data, "0x")) + if err != nil { + return nil, fmt.Errorf("decode barter data: %w", err) + } + + // Parse value from Barter response + value := new(big.Int) + if barter.Value != "" && barter.Value != "0" { + value.SetString(barter.Value, 10) + } + + intentTuple := IntentTuple{ + User: intent.User, + InputToken: intent.InputToken, + OutputToken: intent.OutputToken, + InputAmt: intent.InputAmt, + UserAmtOut: intent.UserAmtOut, + Recipient: intent.Recipient, + Deadline: intent.Deadline, + Nonce: intent.Nonce, + } + + swapCallTuple := SwapCallTuple{ + To: barter.To, + Value: value, + Data: swapData, + } + + calldata, err := executeWithPermitABIParsed.Pack("executeWithPermit", intentTuple, signature, swapCallTuple) + if err != nil { + return nil, fmt.Errorf("pack executeWithPermit calldata: %w", err) + } + + s.logger.Debug("built executeWithPermit calldata", + "calldataLen", len(calldata), + "swapTarget", barter.To.Hex(), + ) + + return calldata, nil +} + +// ============ Handler ============ + +// HandleSwap is the main orchestrator for processing a swap request. +// For Path 1, it builds, signs, and enqueues the transaction for the executor. +func (s *Service) HandleSwap(ctx context.Context, req SwapRequest) (*SwapResult, error) { + // Validate executor dependencies are set + if s.signer == nil || s.txEnqueuer == nil || s.blockTracker == nil { + return &SwapResult{ + Status: "error", + Error: "executor dependencies not configured", + }, nil + } + + // 1. Call Barter API + barterResp, err := s.CallBarterAPI(ctx, req.Intent) + if err != nil { + return &SwapResult{ + Status: "error", + Error: fmt.Sprintf("barter API error: %v", err), + }, nil + } + + // 2. Build execute transaction calldata + calldata, err := s.BuildExecuteTx(req.Intent, req.Signature, barterResp) + if err != nil { + return &SwapResult{ + Status: "error", + Error: fmt.Sprintf("build tx error: %v", err), + }, nil + } + + // 3. Parse gas limit and add buffer + gasLimit, _ := strconv.ParseUint(barterResp.GasLimit, 10, 64) + gasLimit += 100000 // Buffer for settlement contract overhead + + // 4. Get nonce for executor wallet + executorAddr := s.signer.GetAddress() + nonce, err := s.blockTracker.AccountNonce(ctx, executorAddr) + if err != nil { + return &SwapResult{ + Status: "error", + Error: fmt.Sprintf("failed to get nonce: %v", err), + }, nil + } + + // 5. Calculate gas pricing: GasFeeCap = NextBaseFee only (no tip needed, mev-commit bid handles inclusion) + nextBaseFee := s.blockTracker.NextBaseFee() + if nextBaseFee == nil || nextBaseFee.Sign() == 0 { + nextBaseFee = big.NewInt(30_000_000_000) // 30 gwei fallback + } + gasTipCap := big.NewInt(0) // No priority fee - mev-commit bid handles inclusion + gasFeeCap := nextBaseFee // GasFeeCap = BaseFee (tip is 0) + + // 6. Build the transaction + chainID := big.NewInt(int64(s.chainID)) + tx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + Gas: gasLimit, + To: &s.settlementAddr, + Value: big.NewInt(0), // executeWithPermit is non-payable + Data: calldata, + }) + + // 7. Sign the transaction + signedTx, err := s.signer.SignTx(tx, chainID) + if err != nil { + return &SwapResult{ + Status: "error", + Error: fmt.Sprintf("failed to sign tx: %v", err), + }, nil + } + + // 8. Encode to raw hex + rawTxBytes, err := signedTx.MarshalBinary() + if err != nil { + return &SwapResult{ + Status: "error", + Error: fmt.Sprintf("failed to encode tx: %v", err), + }, nil + } + rawTxHex := "0x" + hex.EncodeToString(rawTxBytes) + + // 9. Enqueue the transaction + senderTx := &sender.Transaction{ + Transaction: signedTx, + Sender: executorAddr, + Raw: rawTxHex, + Type: sender.TxTypeRegular, + } + + if err := s.txEnqueuer.Enqueue(ctx, senderTx); err != nil { + return &SwapResult{ + Status: "error", + Error: fmt.Sprintf("failed to enqueue tx: %v", err), + }, nil + } + + s.logger.Info("swap transaction submitted", + "txHash", signedTx.Hash().Hex(), + "user", req.Intent.User.Hex(), + "inputToken", req.Intent.InputToken.Hex(), + "outputToken", req.Intent.OutputToken.Hex(), + "inputAmt", req.Intent.InputAmt.String(), + "outputAmount", barterResp.Route.OutputAmount, + "gasLimit", gasLimit, + "gasFeeCap", gasFeeCap.String(), + "gasTipCap", gasTipCap.String(), + "nonce", nonce, + ) + + return &SwapResult{ + TxHash: signedTx.Hash().Hex(), + OutputAmount: barterResp.Route.OutputAmount, + GasLimit: gasLimit, + Status: "success", + }, nil +} + +// Handler returns an HTTP handler for the /fastswap endpoint. +func (s *Service) Handler() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + // Limit body size + r.Body = http.MaxBytesReader(w, r.Body, 1*1024*1024) // 1MB + defer func() { _ = r.Body.Close() }() + + var req SwapRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, fmt.Sprintf("invalid request body: %v", err), http.StatusBadRequest) + return + } + + // Validate required fields + if req.Intent.User == (common.Address{}) { + http.Error(w, "missing intent.user", http.StatusBadRequest) + return + } + if req.Intent.InputToken == (common.Address{}) { + http.Error(w, "missing intent.inputToken", http.StatusBadRequest) + return + } + if req.Intent.OutputToken == (common.Address{}) { + http.Error(w, "missing intent.outputToken", http.StatusBadRequest) + return + } + if req.Intent.InputAmt == nil || req.Intent.InputAmt.Sign() <= 0 { + http.Error(w, "invalid intent.inputAmt", http.StatusBadRequest) + return + } + if len(req.Signature) == 0 { + http.Error(w, "missing signature", http.StatusBadRequest) + return + } + + result, err := s.HandleSwap(r.Context(), req) + if err != nil { + s.logger.Error("HandleSwap error", "error", err) + http.Error(w, fmt.Sprintf("internal error: %v", err), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + if result.Status == "error" { + w.WriteHeader(http.StatusBadRequest) + } + if err := json.NewEncoder(w).Encode(result); err != nil { + s.logger.Error("failed to encode response", "error", err) + } + } +} + +// ============ Path 2: User ETH Swap ============ + +// CallBarterAPIForETH calls the Barter swap API for an ETH swap (Path 2). +// Uses WETH as the source token since Barter works with ERC20s. +func (s *Service) CallBarterAPIForETH(ctx context.Context, req ETHSwapRequest) (*BarterResponse, error) { + reqBody := barterRequest{ + Source: mainnetWETH.Hex(), // WETH (Barter uses ERC20s) + Target: req.OutputToken.Hex(), + SellAmount: req.InputAmt.String(), + Recipient: s.settlementAddr.Hex(), + Origin: req.Sender.Hex(), + MinReturn: req.UserAmtOut.String(), + Deadline: req.Deadline.String(), + } + return s.callBarter(ctx, reqBody, "eth-swap") +} + +// BuildExecuteWithETHTx constructs the calldata for FastSettlementV3.executeWithETH. +func (s *Service) BuildExecuteWithETHTx(req ETHSwapRequest, barter *BarterResponse) ([]byte, error) { + // Decode swap data from Barter response + swapData, err := hex.DecodeString(strings.TrimPrefix(barter.Data, "0x")) + if err != nil { + return nil, fmt.Errorf("decode barter data: %w", err) + } + + // Parse value from Barter response + value := new(big.Int) + if barter.Value != "" && barter.Value != "0" { + value.SetString(barter.Value, 10) + } + + // Build Intent tuple - inputToken is address(0) for ETH + intentTuple := IntentTuple{ + User: req.Sender, + InputToken: common.Address{}, // address(0) indicates native ETH + OutputToken: req.OutputToken, + InputAmt: req.InputAmt, + UserAmtOut: req.UserAmtOut, + Recipient: req.Sender, // User is also recipient + Deadline: req.Deadline, + Nonce: big.NewInt(0), // Unused for Path 2 + } + + swapCallTuple := SwapCallTuple{ + To: barter.To, + Value: value, + Data: swapData, + } + + calldata, err := executeWithETHABIParsed.Pack("executeWithETH", intentTuple, swapCallTuple) + if err != nil { + return nil, fmt.Errorf("pack executeWithETH calldata: %w", err) + } + + s.logger.Debug("built executeWithETH calldata", + "calldataLen", len(calldata), + "swapTarget", barter.To.Hex(), + ) + + return calldata, nil +} + +// HandleETHSwap is the main orchestrator for processing an ETH swap request (Path 2). +func (s *Service) HandleETHSwap(ctx context.Context, req ETHSwapRequest) (*ETHSwapResponse, error) { + // 1. Call Barter API + barterResp, err := s.CallBarterAPIForETH(ctx, req) + if err != nil { + return ÐSwapResponse{ + Status: "error", + Error: fmt.Sprintf("barter API error: %v", err), + }, nil + } + + // 2. Build executeWithETH transaction calldata + txData, err := s.BuildExecuteWithETHTx(req, barterResp) + if err != nil { + return ÐSwapResponse{ + Status: "error", + Error: fmt.Sprintf("build tx error: %v", err), + }, nil + } + + // 3. Parse gas limit + gasLimit, _ := strconv.ParseUint(barterResp.GasLimit, 10, 64) + + // Add buffer for settlement contract overhead (WETH wrap, approve, transfer, etc.) + // Rough estimate: 150k gas for settlement logic with WETH wrapping + gasLimit += 150000 + + s.logger.Info("ETH swap request processed", + "sender", req.Sender.Hex(), + "outputToken", req.OutputToken.Hex(), + "inputAmt", req.InputAmt.String(), + "outputAmount", barterResp.Route.OutputAmount, + "gasEstimation", barterResp.Route.GasEstimation, + "gasLimit", gasLimit, + ) + + return ÐSwapResponse{ + To: s.settlementAddr.Hex(), + Data: "0x" + hex.EncodeToString(txData), + Value: req.InputAmt.String(), + ChainID: s.chainID, + GasLimit: gasLimit, + Status: "success", + }, nil +} + +// ETHHandler returns an HTTP handler for the /fastswap/eth endpoint. +func (s *Service) ETHHandler() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + // Limit body size + r.Body = http.MaxBytesReader(w, r.Body, 1*1024*1024) // 1MB + defer func() { _ = r.Body.Close() }() + + var req ETHSwapRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, fmt.Sprintf("invalid request body: %v", err), http.StatusBadRequest) + return + } + + // Validate required fields + if req.Sender == (common.Address{}) { + http.Error(w, "missing sender", http.StatusBadRequest) + return + } + if req.OutputToken == (common.Address{}) { + http.Error(w, "missing outputToken", http.StatusBadRequest) + return + } + if req.InputAmt == nil || req.InputAmt.Sign() <= 0 { + http.Error(w, "invalid inputAmt", http.StatusBadRequest) + return + } + if req.UserAmtOut == nil || req.UserAmtOut.Sign() <= 0 { + http.Error(w, "invalid userAmtOut", http.StatusBadRequest) + return + } + if req.Deadline == nil || req.Deadline.Sign() <= 0 { + http.Error(w, "invalid deadline", http.StatusBadRequest) + return + } + + result, err := s.HandleETHSwap(r.Context(), req) + if err != nil { + s.logger.Error("HandleETHSwap error", "error", err) + http.Error(w, fmt.Sprintf("internal error: %v", err), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + if result.Status == "error" { + w.WriteHeader(http.StatusBadRequest) + } + if err := json.NewEncoder(w).Encode(result); err != nil { + s.logger.Error("failed to encode response", "error", err) + } + } +} diff --git a/tools/preconf-rpc/fastswap/fastswap_test.go b/tools/preconf-rpc/fastswap/fastswap_test.go new file mode 100644 index 000000000..72bf9005c --- /dev/null +++ b/tools/preconf-rpc/fastswap/fastswap_test.go @@ -0,0 +1,700 @@ +package fastswap_test + +import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" + "math/big" + "net/http" + "net/http/httptest" + "os" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/primev/mev-commit/tools/preconf-rpc/fastswap" + "github.com/primev/mev-commit/tools/preconf-rpc/sender" + "github.com/primev/mev-commit/x/util" + "github.com/stretchr/testify/require" +) + +// ============ Mocks ============ + +type mockSigner struct { + address common.Address +} + +func (m *mockSigner) SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + // Return the tx unchanged (not actually signed, but tests don't verify signatures) + return tx, nil +} + +func (m *mockSigner) GetAddress() common.Address { + return m.address +} + +type mockTxEnqueuer struct { + enqueuedTxs []*sender.Transaction +} + +func (m *mockTxEnqueuer) Enqueue(ctx context.Context, tx *sender.Transaction) error { + m.enqueuedTxs = append(m.enqueuedTxs, tx) + return nil +} + +type mockBlockTracker struct { + nonce uint64 + nextBaseFee *big.Int +} + +func (m *mockBlockTracker) AccountNonce(ctx context.Context, account common.Address) (uint64, error) { + return m.nonce, nil +} + +func (m *mockBlockTracker) NextBaseFee() *big.Int { + return m.nextBaseFee +} + +// ============ Test Helpers ============ + +func newTestBarterResponse() fastswap.BarterResponse { + // Mock response matching real Barter /swap API format + // Real example: USDT -> USDC swap returns: + // to: swap executor contract + // gasLimit: estimated gas as string + // value: ETH value (usually "0" for ERC20 swaps) + // data: encoded swap calldata + // route.outputAmount: expected output tokens + // route.gasEstimation: gas estimate as uint64 + // route.blockNumber: current block number + return fastswap.BarterResponse{ + To: common.HexToAddress("0x179dc3fb0f2230094894317f307241a52cdb38aa"), // Barter swap executor + GasLimit: "1227112", + Value: "0", + Data: "0xf0d7bb940000000000000000000000002c0552e5dcb79b064fd23e358a86810bc5994244", // truncated for test + Route: struct { + OutputAmount string `json:"outputAmount"` + GasEstimation uint64 `json:"gasEstimation"` + BlockNumber uint64 `json:"blockNumber"` + }{ + OutputAmount: "250212361", // e.g., 250.2 USDC (6 decimals) + GasEstimation: 217861, + BlockNumber: 24322525, + }, + } +} + +func setupTestServer(t *testing.T, barterResp fastswap.BarterResponse) *httptest.Server { + return httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/swap" { + http.NotFound(w, r) + return + } + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + // Verify authorization header + auth := r.Header.Get("Authorization") + if !strings.HasPrefix(auth, "Bearer ") { + http.Error(w, "missing authorization", http.StatusUnauthorized) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + if err := json.NewEncoder(w).Encode(barterResp); err != nil { + t.Errorf("failed to encode response: %v", err) + } + }), + ) +} + +// ============ Tests ============ + +func TestNewService(t *testing.T) { + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService( + "https://api.barter.com", + "test-api-key", + common.HexToAddress("0x1234567890123456789012345678901234567890"), + 1, + logger, + ) + + require.NotNil(t, svc) +} + +func TestCallBarterAPI(t *testing.T) { + barterResp := newTestBarterResponse() + srv := setupTestServer(t, barterResp) + defer srv.Close() + + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService( + srv.URL, + "test-api-key", + common.HexToAddress("0x1234567890123456789012345678901234567890"), + 1, + logger, + ) + + intent := fastswap.Intent{ + User: common.HexToAddress("0xUserAddress"), + InputToken: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), // USDC + OutputToken: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), // WETH + InputAmt: big.NewInt(1000000000), // 1000 USDC + UserAmtOut: big.NewInt(500000000000000000), // 0.5 ETH + Recipient: common.HexToAddress("0xRecipientAddress"), + Deadline: big.NewInt(1700000000), + Nonce: big.NewInt(1), + } + + ctx := context.Background() + resp, err := svc.CallBarterAPI(ctx, intent) + + require.NoError(t, err) + require.NotNil(t, resp) + require.Equal(t, barterResp.To, resp.To) + require.Equal(t, barterResp.Route.OutputAmount, resp.Route.OutputAmount) +} + +func TestCallBarterAPIForETH(t *testing.T) { + barterResp := newTestBarterResponse() + srv := setupTestServer(t, barterResp) + defer srv.Close() + + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService( + srv.URL, + "test-api-key", + common.HexToAddress("0x1234567890123456789012345678901234567890"), + 1, + logger, + ) + + req := fastswap.ETHSwapRequest{ + OutputToken: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), // USDC + InputAmt: big.NewInt(1000000000000000000), // 1 ETH + UserAmtOut: big.NewInt(2000000000), // 2000 USDC + Sender: common.HexToAddress("0xSenderAddress"), + Deadline: big.NewInt(1700000000), + } + + ctx := context.Background() + resp, err := svc.CallBarterAPIForETH(ctx, req) + + require.NoError(t, err) + require.NotNil(t, resp) + require.Equal(t, barterResp.To, resp.To) +} + +func TestBuildExecuteTx(t *testing.T) { + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService( + "https://api.barter.com", + "test-api-key", + common.HexToAddress("0x1234567890123456789012345678901234567890"), + 1, + logger, + ) + + intent := fastswap.Intent{ + User: common.HexToAddress("0xUserAddress"), + InputToken: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + OutputToken: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + InputAmt: big.NewInt(1000000000), + UserAmtOut: big.NewInt(500000000000000000), + Recipient: common.HexToAddress("0xRecipientAddress"), + Deadline: big.NewInt(1700000000), + Nonce: big.NewInt(1), + } + + barterResp := newTestBarterResponse() + signature := []byte{0x01, 0x02, 0x03, 0x04} + + calldata, err := svc.BuildExecuteTx(intent, signature, &barterResp) + + require.NoError(t, err) + require.NotEmpty(t, calldata) + // Check it starts with the function selector (first 4 bytes) + require.True(t, len(calldata) > 4) +} + +func TestBuildExecuteWithETHTx(t *testing.T) { + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService( + "https://api.barter.com", + "test-api-key", + common.HexToAddress("0x1234567890123456789012345678901234567890"), + 1, + logger, + ) + + req := fastswap.ETHSwapRequest{ + OutputToken: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + InputAmt: big.NewInt(1000000000000000000), + UserAmtOut: big.NewInt(2000000000), + Sender: common.HexToAddress("0xSenderAddress"), + Deadline: big.NewInt(1700000000), + } + + barterResp := newTestBarterResponse() + + calldata, err := svc.BuildExecuteWithETHTx(req, &barterResp) + + require.NoError(t, err) + require.NotEmpty(t, calldata) + require.True(t, len(calldata) > 4) +} + +func TestHandleSwap(t *testing.T) { + barterResp := newTestBarterResponse() + srv := setupTestServer(t, barterResp) + defer srv.Close() + + logger := util.NewTestLogger(os.Stdout) + settlementAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") + svc := fastswap.NewService( + srv.URL, + "test-api-key", + settlementAddr, + 1, + logger, + ) + + // Set up executor dependencies + mockSigner := &mockSigner{address: common.HexToAddress("0xExecutorAddress")} + mockEnqueuer := &mockTxEnqueuer{} + mockTracker := &mockBlockTracker{ + nonce: 5, + nextBaseFee: big.NewInt(30000000000), // 30 gwei + } + svc.SetExecutorDeps(mockSigner, mockEnqueuer, mockTracker) + + req := fastswap.SwapRequest{ + Intent: fastswap.Intent{ + User: common.HexToAddress("0xUserAddress"), + InputToken: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + OutputToken: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + InputAmt: big.NewInt(1000000000), + UserAmtOut: big.NewInt(500000000000000000), + Recipient: common.HexToAddress("0xRecipientAddress"), + Deadline: big.NewInt(1700000000), + Nonce: big.NewInt(1), + }, + Signature: []byte{0x01, 0x02, 0x03, 0x04}, + } + + ctx := context.Background() + result, err := svc.HandleSwap(ctx, req) + + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, "success", result.Status) + require.NotEmpty(t, result.TxHash) + require.Equal(t, barterResp.Route.OutputAmount, result.OutputAmount) + + // Verify tx was enqueued + require.Len(t, mockEnqueuer.enqueuedTxs, 1) + enqueuedTx := mockEnqueuer.enqueuedTxs[0] + require.Equal(t, mockSigner.address, enqueuedTx.Sender) +} + +func TestHandleSwap_NoExecutorDeps(t *testing.T) { + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService( + "https://api.barter.com", + "test-api-key", + common.HexToAddress("0x1234567890123456789012345678901234567890"), + 1, + logger, + ) + // No executor deps set + + req := fastswap.SwapRequest{ + Intent: fastswap.Intent{ + User: common.HexToAddress("0xUserAddress"), + InputToken: common.HexToAddress("0xInputToken"), + InputAmt: big.NewInt(1000), + }, + Signature: []byte{0x01, 0x02}, + } + + ctx := context.Background() + result, err := svc.HandleSwap(ctx, req) + + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, "error", result.Status) + require.Contains(t, result.Error, "executor dependencies not configured") +} + +func TestHandleETHSwap(t *testing.T) { + barterResp := newTestBarterResponse() + srv := setupTestServer(t, barterResp) + defer srv.Close() + + logger := util.NewTestLogger(os.Stdout) + settlementAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") + svc := fastswap.NewService( + srv.URL, + "test-api-key", + settlementAddr, + 1, + logger, + ) + + req := fastswap.ETHSwapRequest{ + OutputToken: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + InputAmt: big.NewInt(1000000000000000000), + UserAmtOut: big.NewInt(2000000000), + Sender: common.HexToAddress("0xSenderAddress"), + Deadline: big.NewInt(1700000000), + } + + ctx := context.Background() + result, err := svc.HandleETHSwap(ctx, req) + + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, "success", result.Status) + require.Equal(t, settlementAddr.Hex(), result.To) + require.True(t, strings.HasPrefix(result.Data, "0x")) + require.Equal(t, req.InputAmt.String(), result.Value) + require.Equal(t, uint64(1), result.ChainID) + require.Greater(t, result.GasLimit, uint64(0)) +} + +func TestHandler(t *testing.T) { + barterResp := newTestBarterResponse() + srv := setupTestServer(t, barterResp) + defer srv.Close() + + logger := util.NewTestLogger(os.Stdout) + settlementAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") + svc := fastswap.NewService( + srv.URL, + "test-api-key", + settlementAddr, + 1, + logger, + ) + + mockSignerInst := &mockSigner{address: common.HexToAddress("0xExecutorAddress")} + mockEnqueuer := &mockTxEnqueuer{} + mockTracker := &mockBlockTracker{ + nonce: 0, + nextBaseFee: big.NewInt(30000000000), + } + svc.SetExecutorDeps(mockSignerInst, mockEnqueuer, mockTracker) + + handler := svc.Handler() + + // Use raw JSON with proper big.Int encoding (numbers, not quoted strings) + reqJSON := `{ + "intent": { + "user": "0x0000000000000000000000000000000000000001", + "inputToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "outputToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "inputAmt": 1000000000, + "userAmtOut": 500000000000000000, + "recipient": "0x0000000000000000000000000000000000000002", + "deadline": 1700000000, + "nonce": 1 + }, + "signature": "AQIDBA==" + }` + + req := httptest.NewRequest(http.MethodPost, "/fastswap", strings.NewReader(reqJSON)) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + + handler(w, req) + + require.Equal(t, http.StatusOK, w.Code) + + var result fastswap.SwapResult + err := json.NewDecoder(w.Body).Decode(&result) + require.NoError(t, err) + require.Equal(t, "success", result.Status) +} + +func TestHandler_MethodNotAllowed(t *testing.T) { + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService("", "", common.Address{}, 1, logger) + handler := svc.Handler() + + req := httptest.NewRequest(http.MethodGet, "/fastswap", nil) + w := httptest.NewRecorder() + + handler(w, req) + + require.Equal(t, http.StatusMethodNotAllowed, w.Code) +} + +func TestHandler_MissingFields(t *testing.T) { + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService("", "", common.Address{}, 1, logger) + handler := svc.Handler() + + tests := []struct { + name string + reqBody map[string]interface{} + expected string + }{ + { + name: "missing user", + reqBody: map[string]interface{}{"intent": map[string]interface{}{}}, + expected: "missing intent.user", + }, + { + name: "missing inputToken", + reqBody: map[string]interface{}{ + "intent": map[string]interface{}{ + "user": "0x1234567890123456789012345678901234567890", + }, + }, + expected: "missing intent.inputToken", + }, + { + name: "missing outputToken", + reqBody: map[string]interface{}{ + "intent": map[string]interface{}{ + "user": "0x1234567890123456789012345678901234567890", + "inputToken": "0x1234567890123456789012345678901234567890", + }, + }, + expected: "missing intent.outputToken", + }, + { + name: "missing signature", + reqBody: map[string]interface{}{ + "intent": map[string]interface{}{ + "user": "0x1234567890123456789012345678901234567890", + "inputToken": "0x1234567890123456789012345678901234567890", + "outputToken": "0x1234567890123456789012345678901234567890", + "inputAmt": 1000, // Use numeric value, not string + }, + }, + expected: "missing signature", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + bodyBytes, _ := json.Marshal(tc.reqBody) + req := httptest.NewRequest(http.MethodPost, "/fastswap", bytes.NewReader(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + + handler(w, req) + + require.Equal(t, http.StatusBadRequest, w.Code) + require.Contains(t, w.Body.String(), tc.expected) + }) + } +} + +func TestETHHandler(t *testing.T) { + barterResp := newTestBarterResponse() + srv := setupTestServer(t, barterResp) + defer srv.Close() + + logger := util.NewTestLogger(os.Stdout) + settlementAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") + svc := fastswap.NewService( + srv.URL, + "test-api-key", + settlementAddr, + 1, + logger, + ) + + handler := svc.ETHHandler() + + // Use raw JSON with proper big.Int encoding (numbers, not quoted strings) + reqJSON := `{ + "outputToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "inputAmt": 1000000000000000000, + "userAmtOut": 2000000000, + "sender": "0x0000000000000000000000000000000000000001", + "deadline": 1700000000 + }` + + req := httptest.NewRequest(http.MethodPost, "/fastswap/eth", strings.NewReader(reqJSON)) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + + handler(w, req) + + require.Equal(t, http.StatusOK, w.Code) + + var result fastswap.ETHSwapResponse + err := json.NewDecoder(w.Body).Decode(&result) + require.NoError(t, err) + require.Equal(t, "success", result.Status) + require.Equal(t, settlementAddr.Hex(), result.To) +} + +func TestETHHandler_MethodNotAllowed(t *testing.T) { + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService("", "", common.Address{}, 1, logger) + handler := svc.ETHHandler() + + req := httptest.NewRequest(http.MethodGet, "/fastswap/eth", nil) + w := httptest.NewRecorder() + + handler(w, req) + + require.Equal(t, http.StatusMethodNotAllowed, w.Code) +} + +func TestETHHandler_MissingFields(t *testing.T) { + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService("", "", common.Address{}, 1, logger) + handler := svc.ETHHandler() + + tests := []struct { + name string + reqBody map[string]interface{} + expected string + }{ + { + name: "missing sender", + reqBody: map[string]interface{}{}, + expected: "missing sender", + }, + { + name: "missing outputToken", + reqBody: map[string]interface{}{ + "sender": "0x1234567890123456789012345678901234567890", + }, + expected: "missing outputToken", + }, + { + name: "invalid inputAmt", + reqBody: map[string]interface{}{ + "sender": "0x1234567890123456789012345678901234567890", + "outputToken": "0x1234567890123456789012345678901234567890", + }, + expected: "invalid inputAmt", + }, + { + name: "invalid userAmtOut", + reqBody: map[string]interface{}{ + "sender": "0x1234567890123456789012345678901234567890", + "outputToken": "0x1234567890123456789012345678901234567890", + "inputAmt": 1000, // Use numeric value + }, + expected: "invalid userAmtOut", + }, + { + name: "invalid deadline", + reqBody: map[string]interface{}{ + "sender": "0x1234567890123456789012345678901234567890", + "outputToken": "0x1234567890123456789012345678901234567890", + "inputAmt": 1000, // Use numeric value + "userAmtOut": 900, // Use numeric value + }, + expected: "invalid deadline", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + bodyBytes, _ := json.Marshal(tc.reqBody) + req := httptest.NewRequest(http.MethodPost, "/fastswap/eth", bytes.NewReader(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + + handler(w, req) + + require.Equal(t, http.StatusBadRequest, w.Code) + require.Contains(t, w.Body.String(), tc.expected) + }) + } +} + +func TestBarterAPIError(t *testing.T) { + srv := httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "internal server error", http.StatusInternalServerError) + }), + ) + defer srv.Close() + + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService( + srv.URL, + "test-api-key", + common.HexToAddress("0x1234567890123456789012345678901234567890"), + 1, + logger, + ) + + intent := fastswap.Intent{ + User: common.HexToAddress("0xUserAddress"), + InputToken: common.HexToAddress("0xInputToken"), + OutputToken: common.HexToAddress("0xOutputToken"), + InputAmt: big.NewInt(1000), + UserAmtOut: big.NewInt(900), + Deadline: big.NewInt(1700000000), + Nonce: big.NewInt(1), + } + + ctx := context.Background() + resp, err := svc.CallBarterAPI(ctx, intent) + + require.Error(t, err) + require.Nil(t, resp) + require.Contains(t, err.Error(), "barter API error") +} + +func TestIntentTupleEncoding(t *testing.T) { + // Verify that Intent can be used with the ABI encoding + logger := util.NewTestLogger(os.Stdout) + svc := fastswap.NewService( + "https://api.barter.com", + "test-api-key", + common.HexToAddress("0x1234567890123456789012345678901234567890"), + 1, + logger, + ) + + intent := fastswap.Intent{ + User: common.HexToAddress("0x1111111111111111111111111111111111111111"), + InputToken: common.HexToAddress("0x2222222222222222222222222222222222222222"), + OutputToken: common.HexToAddress("0x3333333333333333333333333333333333333333"), + InputAmt: big.NewInt(1000000000000000000), + UserAmtOut: big.NewInt(500000000000000000), + Recipient: common.HexToAddress("0x4444444444444444444444444444444444444444"), + Deadline: big.NewInt(1700000000), + Nonce: big.NewInt(42), + } + + barterResp := &fastswap.BarterResponse{ + To: common.HexToAddress("0x5555555555555555555555555555555555555555"), + GasLimit: "200000", + Value: "0", + Data: "0x" + hex.EncodeToString([]byte("test swap data")), + } + + signature := make([]byte, 65) + for i := range signature { + signature[i] = byte(i) + } + + calldata, err := svc.BuildExecuteTx(intent, signature, barterResp) + require.NoError(t, err) + require.NotEmpty(t, calldata) + + // The function selector for executeWithPermit should be at the beginning + // We can verify the calldata is properly formed by checking its length + // Function selector (4 bytes) + encoded params + require.True(t, len(calldata) > 4) +} diff --git a/tools/preconf-rpc/main.go b/tools/preconf-rpc/main.go index f1fe4add8..aa36607d8 100644 --- a/tools/preconf-rpc/main.go +++ b/tools/preconf-rpc/main.go @@ -320,6 +320,43 @@ var ( Usage: "Explorer App Code", EnvVars: []string{"PRECONF_RPC_EXPLORER_APPCODE"}, } + + // FastSwap configuration + optionBarterAPIURL = &cli.StringFlag{ + Name: "barter-api-url", + Usage: "Barter API URL for swap routing", + EnvVars: []string{"PRECONF_RPC_BARTER_API_URL"}, + } + + optionBarterAPIKey = &cli.StringFlag{ + Name: "barter-api-key", + Usage: "Barter API key", + EnvVars: []string{"PRECONF_RPC_BARTER_API_KEY"}, + } + + optionFastSettlementAddress = &cli.StringFlag{ + Name: "fast-settlement-address", + Usage: "FastSettlementV3 contract address", + EnvVars: []string{"PRECONF_RPC_FAST_SETTLEMENT_ADDRESS"}, + Action: func(ctx *cli.Context, s string) error { + if s != "" && !common.IsHexAddress(s) { + return fmt.Errorf("invalid fast-settlement-address: %s", s) + } + return nil + }, + } + + optionFastSwapKeystorePath = &cli.StringFlag{ + Name: "fastswap-keystore-path", + Usage: "Path to the FastSwap executor keystore file (separate wallet for FastSwap transactions)", + EnvVars: []string{"PRECONF_RPC_FASTSWAP_KEYSTORE_PATH"}, + } + + optionFastSwapKeystorePassword = &cli.StringFlag{ + Name: "fastswap-keystore-password", + Usage: "Password for the FastSwap executor keystore", + EnvVars: []string{"PRECONF_RPC_FASTSWAP_KEYSTORE_PASSWORD"}, + } ) func main() { @@ -367,6 +404,11 @@ func main() { optionPointsAPIURL, optionPointsAPIKey, optionL1ReceiptsRPCUrl, + optionBarterAPIURL, + optionBarterAPIKey, + optionFastSettlementAddress, + optionFastSwapKeystorePath, + optionFastSwapKeystorePassword, }, Action: func(c *cli.Context) error { logger, err := util.NewLogger( @@ -422,6 +464,19 @@ func main() { return fmt.Errorf("failed to create signer: %w", err) } + // Load separate FastSwap signer if configured + var fastSwapSigner keysigner.KeySigner + if c.String(optionFastSwapKeystorePath.Name) != "" { + fastSwapSigner, err = keysigner.NewKeystoreSigner( + c.String(optionFastSwapKeystorePath.Name), + c.String(optionFastSwapKeystorePassword.Name), + ) + if err != nil { + return fmt.Errorf("failed to create FastSwap signer: %w", err) + } + logger.Info("FastSwap executor wallet loaded", "address", fastSwapSigner.GetAddress().Hex()) + } + l1ReceiptsURL := c.String(optionL1ReceiptsRPCUrl.Name) if l1ReceiptsURL == "" { l1ReceiptsURL = c.String(optionL1RPCHTTPUrl.Name) @@ -468,6 +523,10 @@ func main() { PointsAPIURL: c.String(optionPointsAPIURL.Name), PointsAPIKey: c.String(optionPointsAPIKey.Name), L1ReceiptsRPCUrl: l1ReceiptsURL, + BarterAPIURL: c.String(optionBarterAPIURL.Name), + BarterAPIKey: c.String(optionBarterAPIKey.Name), + FastSettlementAddress: common.HexToAddress(c.String(optionFastSettlementAddress.Name)), + FastSwapSigner: fastSwapSigner, } s, err := service.New(&config) diff --git a/tools/preconf-rpc/service/service.go b/tools/preconf-rpc/service/service.go index f37515c2b..45d979555 100644 --- a/tools/preconf-rpc/service/service.go +++ b/tools/preconf-rpc/service/service.go @@ -28,6 +28,7 @@ import ( bidder "github.com/primev/mev-commit/tools/preconf-rpc/bidder" "github.com/primev/mev-commit/tools/preconf-rpc/blocktracker" explorersubmitter "github.com/primev/mev-commit/tools/preconf-rpc/explorer-submitter" + "github.com/primev/mev-commit/tools/preconf-rpc/fastswap" "github.com/primev/mev-commit/tools/preconf-rpc/handlers" "github.com/primev/mev-commit/tools/preconf-rpc/notifier" "github.com/primev/mev-commit/tools/preconf-rpc/points" @@ -88,6 +89,11 @@ type Config struct { PointsAPIURL string PointsAPIKey string L1ReceiptsRPCUrl string + // FastSwap config + BarterAPIURL string + BarterAPIKey string + FastSettlementAddress common.Address + FastSwapSigner keysigner.KeySigner // Separate wallet for FastSwap executor } type Service struct { @@ -413,6 +419,34 @@ func New(config *Config) (*Service, error) { registerAdminAPIs(mux, config.Token, sndr, rpcstore) + // Register FastSwap endpoints if configured + if config.BarterAPIURL != "" { + fastswapSvc := fastswap.NewService( + config.BarterAPIURL, + config.BarterAPIKey, + config.FastSettlementAddress, + l1ChainID.Uint64(), + config.Logger.With("module", "fastswap"), + ) + + // Wire executor dependencies for Path 1 (executor-submitted transactions) + // Uses separate FastSwapSigner to isolate from main operational wallet + if config.FastSwapSigner != nil { + fastswapSvc.SetExecutorDeps(config.FastSwapSigner, sndr, blockTracker) + config.Logger.Info("FastSwap Path 1 enabled", + "executorAddress", config.FastSwapSigner.GetAddress().Hex(), + ) + } else { + config.Logger.Warn("FastSwap Path 1 disabled - no fastswap-keystore-path provided") + } + + mux.HandleFunc("POST /fastswap", fastswapSvc.Handler()) + mux.HandleFunc("POST /fastswap/eth", fastswapSvc.ETHHandler()) + config.Logger.Info("FastSwap endpoints registered", + "settlementAddress", config.FastSettlementAddress.Hex(), + ) + } + srv := http.Server{ Addr: fmt.Sprintf(":%d", config.HTTPPort), Handler: mux, From 08337a936958ae14c9326d4d4d3404d65a4c9346 Mon Sep 17 00:00:00 2001 From: owen-eth Date: Mon, 26 Jan 2026 19:52:46 -0500 Subject: [PATCH 2/4] linting error --- tools/preconf-rpc/fastswap/fastswap.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tools/preconf-rpc/fastswap/fastswap.go b/tools/preconf-rpc/fastswap/fastswap.go index 6ac23c4e5..8683a8335 100644 --- a/tools/preconf-rpc/fastswap/fastswap.go +++ b/tools/preconf-rpc/fastswap/fastswap.go @@ -381,16 +381,7 @@ func (s *Service) BuildExecuteTx(intent Intent, signature []byte, barter *Barter value.SetString(barter.Value, 10) } - intentTuple := IntentTuple{ - User: intent.User, - InputToken: intent.InputToken, - OutputToken: intent.OutputToken, - InputAmt: intent.InputAmt, - UserAmtOut: intent.UserAmtOut, - Recipient: intent.Recipient, - Deadline: intent.Deadline, - Nonce: intent.Nonce, - } + intentTuple := IntentTuple(intent) swapCallTuple := SwapCallTuple{ To: barter.To, From 1948b39012fb6e820763ad7fa66eaab91de00cc6 Mon Sep 17 00:00:00 2001 From: owen-eth Date: Tue, 27 Jan 2026 12:53:58 -0500 Subject: [PATCH 3/4] add and use go bindings, minor changes --- contracts-abi/abi/FastSettlementV3.abi | 865 +++++++ .../FastSettlementV3/FastSettlementV3.go | 1984 +++++++++++++++++ tools/preconf-rpc/fastswap/fastswap.go | 338 +-- tools/preconf-rpc/fastswap/fastswap_test.go | 99 +- 4 files changed, 3017 insertions(+), 269 deletions(-) create mode 100644 contracts-abi/abi/FastSettlementV3.abi create mode 100644 contracts-abi/clients/FastSettlementV3/FastSettlementV3.go diff --git a/contracts-abi/abi/FastSettlementV3.abi b/contracts-abi/abi/FastSettlementV3.abi new file mode 100644 index 000000000..d228e23d8 --- /dev/null +++ b/contracts-abi/abi/FastSettlementV3.abi @@ -0,0 +1,865 @@ +[ + { + "type": "constructor", + "inputs": [ + { + "name": "_permit2", + "type": "address", + "internalType": "address" + }, + { + "name": "_weth", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "INTENT_TYPEHASH", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PERMIT2", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IPermit2" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "UPGRADE_INTERFACE_VERSION", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "WETH", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IWETH" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "WITNESS_TYPE_STRING", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "acceptOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "allowedSwapTargets", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "executeWithETH", + "inputs": [ + { + "name": "intent", + "type": "tuple", + "internalType": "struct IFastSettlementV3.Intent", + "components": [ + { + "name": "user", + "type": "address", + "internalType": "address" + }, + { + "name": "inputToken", + "type": "address", + "internalType": "address" + }, + { + "name": "outputToken", + "type": "address", + "internalType": "address" + }, + { + "name": "inputAmt", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "userAmtOut", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "recipient", + "type": "address", + "internalType": "address" + }, + { + "name": "deadline", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "nonce", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "swapData", + "type": "tuple", + "internalType": "struct IFastSettlementV3.SwapCall", + "components": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "outputs": [ + { + "name": "received", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "surplus", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "executeWithPermit", + "inputs": [ + { + "name": "intent", + "type": "tuple", + "internalType": "struct IFastSettlementV3.Intent", + "components": [ + { + "name": "user", + "type": "address", + "internalType": "address" + }, + { + "name": "inputToken", + "type": "address", + "internalType": "address" + }, + { + "name": "outputToken", + "type": "address", + "internalType": "address" + }, + { + "name": "inputAmt", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "userAmtOut", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "recipient", + "type": "address", + "internalType": "address" + }, + { + "name": "deadline", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "nonce", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "signature", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "swapData", + "type": "tuple", + "internalType": "struct IFastSettlementV3.SwapCall", + "components": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "outputs": [ + { + "name": "received", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "surplus", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "executor", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_executor", + "type": "address", + "internalType": "address" + }, + { + "name": "_treasury", + "type": "address", + "internalType": "address" + }, + { + "name": "_initialSwapTargets", + "type": "address[]", + "internalType": "address[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "pendingOwner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "proxiableUUID", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "rescueTokens", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setExecutor", + "inputs": [ + { + "name": "_newExecutor", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setSwapTargets", + "inputs": [ + { + "name": "targets", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "allowed", + "type": "bool[]", + "internalType": "bool[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setTreasury", + "inputs": [ + { + "name": "_newTreasury", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "treasury", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "newImplementation", + "type": "address", + "internalType": "address" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "ExecutorUpdated", + "inputs": [ + { + "name": "oldExecutor", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newExecutor", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint64", + "indexed": false, + "internalType": "uint64" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "IntentExecuted", + "inputs": [ + { + "name": "user", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "inputToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "outputToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "inputAmt", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "userAmtOut", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "received", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "surplus", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferStarted", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "SwapTargetsUpdated", + "inputs": [ + { + "name": "targets", + "type": "address[]", + "indexed": false, + "internalType": "address[]" + }, + { + "name": "allowed", + "type": "bool[]", + "indexed": false, + "internalType": "bool[]" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TreasuryUpdated", + "inputs": [ + { + "name": "oldTreasury", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newTreasury", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AddressEmptyCode", + "inputs": [ + { + "name": "target", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ArrayLengthMismatch", + "inputs": [] + }, + { + "type": "error", + "name": "BadCallTarget", + "inputs": [] + }, + { + "type": "error", + "name": "BadExecutor", + "inputs": [] + }, + { + "type": "error", + "name": "BadInputAmt", + "inputs": [] + }, + { + "type": "error", + "name": "BadInputToken", + "inputs": [] + }, + { + "type": "error", + "name": "BadNonce", + "inputs": [] + }, + { + "type": "error", + "name": "BadRecipient", + "inputs": [] + }, + { + "type": "error", + "name": "BadTreasury", + "inputs": [] + }, + { + "type": "error", + "name": "BadUserAmtOut", + "inputs": [] + }, + { + "type": "error", + "name": "ERC1967InvalidImplementation", + "inputs": [ + { + "name": "implementation", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ERC1967NonPayable", + "inputs": [] + }, + { + "type": "error", + "name": "ExpectedETHInput", + "inputs": [] + }, + { + "type": "error", + "name": "FailedCall", + "inputs": [] + }, + { + "type": "error", + "name": "InsufficientBalance", + "inputs": [ + { + "name": "balance", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "needed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InsufficientOut", + "inputs": [ + { + "name": "received", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "userAmtOut", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "IntentExpired", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidETHAmount", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidInitialization", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidPermit2", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidWETH", + "inputs": [] + }, + { + "type": "error", + "name": "NotInitializing", + "inputs": [] + }, + { + "type": "error", + "name": "OwnableInvalidOwner", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "OwnableUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ReentrancyGuardReentrantCall", + "inputs": [] + }, + { + "type": "error", + "name": "SafeERC20FailedOperation", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "UUPSUnauthorizedCallContext", + "inputs": [] + }, + { + "type": "error", + "name": "UUPSUnsupportedProxiableUUID", + "inputs": [ + { + "name": "slot", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "UnauthorizedCaller", + "inputs": [] + }, + { + "type": "error", + "name": "UnauthorizedExecutor", + "inputs": [] + }, + { + "type": "error", + "name": "UnauthorizedSwapTarget", + "inputs": [] + } +] diff --git a/contracts-abi/clients/FastSettlementV3/FastSettlementV3.go b/contracts-abi/clients/FastSettlementV3/FastSettlementV3.go new file mode 100644 index 000000000..f8af0b1ff --- /dev/null +++ b/contracts-abi/clients/FastSettlementV3/FastSettlementV3.go @@ -0,0 +1,1984 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package fastsettlementv3 + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// IFastSettlementV3Intent is an auto generated low-level Go binding around an user-defined struct. +type IFastSettlementV3Intent struct { + User common.Address + InputToken common.Address + OutputToken common.Address + InputAmt *big.Int + UserAmtOut *big.Int + Recipient common.Address + Deadline *big.Int + Nonce *big.Int +} + +// IFastSettlementV3SwapCall is an auto generated low-level Go binding around an user-defined struct. +type IFastSettlementV3SwapCall struct { + To common.Address + Value *big.Int + Data []byte +} + +// Fastsettlementv3MetaData contains all meta data concerning the Fastsettlementv3 contract. +var Fastsettlementv3MetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_permit2\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_weth\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"INTENT_TYPEHASH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PERMIT2\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIPermit2\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"UPGRADE_INTERFACE_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WETH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWETH\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WITNESS_TYPE_STRING\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowedSwapTargets\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"executeWithETH\",\"inputs\":[{\"name\":\"intent\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.Intent\",\"components\":[{\"name\":\"user\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"swapData\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.SwapCall\",\"components\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"executeWithPermit\",\"inputs\":[{\"name\":\"intent\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.Intent\",\"components\":[{\"name\":\"user\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"swapData\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.SwapCall\",\"components\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"executor\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_executor\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_treasury\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_initialSwapTargets\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"pendingOwner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proxiableUUID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"rescueTokens\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setExecutor\",\"inputs\":[{\"name\":\"_newExecutor\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setSwapTargets\",\"inputs\":[{\"name\":\"targets\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"allowed\",\"type\":\"bool[]\",\"internalType\":\"bool[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setTreasury\",\"inputs\":[{\"name\":\"_newTreasury\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"treasury\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"ExecutorUpdated\",\"inputs\":[{\"name\":\"oldExecutor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newExecutor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"IntentExecuted\",\"inputs\":[{\"name\":\"user\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"received\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferStarted\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SwapTargetsUpdated\",\"inputs\":[{\"name\":\"targets\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"allowed\",\"type\":\"bool[]\",\"indexed\":false,\"internalType\":\"bool[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TreasuryUpdated\",\"inputs\":[{\"name\":\"oldTreasury\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newTreasury\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ArrayLengthMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadCallTarget\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadExecutor\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadInputAmt\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadInputToken\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadNonce\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadRecipient\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadTreasury\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadUserAmtOut\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ERC1967InvalidImplementation\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967NonPayable\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ExpectedETHInput\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBalance\",\"inputs\":[{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InsufficientOut\",\"inputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"IntentExpired\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidETHAmount\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPermit2\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidWETH\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SafeERC20FailedOperation\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UUPSUnauthorizedCallContext\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UUPSUnsupportedProxiableUUID\",\"inputs\":[{\"name\":\"slot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedExecutor\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedSwapTarget\",\"inputs\":[]}]", +} + +// Fastsettlementv3ABI is the input ABI used to generate the binding from. +// Deprecated: Use Fastsettlementv3MetaData.ABI instead. +var Fastsettlementv3ABI = Fastsettlementv3MetaData.ABI + +// Fastsettlementv3 is an auto generated Go binding around an Ethereum contract. +type Fastsettlementv3 struct { + Fastsettlementv3Caller // Read-only binding to the contract + Fastsettlementv3Transactor // Write-only binding to the contract + Fastsettlementv3Filterer // Log filterer for contract events +} + +// Fastsettlementv3Caller is an auto generated read-only Go binding around an Ethereum contract. +type Fastsettlementv3Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Fastsettlementv3Transactor is an auto generated write-only Go binding around an Ethereum contract. +type Fastsettlementv3Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Fastsettlementv3Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Fastsettlementv3Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Fastsettlementv3Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Fastsettlementv3Session struct { + Contract *Fastsettlementv3 // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Fastsettlementv3CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Fastsettlementv3CallerSession struct { + Contract *Fastsettlementv3Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Fastsettlementv3TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Fastsettlementv3TransactorSession struct { + Contract *Fastsettlementv3Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Fastsettlementv3Raw is an auto generated low-level Go binding around an Ethereum contract. +type Fastsettlementv3Raw struct { + Contract *Fastsettlementv3 // Generic contract binding to access the raw methods on +} + +// Fastsettlementv3CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Fastsettlementv3CallerRaw struct { + Contract *Fastsettlementv3Caller // Generic read-only contract binding to access the raw methods on +} + +// Fastsettlementv3TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Fastsettlementv3TransactorRaw struct { + Contract *Fastsettlementv3Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewFastsettlementv3 creates a new instance of Fastsettlementv3, bound to a specific deployed contract. +func NewFastsettlementv3(address common.Address, backend bind.ContractBackend) (*Fastsettlementv3, error) { + contract, err := bindFastsettlementv3(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Fastsettlementv3{Fastsettlementv3Caller: Fastsettlementv3Caller{contract: contract}, Fastsettlementv3Transactor: Fastsettlementv3Transactor{contract: contract}, Fastsettlementv3Filterer: Fastsettlementv3Filterer{contract: contract}}, nil +} + +// NewFastsettlementv3Caller creates a new read-only instance of Fastsettlementv3, bound to a specific deployed contract. +func NewFastsettlementv3Caller(address common.Address, caller bind.ContractCaller) (*Fastsettlementv3Caller, error) { + contract, err := bindFastsettlementv3(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Fastsettlementv3Caller{contract: contract}, nil +} + +// NewFastsettlementv3Transactor creates a new write-only instance of Fastsettlementv3, bound to a specific deployed contract. +func NewFastsettlementv3Transactor(address common.Address, transactor bind.ContractTransactor) (*Fastsettlementv3Transactor, error) { + contract, err := bindFastsettlementv3(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Fastsettlementv3Transactor{contract: contract}, nil +} + +// NewFastsettlementv3Filterer creates a new log filterer instance of Fastsettlementv3, bound to a specific deployed contract. +func NewFastsettlementv3Filterer(address common.Address, filterer bind.ContractFilterer) (*Fastsettlementv3Filterer, error) { + contract, err := bindFastsettlementv3(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Fastsettlementv3Filterer{contract: contract}, nil +} + +// bindFastsettlementv3 binds a generic wrapper to an already deployed contract. +func bindFastsettlementv3(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Fastsettlementv3MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Fastsettlementv3 *Fastsettlementv3Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Fastsettlementv3.Contract.Fastsettlementv3Caller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Fastsettlementv3 *Fastsettlementv3Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.Fastsettlementv3Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Fastsettlementv3 *Fastsettlementv3Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.Fastsettlementv3Transactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Fastsettlementv3 *Fastsettlementv3CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Fastsettlementv3.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Fastsettlementv3 *Fastsettlementv3TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Fastsettlementv3 *Fastsettlementv3TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.contract.Transact(opts, method, params...) +} + +// INTENTTYPEHASH is a free data retrieval call binding the contract method 0xb082a274. +// +// Solidity: function INTENT_TYPEHASH() view returns(bytes32) +func (_Fastsettlementv3 *Fastsettlementv3Caller) INTENTTYPEHASH(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "INTENT_TYPEHASH") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// INTENTTYPEHASH is a free data retrieval call binding the contract method 0xb082a274. +// +// Solidity: function INTENT_TYPEHASH() view returns(bytes32) +func (_Fastsettlementv3 *Fastsettlementv3Session) INTENTTYPEHASH() ([32]byte, error) { + return _Fastsettlementv3.Contract.INTENTTYPEHASH(&_Fastsettlementv3.CallOpts) +} + +// INTENTTYPEHASH is a free data retrieval call binding the contract method 0xb082a274. +// +// Solidity: function INTENT_TYPEHASH() view returns(bytes32) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) INTENTTYPEHASH() ([32]byte, error) { + return _Fastsettlementv3.Contract.INTENTTYPEHASH(&_Fastsettlementv3.CallOpts) +} + +// PERMIT2 is a free data retrieval call binding the contract method 0x6afdd850. +// +// Solidity: function PERMIT2() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Caller) PERMIT2(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "PERMIT2") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// PERMIT2 is a free data retrieval call binding the contract method 0x6afdd850. +// +// Solidity: function PERMIT2() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Session) PERMIT2() (common.Address, error) { + return _Fastsettlementv3.Contract.PERMIT2(&_Fastsettlementv3.CallOpts) +} + +// PERMIT2 is a free data retrieval call binding the contract method 0x6afdd850. +// +// Solidity: function PERMIT2() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) PERMIT2() (common.Address, error) { + return _Fastsettlementv3.Contract.PERMIT2(&_Fastsettlementv3.CallOpts) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_Fastsettlementv3 *Fastsettlementv3Caller) UPGRADEINTERFACEVERSION(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "UPGRADE_INTERFACE_VERSION") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_Fastsettlementv3 *Fastsettlementv3Session) UPGRADEINTERFACEVERSION() (string, error) { + return _Fastsettlementv3.Contract.UPGRADEINTERFACEVERSION(&_Fastsettlementv3.CallOpts) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) UPGRADEINTERFACEVERSION() (string, error) { + return _Fastsettlementv3.Contract.UPGRADEINTERFACEVERSION(&_Fastsettlementv3.CallOpts) +} + +// WETH is a free data retrieval call binding the contract method 0xad5c4648. +// +// Solidity: function WETH() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Caller) WETH(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "WETH") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// WETH is a free data retrieval call binding the contract method 0xad5c4648. +// +// Solidity: function WETH() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Session) WETH() (common.Address, error) { + return _Fastsettlementv3.Contract.WETH(&_Fastsettlementv3.CallOpts) +} + +// WETH is a free data retrieval call binding the contract method 0xad5c4648. +// +// Solidity: function WETH() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) WETH() (common.Address, error) { + return _Fastsettlementv3.Contract.WETH(&_Fastsettlementv3.CallOpts) +} + +// WITNESSTYPESTRING is a free data retrieval call binding the contract method 0x156e2152. +// +// Solidity: function WITNESS_TYPE_STRING() view returns(string) +func (_Fastsettlementv3 *Fastsettlementv3Caller) WITNESSTYPESTRING(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "WITNESS_TYPE_STRING") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// WITNESSTYPESTRING is a free data retrieval call binding the contract method 0x156e2152. +// +// Solidity: function WITNESS_TYPE_STRING() view returns(string) +func (_Fastsettlementv3 *Fastsettlementv3Session) WITNESSTYPESTRING() (string, error) { + return _Fastsettlementv3.Contract.WITNESSTYPESTRING(&_Fastsettlementv3.CallOpts) +} + +// WITNESSTYPESTRING is a free data retrieval call binding the contract method 0x156e2152. +// +// Solidity: function WITNESS_TYPE_STRING() view returns(string) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) WITNESSTYPESTRING() (string, error) { + return _Fastsettlementv3.Contract.WITNESSTYPESTRING(&_Fastsettlementv3.CallOpts) +} + +// AllowedSwapTargets is a free data retrieval call binding the contract method 0x1fa1fe36. +// +// Solidity: function allowedSwapTargets(address ) view returns(bool) +func (_Fastsettlementv3 *Fastsettlementv3Caller) AllowedSwapTargets(opts *bind.CallOpts, arg0 common.Address) (bool, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "allowedSwapTargets", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// AllowedSwapTargets is a free data retrieval call binding the contract method 0x1fa1fe36. +// +// Solidity: function allowedSwapTargets(address ) view returns(bool) +func (_Fastsettlementv3 *Fastsettlementv3Session) AllowedSwapTargets(arg0 common.Address) (bool, error) { + return _Fastsettlementv3.Contract.AllowedSwapTargets(&_Fastsettlementv3.CallOpts, arg0) +} + +// AllowedSwapTargets is a free data retrieval call binding the contract method 0x1fa1fe36. +// +// Solidity: function allowedSwapTargets(address ) view returns(bool) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) AllowedSwapTargets(arg0 common.Address) (bool, error) { + return _Fastsettlementv3.Contract.AllowedSwapTargets(&_Fastsettlementv3.CallOpts, arg0) +} + +// Executor is a free data retrieval call binding the contract method 0xc34c08e5. +// +// Solidity: function executor() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Caller) Executor(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "executor") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Executor is a free data retrieval call binding the contract method 0xc34c08e5. +// +// Solidity: function executor() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Session) Executor() (common.Address, error) { + return _Fastsettlementv3.Contract.Executor(&_Fastsettlementv3.CallOpts) +} + +// Executor is a free data retrieval call binding the contract method 0xc34c08e5. +// +// Solidity: function executor() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) Executor() (common.Address, error) { + return _Fastsettlementv3.Contract.Executor(&_Fastsettlementv3.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Caller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Session) Owner() (common.Address, error) { + return _Fastsettlementv3.Contract.Owner(&_Fastsettlementv3.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) Owner() (common.Address, error) { + return _Fastsettlementv3.Contract.Owner(&_Fastsettlementv3.CallOpts) +} + +// PendingOwner is a free data retrieval call binding the contract method 0xe30c3978. +// +// Solidity: function pendingOwner() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Caller) PendingOwner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "pendingOwner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// PendingOwner is a free data retrieval call binding the contract method 0xe30c3978. +// +// Solidity: function pendingOwner() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Session) PendingOwner() (common.Address, error) { + return _Fastsettlementv3.Contract.PendingOwner(&_Fastsettlementv3.CallOpts) +} + +// PendingOwner is a free data retrieval call binding the contract method 0xe30c3978. +// +// Solidity: function pendingOwner() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) PendingOwner() (common.Address, error) { + return _Fastsettlementv3.Contract.PendingOwner(&_Fastsettlementv3.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_Fastsettlementv3 *Fastsettlementv3Caller) ProxiableUUID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "proxiableUUID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_Fastsettlementv3 *Fastsettlementv3Session) ProxiableUUID() ([32]byte, error) { + return _Fastsettlementv3.Contract.ProxiableUUID(&_Fastsettlementv3.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) ProxiableUUID() ([32]byte, error) { + return _Fastsettlementv3.Contract.ProxiableUUID(&_Fastsettlementv3.CallOpts) +} + +// Treasury is a free data retrieval call binding the contract method 0x61d027b3. +// +// Solidity: function treasury() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Caller) Treasury(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Fastsettlementv3.contract.Call(opts, &out, "treasury") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Treasury is a free data retrieval call binding the contract method 0x61d027b3. +// +// Solidity: function treasury() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3Session) Treasury() (common.Address, error) { + return _Fastsettlementv3.Contract.Treasury(&_Fastsettlementv3.CallOpts) +} + +// Treasury is a free data retrieval call binding the contract method 0x61d027b3. +// +// Solidity: function treasury() view returns(address) +func (_Fastsettlementv3 *Fastsettlementv3CallerSession) Treasury() (common.Address, error) { + return _Fastsettlementv3.Contract.Treasury(&_Fastsettlementv3.CallOpts) +} + +// AcceptOwnership is a paid mutator transaction binding the contract method 0x79ba5097. +// +// Solidity: function acceptOwnership() returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "acceptOwnership") +} + +// AcceptOwnership is a paid mutator transaction binding the contract method 0x79ba5097. +// +// Solidity: function acceptOwnership() returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) AcceptOwnership() (*types.Transaction, error) { + return _Fastsettlementv3.Contract.AcceptOwnership(&_Fastsettlementv3.TransactOpts) +} + +// AcceptOwnership is a paid mutator transaction binding the contract method 0x79ba5097. +// +// Solidity: function acceptOwnership() returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _Fastsettlementv3.Contract.AcceptOwnership(&_Fastsettlementv3.TransactOpts) +} + +// ExecuteWithETH is a paid mutator transaction binding the contract method 0x1fb7a307. +// +// Solidity: function executeWithETH((address,address,address,uint256,uint256,address,uint256,uint256) intent, (address,uint256,bytes) swapData) payable returns(uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3Transactor) ExecuteWithETH(opts *bind.TransactOpts, intent IFastSettlementV3Intent, swapData IFastSettlementV3SwapCall) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "executeWithETH", intent, swapData) +} + +// ExecuteWithETH is a paid mutator transaction binding the contract method 0x1fb7a307. +// +// Solidity: function executeWithETH((address,address,address,uint256,uint256,address,uint256,uint256) intent, (address,uint256,bytes) swapData) payable returns(uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3Session) ExecuteWithETH(intent IFastSettlementV3Intent, swapData IFastSettlementV3SwapCall) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.ExecuteWithETH(&_Fastsettlementv3.TransactOpts, intent, swapData) +} + +// ExecuteWithETH is a paid mutator transaction binding the contract method 0x1fb7a307. +// +// Solidity: function executeWithETH((address,address,address,uint256,uint256,address,uint256,uint256) intent, (address,uint256,bytes) swapData) payable returns(uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) ExecuteWithETH(intent IFastSettlementV3Intent, swapData IFastSettlementV3SwapCall) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.ExecuteWithETH(&_Fastsettlementv3.TransactOpts, intent, swapData) +} + +// ExecuteWithPermit is a paid mutator transaction binding the contract method 0x02c52a55. +// +// Solidity: function executeWithPermit((address,address,address,uint256,uint256,address,uint256,uint256) intent, bytes signature, (address,uint256,bytes) swapData) returns(uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3Transactor) ExecuteWithPermit(opts *bind.TransactOpts, intent IFastSettlementV3Intent, signature []byte, swapData IFastSettlementV3SwapCall) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "executeWithPermit", intent, signature, swapData) +} + +// ExecuteWithPermit is a paid mutator transaction binding the contract method 0x02c52a55. +// +// Solidity: function executeWithPermit((address,address,address,uint256,uint256,address,uint256,uint256) intent, bytes signature, (address,uint256,bytes) swapData) returns(uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3Session) ExecuteWithPermit(intent IFastSettlementV3Intent, signature []byte, swapData IFastSettlementV3SwapCall) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.ExecuteWithPermit(&_Fastsettlementv3.TransactOpts, intent, signature, swapData) +} + +// ExecuteWithPermit is a paid mutator transaction binding the contract method 0x02c52a55. +// +// Solidity: function executeWithPermit((address,address,address,uint256,uint256,address,uint256,uint256) intent, bytes signature, (address,uint256,bytes) swapData) returns(uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) ExecuteWithPermit(intent IFastSettlementV3Intent, signature []byte, swapData IFastSettlementV3SwapCall) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.ExecuteWithPermit(&_Fastsettlementv3.TransactOpts, intent, signature, swapData) +} + +// Initialize is a paid mutator transaction binding the contract method 0x77a24f36. +// +// Solidity: function initialize(address _executor, address _treasury, address[] _initialSwapTargets) returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) Initialize(opts *bind.TransactOpts, _executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "initialize", _executor, _treasury, _initialSwapTargets) +} + +// Initialize is a paid mutator transaction binding the contract method 0x77a24f36. +// +// Solidity: function initialize(address _executor, address _treasury, address[] _initialSwapTargets) returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) Initialize(_executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.Initialize(&_Fastsettlementv3.TransactOpts, _executor, _treasury, _initialSwapTargets) +} + +// Initialize is a paid mutator transaction binding the contract method 0x77a24f36. +// +// Solidity: function initialize(address _executor, address _treasury, address[] _initialSwapTargets) returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) Initialize(_executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.Initialize(&_Fastsettlementv3.TransactOpts, _executor, _treasury, _initialSwapTargets) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) RenounceOwnership() (*types.Transaction, error) { + return _Fastsettlementv3.Contract.RenounceOwnership(&_Fastsettlementv3.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Fastsettlementv3.Contract.RenounceOwnership(&_Fastsettlementv3.TransactOpts) +} + +// RescueTokens is a paid mutator transaction binding the contract method 0x57376198. +// +// Solidity: function rescueTokens(address token, uint256 amount) returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) RescueTokens(opts *bind.TransactOpts, token common.Address, amount *big.Int) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "rescueTokens", token, amount) +} + +// RescueTokens is a paid mutator transaction binding the contract method 0x57376198. +// +// Solidity: function rescueTokens(address token, uint256 amount) returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) RescueTokens(token common.Address, amount *big.Int) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.RescueTokens(&_Fastsettlementv3.TransactOpts, token, amount) +} + +// RescueTokens is a paid mutator transaction binding the contract method 0x57376198. +// +// Solidity: function rescueTokens(address token, uint256 amount) returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) RescueTokens(token common.Address, amount *big.Int) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.RescueTokens(&_Fastsettlementv3.TransactOpts, token, amount) +} + +// SetExecutor is a paid mutator transaction binding the contract method 0x1c3c0ea8. +// +// Solidity: function setExecutor(address _newExecutor) returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) SetExecutor(opts *bind.TransactOpts, _newExecutor common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "setExecutor", _newExecutor) +} + +// SetExecutor is a paid mutator transaction binding the contract method 0x1c3c0ea8. +// +// Solidity: function setExecutor(address _newExecutor) returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) SetExecutor(_newExecutor common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.SetExecutor(&_Fastsettlementv3.TransactOpts, _newExecutor) +} + +// SetExecutor is a paid mutator transaction binding the contract method 0x1c3c0ea8. +// +// Solidity: function setExecutor(address _newExecutor) returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) SetExecutor(_newExecutor common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.SetExecutor(&_Fastsettlementv3.TransactOpts, _newExecutor) +} + +// SetSwapTargets is a paid mutator transaction binding the contract method 0x57d6924c. +// +// Solidity: function setSwapTargets(address[] targets, bool[] allowed) returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) SetSwapTargets(opts *bind.TransactOpts, targets []common.Address, allowed []bool) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "setSwapTargets", targets, allowed) +} + +// SetSwapTargets is a paid mutator transaction binding the contract method 0x57d6924c. +// +// Solidity: function setSwapTargets(address[] targets, bool[] allowed) returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) SetSwapTargets(targets []common.Address, allowed []bool) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.SetSwapTargets(&_Fastsettlementv3.TransactOpts, targets, allowed) +} + +// SetSwapTargets is a paid mutator transaction binding the contract method 0x57d6924c. +// +// Solidity: function setSwapTargets(address[] targets, bool[] allowed) returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) SetSwapTargets(targets []common.Address, allowed []bool) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.SetSwapTargets(&_Fastsettlementv3.TransactOpts, targets, allowed) +} + +// SetTreasury is a paid mutator transaction binding the contract method 0xf0f44260. +// +// Solidity: function setTreasury(address _newTreasury) returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) SetTreasury(opts *bind.TransactOpts, _newTreasury common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "setTreasury", _newTreasury) +} + +// SetTreasury is a paid mutator transaction binding the contract method 0xf0f44260. +// +// Solidity: function setTreasury(address _newTreasury) returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) SetTreasury(_newTreasury common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.SetTreasury(&_Fastsettlementv3.TransactOpts, _newTreasury) +} + +// SetTreasury is a paid mutator transaction binding the contract method 0xf0f44260. +// +// Solidity: function setTreasury(address _newTreasury) returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) SetTreasury(_newTreasury common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.SetTreasury(&_Fastsettlementv3.TransactOpts, _newTreasury) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.TransferOwnership(&_Fastsettlementv3.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.TransferOwnership(&_Fastsettlementv3.TransactOpts, newOwner) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) UpgradeToAndCall(opts *bind.TransactOpts, newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "upgradeToAndCall", newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.UpgradeToAndCall(&_Fastsettlementv3.TransactOpts, newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.UpgradeToAndCall(&_Fastsettlementv3.TransactOpts, newImplementation, data) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Fastsettlementv3.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) Receive() (*types.Transaction, error) { + return _Fastsettlementv3.Contract.Receive(&_Fastsettlementv3.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) Receive() (*types.Transaction, error) { + return _Fastsettlementv3.Contract.Receive(&_Fastsettlementv3.TransactOpts) +} + +// Fastsettlementv3ExecutorUpdatedIterator is returned from FilterExecutorUpdated and is used to iterate over the raw logs and unpacked data for ExecutorUpdated events raised by the Fastsettlementv3 contract. +type Fastsettlementv3ExecutorUpdatedIterator struct { + Event *Fastsettlementv3ExecutorUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Fastsettlementv3ExecutorUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3ExecutorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3ExecutorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Fastsettlementv3ExecutorUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Fastsettlementv3ExecutorUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Fastsettlementv3ExecutorUpdated represents a ExecutorUpdated event raised by the Fastsettlementv3 contract. +type Fastsettlementv3ExecutorUpdated struct { + OldExecutor common.Address + NewExecutor common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterExecutorUpdated is a free log retrieval operation binding the contract event 0x0ef3c7eb9dbcf33ddf032f4cce366a07eda85eed03e3172e4a90c4cc16d57886. +// +// Solidity: event ExecutorUpdated(address indexed oldExecutor, address indexed newExecutor) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) FilterExecutorUpdated(opts *bind.FilterOpts, oldExecutor []common.Address, newExecutor []common.Address) (*Fastsettlementv3ExecutorUpdatedIterator, error) { + + var oldExecutorRule []interface{} + for _, oldExecutorItem := range oldExecutor { + oldExecutorRule = append(oldExecutorRule, oldExecutorItem) + } + var newExecutorRule []interface{} + for _, newExecutorItem := range newExecutor { + newExecutorRule = append(newExecutorRule, newExecutorItem) + } + + logs, sub, err := _Fastsettlementv3.contract.FilterLogs(opts, "ExecutorUpdated", oldExecutorRule, newExecutorRule) + if err != nil { + return nil, err + } + return &Fastsettlementv3ExecutorUpdatedIterator{contract: _Fastsettlementv3.contract, event: "ExecutorUpdated", logs: logs, sub: sub}, nil +} + +// WatchExecutorUpdated is a free log subscription operation binding the contract event 0x0ef3c7eb9dbcf33ddf032f4cce366a07eda85eed03e3172e4a90c4cc16d57886. +// +// Solidity: event ExecutorUpdated(address indexed oldExecutor, address indexed newExecutor) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) WatchExecutorUpdated(opts *bind.WatchOpts, sink chan<- *Fastsettlementv3ExecutorUpdated, oldExecutor []common.Address, newExecutor []common.Address) (event.Subscription, error) { + + var oldExecutorRule []interface{} + for _, oldExecutorItem := range oldExecutor { + oldExecutorRule = append(oldExecutorRule, oldExecutorItem) + } + var newExecutorRule []interface{} + for _, newExecutorItem := range newExecutor { + newExecutorRule = append(newExecutorRule, newExecutorItem) + } + + logs, sub, err := _Fastsettlementv3.contract.WatchLogs(opts, "ExecutorUpdated", oldExecutorRule, newExecutorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Fastsettlementv3ExecutorUpdated) + if err := _Fastsettlementv3.contract.UnpackLog(event, "ExecutorUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseExecutorUpdated is a log parse operation binding the contract event 0x0ef3c7eb9dbcf33ddf032f4cce366a07eda85eed03e3172e4a90c4cc16d57886. +// +// Solidity: event ExecutorUpdated(address indexed oldExecutor, address indexed newExecutor) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) ParseExecutorUpdated(log types.Log) (*Fastsettlementv3ExecutorUpdated, error) { + event := new(Fastsettlementv3ExecutorUpdated) + if err := _Fastsettlementv3.contract.UnpackLog(event, "ExecutorUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Fastsettlementv3InitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Fastsettlementv3 contract. +type Fastsettlementv3InitializedIterator struct { + Event *Fastsettlementv3Initialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Fastsettlementv3InitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3Initialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3Initialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Fastsettlementv3InitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Fastsettlementv3InitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Fastsettlementv3Initialized represents a Initialized event raised by the Fastsettlementv3 contract. +type Fastsettlementv3Initialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) FilterInitialized(opts *bind.FilterOpts) (*Fastsettlementv3InitializedIterator, error) { + + logs, sub, err := _Fastsettlementv3.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &Fastsettlementv3InitializedIterator{contract: _Fastsettlementv3.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *Fastsettlementv3Initialized) (event.Subscription, error) { + + logs, sub, err := _Fastsettlementv3.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Fastsettlementv3Initialized) + if err := _Fastsettlementv3.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) ParseInitialized(log types.Log) (*Fastsettlementv3Initialized, error) { + event := new(Fastsettlementv3Initialized) + if err := _Fastsettlementv3.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Fastsettlementv3IntentExecutedIterator is returned from FilterIntentExecuted and is used to iterate over the raw logs and unpacked data for IntentExecuted events raised by the Fastsettlementv3 contract. +type Fastsettlementv3IntentExecutedIterator struct { + Event *Fastsettlementv3IntentExecuted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Fastsettlementv3IntentExecutedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3IntentExecuted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3IntentExecuted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Fastsettlementv3IntentExecutedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Fastsettlementv3IntentExecutedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Fastsettlementv3IntentExecuted represents a IntentExecuted event raised by the Fastsettlementv3 contract. +type Fastsettlementv3IntentExecuted struct { + User common.Address + InputToken common.Address + OutputToken common.Address + InputAmt *big.Int + UserAmtOut *big.Int + Received *big.Int + Surplus *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterIntentExecuted is a free log retrieval operation binding the contract event 0x1ad6a4af59e844de3a921ec3dba60cb46f0b9051c9a106258624709dff629a87. +// +// Solidity: event IntentExecuted(address indexed user, address indexed inputToken, address indexed outputToken, uint256 inputAmt, uint256 userAmtOut, uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) FilterIntentExecuted(opts *bind.FilterOpts, user []common.Address, inputToken []common.Address, outputToken []common.Address) (*Fastsettlementv3IntentExecutedIterator, error) { + + var userRule []interface{} + for _, userItem := range user { + userRule = append(userRule, userItem) + } + var inputTokenRule []interface{} + for _, inputTokenItem := range inputToken { + inputTokenRule = append(inputTokenRule, inputTokenItem) + } + var outputTokenRule []interface{} + for _, outputTokenItem := range outputToken { + outputTokenRule = append(outputTokenRule, outputTokenItem) + } + + logs, sub, err := _Fastsettlementv3.contract.FilterLogs(opts, "IntentExecuted", userRule, inputTokenRule, outputTokenRule) + if err != nil { + return nil, err + } + return &Fastsettlementv3IntentExecutedIterator{contract: _Fastsettlementv3.contract, event: "IntentExecuted", logs: logs, sub: sub}, nil +} + +// WatchIntentExecuted is a free log subscription operation binding the contract event 0x1ad6a4af59e844de3a921ec3dba60cb46f0b9051c9a106258624709dff629a87. +// +// Solidity: event IntentExecuted(address indexed user, address indexed inputToken, address indexed outputToken, uint256 inputAmt, uint256 userAmtOut, uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) WatchIntentExecuted(opts *bind.WatchOpts, sink chan<- *Fastsettlementv3IntentExecuted, user []common.Address, inputToken []common.Address, outputToken []common.Address) (event.Subscription, error) { + + var userRule []interface{} + for _, userItem := range user { + userRule = append(userRule, userItem) + } + var inputTokenRule []interface{} + for _, inputTokenItem := range inputToken { + inputTokenRule = append(inputTokenRule, inputTokenItem) + } + var outputTokenRule []interface{} + for _, outputTokenItem := range outputToken { + outputTokenRule = append(outputTokenRule, outputTokenItem) + } + + logs, sub, err := _Fastsettlementv3.contract.WatchLogs(opts, "IntentExecuted", userRule, inputTokenRule, outputTokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Fastsettlementv3IntentExecuted) + if err := _Fastsettlementv3.contract.UnpackLog(event, "IntentExecuted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseIntentExecuted is a log parse operation binding the contract event 0x1ad6a4af59e844de3a921ec3dba60cb46f0b9051c9a106258624709dff629a87. +// +// Solidity: event IntentExecuted(address indexed user, address indexed inputToken, address indexed outputToken, uint256 inputAmt, uint256 userAmtOut, uint256 received, uint256 surplus) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) ParseIntentExecuted(log types.Log) (*Fastsettlementv3IntentExecuted, error) { + event := new(Fastsettlementv3IntentExecuted) + if err := _Fastsettlementv3.contract.UnpackLog(event, "IntentExecuted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Fastsettlementv3OwnershipTransferStartedIterator is returned from FilterOwnershipTransferStarted and is used to iterate over the raw logs and unpacked data for OwnershipTransferStarted events raised by the Fastsettlementv3 contract. +type Fastsettlementv3OwnershipTransferStartedIterator struct { + Event *Fastsettlementv3OwnershipTransferStarted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Fastsettlementv3OwnershipTransferStartedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3OwnershipTransferStarted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3OwnershipTransferStarted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Fastsettlementv3OwnershipTransferStartedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Fastsettlementv3OwnershipTransferStartedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Fastsettlementv3OwnershipTransferStarted represents a OwnershipTransferStarted event raised by the Fastsettlementv3 contract. +type Fastsettlementv3OwnershipTransferStarted struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferStarted is a free log retrieval operation binding the contract event 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700. +// +// Solidity: event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) FilterOwnershipTransferStarted(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*Fastsettlementv3OwnershipTransferStartedIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Fastsettlementv3.contract.FilterLogs(opts, "OwnershipTransferStarted", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &Fastsettlementv3OwnershipTransferStartedIterator{contract: _Fastsettlementv3.contract, event: "OwnershipTransferStarted", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferStarted is a free log subscription operation binding the contract event 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700. +// +// Solidity: event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) WatchOwnershipTransferStarted(opts *bind.WatchOpts, sink chan<- *Fastsettlementv3OwnershipTransferStarted, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Fastsettlementv3.contract.WatchLogs(opts, "OwnershipTransferStarted", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Fastsettlementv3OwnershipTransferStarted) + if err := _Fastsettlementv3.contract.UnpackLog(event, "OwnershipTransferStarted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferStarted is a log parse operation binding the contract event 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700. +// +// Solidity: event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) ParseOwnershipTransferStarted(log types.Log) (*Fastsettlementv3OwnershipTransferStarted, error) { + event := new(Fastsettlementv3OwnershipTransferStarted) + if err := _Fastsettlementv3.contract.UnpackLog(event, "OwnershipTransferStarted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Fastsettlementv3OwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Fastsettlementv3 contract. +type Fastsettlementv3OwnershipTransferredIterator struct { + Event *Fastsettlementv3OwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Fastsettlementv3OwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3OwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3OwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Fastsettlementv3OwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Fastsettlementv3OwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Fastsettlementv3OwnershipTransferred represents a OwnershipTransferred event raised by the Fastsettlementv3 contract. +type Fastsettlementv3OwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*Fastsettlementv3OwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Fastsettlementv3.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &Fastsettlementv3OwnershipTransferredIterator{contract: _Fastsettlementv3.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *Fastsettlementv3OwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Fastsettlementv3.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Fastsettlementv3OwnershipTransferred) + if err := _Fastsettlementv3.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) ParseOwnershipTransferred(log types.Log) (*Fastsettlementv3OwnershipTransferred, error) { + event := new(Fastsettlementv3OwnershipTransferred) + if err := _Fastsettlementv3.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Fastsettlementv3SwapTargetsUpdatedIterator is returned from FilterSwapTargetsUpdated and is used to iterate over the raw logs and unpacked data for SwapTargetsUpdated events raised by the Fastsettlementv3 contract. +type Fastsettlementv3SwapTargetsUpdatedIterator struct { + Event *Fastsettlementv3SwapTargetsUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Fastsettlementv3SwapTargetsUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3SwapTargetsUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3SwapTargetsUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Fastsettlementv3SwapTargetsUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Fastsettlementv3SwapTargetsUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Fastsettlementv3SwapTargetsUpdated represents a SwapTargetsUpdated event raised by the Fastsettlementv3 contract. +type Fastsettlementv3SwapTargetsUpdated struct { + Targets []common.Address + Allowed []bool + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSwapTargetsUpdated is a free log retrieval operation binding the contract event 0xe18e0ae71e84871d203445f1d9d5c51bd93bb2e362ee0e455940a88475dc13bc. +// +// Solidity: event SwapTargetsUpdated(address[] targets, bool[] allowed) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) FilterSwapTargetsUpdated(opts *bind.FilterOpts) (*Fastsettlementv3SwapTargetsUpdatedIterator, error) { + + logs, sub, err := _Fastsettlementv3.contract.FilterLogs(opts, "SwapTargetsUpdated") + if err != nil { + return nil, err + } + return &Fastsettlementv3SwapTargetsUpdatedIterator{contract: _Fastsettlementv3.contract, event: "SwapTargetsUpdated", logs: logs, sub: sub}, nil +} + +// WatchSwapTargetsUpdated is a free log subscription operation binding the contract event 0xe18e0ae71e84871d203445f1d9d5c51bd93bb2e362ee0e455940a88475dc13bc. +// +// Solidity: event SwapTargetsUpdated(address[] targets, bool[] allowed) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) WatchSwapTargetsUpdated(opts *bind.WatchOpts, sink chan<- *Fastsettlementv3SwapTargetsUpdated) (event.Subscription, error) { + + logs, sub, err := _Fastsettlementv3.contract.WatchLogs(opts, "SwapTargetsUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Fastsettlementv3SwapTargetsUpdated) + if err := _Fastsettlementv3.contract.UnpackLog(event, "SwapTargetsUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseSwapTargetsUpdated is a log parse operation binding the contract event 0xe18e0ae71e84871d203445f1d9d5c51bd93bb2e362ee0e455940a88475dc13bc. +// +// Solidity: event SwapTargetsUpdated(address[] targets, bool[] allowed) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) ParseSwapTargetsUpdated(log types.Log) (*Fastsettlementv3SwapTargetsUpdated, error) { + event := new(Fastsettlementv3SwapTargetsUpdated) + if err := _Fastsettlementv3.contract.UnpackLog(event, "SwapTargetsUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Fastsettlementv3TreasuryUpdatedIterator is returned from FilterTreasuryUpdated and is used to iterate over the raw logs and unpacked data for TreasuryUpdated events raised by the Fastsettlementv3 contract. +type Fastsettlementv3TreasuryUpdatedIterator struct { + Event *Fastsettlementv3TreasuryUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Fastsettlementv3TreasuryUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3TreasuryUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3TreasuryUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Fastsettlementv3TreasuryUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Fastsettlementv3TreasuryUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Fastsettlementv3TreasuryUpdated represents a TreasuryUpdated event raised by the Fastsettlementv3 contract. +type Fastsettlementv3TreasuryUpdated struct { + OldTreasury common.Address + NewTreasury common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTreasuryUpdated is a free log retrieval operation binding the contract event 0x4ab5be82436d353e61ca18726e984e561f5c1cc7c6d38b29d2553c790434705a. +// +// Solidity: event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) FilterTreasuryUpdated(opts *bind.FilterOpts, oldTreasury []common.Address, newTreasury []common.Address) (*Fastsettlementv3TreasuryUpdatedIterator, error) { + + var oldTreasuryRule []interface{} + for _, oldTreasuryItem := range oldTreasury { + oldTreasuryRule = append(oldTreasuryRule, oldTreasuryItem) + } + var newTreasuryRule []interface{} + for _, newTreasuryItem := range newTreasury { + newTreasuryRule = append(newTreasuryRule, newTreasuryItem) + } + + logs, sub, err := _Fastsettlementv3.contract.FilterLogs(opts, "TreasuryUpdated", oldTreasuryRule, newTreasuryRule) + if err != nil { + return nil, err + } + return &Fastsettlementv3TreasuryUpdatedIterator{contract: _Fastsettlementv3.contract, event: "TreasuryUpdated", logs: logs, sub: sub}, nil +} + +// WatchTreasuryUpdated is a free log subscription operation binding the contract event 0x4ab5be82436d353e61ca18726e984e561f5c1cc7c6d38b29d2553c790434705a. +// +// Solidity: event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) WatchTreasuryUpdated(opts *bind.WatchOpts, sink chan<- *Fastsettlementv3TreasuryUpdated, oldTreasury []common.Address, newTreasury []common.Address) (event.Subscription, error) { + + var oldTreasuryRule []interface{} + for _, oldTreasuryItem := range oldTreasury { + oldTreasuryRule = append(oldTreasuryRule, oldTreasuryItem) + } + var newTreasuryRule []interface{} + for _, newTreasuryItem := range newTreasury { + newTreasuryRule = append(newTreasuryRule, newTreasuryItem) + } + + logs, sub, err := _Fastsettlementv3.contract.WatchLogs(opts, "TreasuryUpdated", oldTreasuryRule, newTreasuryRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Fastsettlementv3TreasuryUpdated) + if err := _Fastsettlementv3.contract.UnpackLog(event, "TreasuryUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTreasuryUpdated is a log parse operation binding the contract event 0x4ab5be82436d353e61ca18726e984e561f5c1cc7c6d38b29d2553c790434705a. +// +// Solidity: event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) ParseTreasuryUpdated(log types.Log) (*Fastsettlementv3TreasuryUpdated, error) { + event := new(Fastsettlementv3TreasuryUpdated) + if err := _Fastsettlementv3.contract.UnpackLog(event, "TreasuryUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Fastsettlementv3UpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the Fastsettlementv3 contract. +type Fastsettlementv3UpgradedIterator struct { + Event *Fastsettlementv3Upgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Fastsettlementv3UpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3Upgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Fastsettlementv3Upgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Fastsettlementv3UpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Fastsettlementv3UpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Fastsettlementv3Upgraded represents a Upgraded event raised by the Fastsettlementv3 contract. +type Fastsettlementv3Upgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*Fastsettlementv3UpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _Fastsettlementv3.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &Fastsettlementv3UpgradedIterator{contract: _Fastsettlementv3.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *Fastsettlementv3Upgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _Fastsettlementv3.contract.WatchLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Fastsettlementv3Upgraded) + if err := _Fastsettlementv3.contract.UnpackLog(event, "Upgraded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Fastsettlementv3 *Fastsettlementv3Filterer) ParseUpgraded(log types.Log) (*Fastsettlementv3Upgraded, error) { + event := new(Fastsettlementv3Upgraded) + if err := _Fastsettlementv3.contract.UnpackLog(event, "Upgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/tools/preconf-rpc/fastswap/fastswap.go b/tools/preconf-rpc/fastswap/fastswap.go index 8683a8335..dd2db9cc0 100644 --- a/tools/preconf-rpc/fastswap/fastswap.go +++ b/tools/preconf-rpc/fastswap/fastswap.go @@ -17,13 +17,21 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + fastsettlementv3 "github.com/primev/mev-commit/contracts-abi/clients/FastSettlementV3" "github.com/primev/mev-commit/tools/preconf-rpc/sender" ) // ============ Types ============ -// Intent mirrors the Solidity Intent struct from FastSettlementV3. -type Intent struct { +// Intent is an alias to the generated contract binding type for HTTP JSON parsing. +// Uses the exact same struct layout as the Solidity definition. +type Intent = fastsettlementv3.IFastSettlementV3Intent + +// SwapCall is an alias to the generated contract binding type. +type SwapCall = fastsettlementv3.IFastSettlementV3SwapCall + +// SwapRequest is the HTTP request body for the /fastswap endpoint. +type SwapRequest struct { User common.Address `json:"user"` InputToken common.Address `json:"inputToken"` OutputToken common.Address `json:"outputToken"` @@ -32,19 +40,21 @@ type Intent struct { Recipient common.Address `json:"recipient"` Deadline *big.Int `json:"deadline"` Nonce *big.Int `json:"nonce"` + Signature []byte `json:"signature"` // EIP-712 Permit2 signature } -// SwapCall mirrors the Solidity SwapCall struct. -type SwapCall struct { - To common.Address `json:"to"` - Value *big.Int `json:"value"` - Data []byte `json:"data"` -} - -// SwapRequest is the HTTP request body for the /fastswap endpoint. -type SwapRequest struct { - Intent Intent `json:"intent"` - Signature []byte `json:"signature"` // EIP-712 Permit2 signature +// ToIntent converts SwapRequest to the generated Intent type for ABI encoding. +func (r *SwapRequest) ToIntent() Intent { + return Intent{ + User: r.User, + InputToken: r.InputToken, + OutputToken: r.OutputToken, + InputAmt: r.InputAmt, + UserAmtOut: r.UserAmtOut, + Recipient: r.Recipient, + Deadline: r.Deadline, + Nonce: r.Nonce, + } } // SwapResult is the HTTP response for /fastswap. @@ -107,30 +117,24 @@ type sourceFee struct { Recipient string `json:"recipient"` } -// IntentTuple is a struct that matches the ABI tuple for Intent. -type IntentTuple struct { - User common.Address - InputToken common.Address - OutputToken common.Address - InputAmt *big.Int - UserAmtOut *big.Int - Recipient common.Address - Deadline *big.Int - Nonce *big.Int -} - -// SwapCallTuple is a struct that matches the ABI tuple for SwapCall. -type SwapCallTuple struct { - To common.Address - Value *big.Int - Data []byte -} - // ============ Service ============ // Mainnet WETH address var mainnetWETH = common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +// parsedABI holds the pre-parsed contract ABI from generated bindings +var parsedABI *abi.ABI + +func init() { + // Use pre-parsed ABI from generated bindings - no panic possible + parsed, err := fastsettlementv3.Fastsettlementv3MetaData.GetAbi() + if err != nil { + // This should never happen with generated bindings + parsed = nil + } + parsedABI = parsed +} + // Signer interface for signing transactions type Signer interface { SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) @@ -191,102 +195,6 @@ func (s *Service) SetExecutorDeps(signer Signer, txEnqueuer TxEnqueuer, blockTra s.blockTracker = blockTracker } -// ============ ABI ============ - -// FastSettlementV3 ABI for executeWithPermit (executor path) -const executeWithPermitABI = `[{ - "inputs": [ - { - "components": [ - {"internalType": "address", "name": "user", "type": "address"}, - {"internalType": "address", "name": "inputToken", "type": "address"}, - {"internalType": "address", "name": "outputToken", "type": "address"}, - {"internalType": "uint256", "name": "inputAmt", "type": "uint256"}, - {"internalType": "uint256", "name": "userAmtOut", "type": "uint256"}, - {"internalType": "address", "name": "recipient", "type": "address"}, - {"internalType": "uint256", "name": "deadline", "type": "uint256"}, - {"internalType": "uint256", "name": "nonce", "type": "uint256"} - ], - "internalType": "struct IFastSettlementV3.Intent", - "name": "intent", - "type": "tuple" - }, - {"internalType": "bytes", "name": "signature", "type": "bytes"}, - { - "components": [ - {"internalType": "address", "name": "to", "type": "address"}, - {"internalType": "uint256", "name": "value", "type": "uint256"}, - {"internalType": "bytes", "name": "data", "type": "bytes"} - ], - "internalType": "struct IFastSettlementV3.SwapCall", - "name": "swapData", - "type": "tuple" - } - ], - "name": "executeWithPermit", - "outputs": [ - {"internalType": "uint256", "name": "received", "type": "uint256"}, - {"internalType": "uint256", "name": "surplus", "type": "uint256"} - ], - "stateMutability": "nonpayable", - "type": "function" -}]` - -// FastSettlementV3 ABI for executeWithETH (user ETH swap path) -const executeWithETHABI = `[{ - "inputs": [ - { - "components": [ - {"internalType": "address", "name": "user", "type": "address"}, - {"internalType": "address", "name": "inputToken", "type": "address"}, - {"internalType": "address", "name": "outputToken", "type": "address"}, - {"internalType": "uint256", "name": "inputAmt", "type": "uint256"}, - {"internalType": "uint256", "name": "userAmtOut", "type": "uint256"}, - {"internalType": "address", "name": "recipient", "type": "address"}, - {"internalType": "uint256", "name": "deadline", "type": "uint256"}, - {"internalType": "uint256", "name": "nonce", "type": "uint256"} - ], - "internalType": "struct IFastSettlementV3.Intent", - "name": "intent", - "type": "tuple" - }, - { - "components": [ - {"internalType": "address", "name": "to", "type": "address"}, - {"internalType": "uint256", "name": "value", "type": "uint256"}, - {"internalType": "bytes", "name": "data", "type": "bytes"} - ], - "internalType": "struct IFastSettlementV3.SwapCall", - "name": "swapData", - "type": "tuple" - } - ], - "name": "executeWithETH", - "outputs": [ - {"internalType": "uint256", "name": "received", "type": "uint256"}, - {"internalType": "uint256", "name": "surplus", "type": "uint256"} - ], - "stateMutability": "payable", - "type": "function" -}]` - -var ( - executeWithPermitABIParsed abi.ABI - executeWithETHABIParsed abi.ABI -) - -func init() { - var err error - executeWithPermitABIParsed, err = abi.JSON(strings.NewReader(executeWithPermitABI)) - if err != nil { - panic(fmt.Sprintf("failed to parse executeWithPermit ABI: %v", err)) - } - executeWithETHABIParsed, err = abi.JSON(strings.NewReader(executeWithETHABI)) - if err != nil { - panic(fmt.Sprintf("failed to parse executeWithETH ABI: %v", err)) - } -} - // ============ Barter API ============ // callBarter is the shared HTTP call logic for calling the Barter swap API. @@ -299,7 +207,7 @@ func (s *Service) callBarter(ctx context.Context, reqBody barterRequest, logDesc req, err := http.NewRequestWithContext( ctx, http.MethodPost, - fmt.Sprintf("%s/swap", s.barterBaseURL), + s.barterBaseURL+"/swap", bytes.NewReader(bodyBytes), ) if err != nil { @@ -311,7 +219,7 @@ func (s *Service) callBarter(ctx context.Context, reqBody barterRequest, logDesc s.logger.Debug("calling Barter API", "type", logDescription, - "url", req.URL.String(), + "url", s.barterBaseURL+"/swap", "source", reqBody.Source, "target", reqBody.Target, "sellAmount", reqBody.SellAmount, @@ -334,7 +242,7 @@ func (s *Service) callBarter(ctx context.Context, reqBody barterRequest, logDesc var barterResp BarterResponse if err := json.Unmarshal(respBody, &barterResp); err != nil { - return nil, fmt.Errorf("unmarshal barter response: %w", err) + return nil, fmt.Errorf("decode barter response: %w", err) } s.logger.Info("Barter API response", @@ -347,12 +255,8 @@ func (s *Service) callBarter(ctx context.Context, reqBody barterRequest, logDesc return &barterResp, nil } -// CallBarterAPI calls the Barter swap API with the given intent (Path 1). +// CallBarterAPI calls the Barter API for swap routing (Path 1 - executor submitted). func (s *Service) CallBarterAPI(ctx context.Context, intent Intent) (*BarterResponse, error) { - // IMPORTANT: Recipient must be the settlement contract, not the user's recipient. - // The contract receives the swap output, then distributes: - // - userAmtOut → intent.Recipient - // - surplus → treasury reqBody := barterRequest{ Source: intent.InputToken.Hex(), Target: intent.OutputToken.Hex(), @@ -365,31 +269,33 @@ func (s *Service) CallBarterAPI(ctx context.Context, intent Intent) (*BarterResp return s.callBarter(ctx, reqBody, "executor-swap") } -// ============ Transaction Builder ============ +// ============ Transaction Building ============ -// BuildExecuteTx constructs the calldata for FastSettlementV3.execute. +// BuildExecuteTx constructs the calldata for FastSettlementV3.executeWithPermit. func (s *Service) BuildExecuteTx(intent Intent, signature []byte, barter *BarterResponse) ([]byte, error) { + if parsedABI == nil { + return nil, fmt.Errorf("contract ABI not initialized") + } + // Decode swap data from Barter response swapData, err := hex.DecodeString(strings.TrimPrefix(barter.Data, "0x")) if err != nil { return nil, fmt.Errorf("decode barter data: %w", err) } - // Parse value from Barter response - value := new(big.Int) - if barter.Value != "" && barter.Value != "0" { - value.SetString(barter.Value, 10) + // Parse value from Barter response with proper error handling + value, ok := new(big.Int).SetString(barter.Value, 10) + if !ok { + value = big.NewInt(0) } - intentTuple := IntentTuple(intent) - - swapCallTuple := SwapCallTuple{ + swapCall := SwapCall{ To: barter.To, Value: value, Data: swapData, } - calldata, err := executeWithPermitABIParsed.Pack("executeWithPermit", intentTuple, signature, swapCallTuple) + calldata, err := parsedABI.Pack("executeWithPermit", intent, signature, swapCall) if err != nil { return nil, fmt.Errorf("pack executeWithPermit calldata: %w", err) } @@ -415,8 +321,11 @@ func (s *Service) HandleSwap(ctx context.Context, req SwapRequest) (*SwapResult, }, nil } + // Convert request to Intent + intent := req.ToIntent() + // 1. Call Barter API - barterResp, err := s.CallBarterAPI(ctx, req.Intent) + barterResp, err := s.CallBarterAPI(ctx, intent) if err != nil { return &SwapResult{ Status: "error", @@ -425,7 +334,7 @@ func (s *Service) HandleSwap(ctx context.Context, req SwapRequest) (*SwapResult, } // 2. Build execute transaction calldata - calldata, err := s.BuildExecuteTx(req.Intent, req.Signature, barterResp) + calldata, err := s.BuildExecuteTx(intent, req.Signature, barterResp) if err != nil { return &SwapResult{ Status: "error", @@ -504,10 +413,10 @@ func (s *Service) HandleSwap(ctx context.Context, req SwapRequest) (*SwapResult, s.logger.Info("swap transaction submitted", "txHash", signedTx.Hash().Hex(), - "user", req.Intent.User.Hex(), - "inputToken", req.Intent.InputToken.Hex(), - "outputToken", req.Intent.OutputToken.Hex(), - "inputAmt", req.Intent.InputAmt.String(), + "user", intent.User.Hex(), + "inputToken", intent.InputToken.Hex(), + "outputToken", intent.OutputToken.Hex(), + "inputAmt", intent.InputAmt.String(), "outputAmount", barterResp.Route.OutputAmount, "gasLimit", gasLimit, "gasFeeCap", gasFeeCap.String(), @@ -523,6 +432,8 @@ func (s *Service) HandleSwap(ctx context.Context, req SwapRequest) (*SwapResult, }, nil } +// ============ HTTP Handlers ============ + // Handler returns an HTTP handler for the /fastswap endpoint. func (s *Service) Handler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { @@ -531,31 +442,23 @@ func (s *Service) Handler() http.HandlerFunc { return } - // Limit body size - r.Body = http.MaxBytesReader(w, r.Body, 1*1024*1024) // 1MB - defer func() { _ = r.Body.Close() }() - var req SwapRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - http.Error(w, fmt.Sprintf("invalid request body: %v", err), http.StatusBadRequest) + http.Error(w, fmt.Sprintf("invalid request: %v", err), http.StatusBadRequest) return } // Validate required fields - if req.Intent.User == (common.Address{}) { - http.Error(w, "missing intent.user", http.StatusBadRequest) + if req.User == (common.Address{}) { + http.Error(w, "missing user address", http.StatusBadRequest) return } - if req.Intent.InputToken == (common.Address{}) { - http.Error(w, "missing intent.inputToken", http.StatusBadRequest) + if req.InputToken == (common.Address{}) { + http.Error(w, "missing inputToken", http.StatusBadRequest) return } - if req.Intent.OutputToken == (common.Address{}) { - http.Error(w, "missing intent.outputToken", http.StatusBadRequest) - return - } - if req.Intent.InputAmt == nil || req.Intent.InputAmt.Sign() <= 0 { - http.Error(w, "invalid intent.inputAmt", http.StatusBadRequest) + if req.OutputToken == (common.Address{}) { + http.Error(w, "missing outputToken", http.StatusBadRequest) return } if len(req.Signature) == 0 { @@ -565,28 +468,22 @@ func (s *Service) Handler() http.HandlerFunc { result, err := s.HandleSwap(r.Context(), req) if err != nil { - s.logger.Error("HandleSwap error", "error", err) - http.Error(w, fmt.Sprintf("internal error: %v", err), http.StatusInternalServerError) + http.Error(w, fmt.Sprintf("swap failed: %v", err), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") - if result.Status == "error" { - w.WriteHeader(http.StatusBadRequest) - } - if err := json.NewEncoder(w).Encode(result); err != nil { - s.logger.Error("failed to encode response", "error", err) - } + _ = json.NewEncoder(w).Encode(result) } } -// ============ Path 2: User ETH Swap ============ +// ============ Path 2: User-Submitted ETH Swaps ============ -// CallBarterAPIForETH calls the Barter swap API for an ETH swap (Path 2). +// CallBarterAPIForETH calls the Barter API for ETH->Token swap routing (Path 2). // Uses WETH as the source token since Barter works with ERC20s. func (s *Service) CallBarterAPIForETH(ctx context.Context, req ETHSwapRequest) (*BarterResponse, error) { reqBody := barterRequest{ - Source: mainnetWETH.Hex(), // WETH (Barter uses ERC20s) + Source: mainnetWETH.Hex(), Target: req.OutputToken.Hex(), SellAmount: req.InputAmt.String(), Recipient: s.settlementAddr.Hex(), @@ -599,20 +496,24 @@ func (s *Service) CallBarterAPIForETH(ctx context.Context, req ETHSwapRequest) ( // BuildExecuteWithETHTx constructs the calldata for FastSettlementV3.executeWithETH. func (s *Service) BuildExecuteWithETHTx(req ETHSwapRequest, barter *BarterResponse) ([]byte, error) { + if parsedABI == nil { + return nil, fmt.Errorf("contract ABI not initialized") + } + // Decode swap data from Barter response swapData, err := hex.DecodeString(strings.TrimPrefix(barter.Data, "0x")) if err != nil { return nil, fmt.Errorf("decode barter data: %w", err) } - // Parse value from Barter response - value := new(big.Int) - if barter.Value != "" && barter.Value != "0" { - value.SetString(barter.Value, 10) + // Parse value from Barter response with proper error handling + value, ok := new(big.Int).SetString(barter.Value, 10) + if !ok { + value = big.NewInt(0) } - // Build Intent tuple - inputToken is address(0) for ETH - intentTuple := IntentTuple{ + // Build Intent - inputToken is address(0) for ETH + intent := Intent{ User: req.Sender, InputToken: common.Address{}, // address(0) indicates native ETH OutputToken: req.OutputToken, @@ -623,13 +524,13 @@ func (s *Service) BuildExecuteWithETHTx(req ETHSwapRequest, barter *BarterRespon Nonce: big.NewInt(0), // Unused for Path 2 } - swapCallTuple := SwapCallTuple{ + swapCall := SwapCall{ To: barter.To, Value: value, Data: swapData, } - calldata, err := executeWithETHABIParsed.Pack("executeWithETH", intentTuple, swapCallTuple) + calldata, err := parsedABI.Pack("executeWithETH", intent, swapCall) if err != nil { return nil, fmt.Errorf("pack executeWithETH calldata: %w", err) } @@ -653,8 +554,8 @@ func (s *Service) HandleETHSwap(ctx context.Context, req ETHSwapRequest) (*ETHSw }, nil } - // 2. Build executeWithETH transaction calldata - txData, err := s.BuildExecuteWithETHTx(req, barterResp) + // 2. Build executeWithETH calldata + calldata, err := s.BuildExecuteWithETHTx(req, barterResp) if err != nil { return ÐSwapResponse{ Status: "error", @@ -662,12 +563,9 @@ func (s *Service) HandleETHSwap(ctx context.Context, req ETHSwapRequest) (*ETHSw }, nil } - // 3. Parse gas limit + // 3. Calculate gas limit with buffer gasLimit, _ := strconv.ParseUint(barterResp.GasLimit, 10, 64) - - // Add buffer for settlement contract overhead (WETH wrap, approve, transfer, etc.) - // Rough estimate: 150k gas for settlement logic with WETH wrapping - gasLimit += 150000 + gasLimit += 150000 // Buffer for ETH wrap + settlement contract overhead s.logger.Info("ETH swap request processed", "sender", req.Sender.Hex(), @@ -680,7 +578,7 @@ func (s *Service) HandleETHSwap(ctx context.Context, req ETHSwapRequest) (*ETHSw return ÐSwapResponse{ To: s.settlementAddr.Hex(), - Data: "0x" + hex.EncodeToString(txData), + Data: "0x" + hex.EncodeToString(calldata), Value: req.InputAmt.String(), ChainID: s.chainID, GasLimit: gasLimit, @@ -696,51 +594,61 @@ func (s *Service) ETHHandler() http.HandlerFunc { return } - // Limit body size - r.Body = http.MaxBytesReader(w, r.Body, 1*1024*1024) // 1MB - defer func() { _ = r.Body.Close() }() + var rawReq struct { + OutputToken string `json:"outputToken"` + InputAmt string `json:"inputAmt"` + UserAmtOut string `json:"userAmtOut"` + Sender string `json:"sender"` + Deadline string `json:"deadline"` + } - var req ETHSwapRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - http.Error(w, fmt.Sprintf("invalid request body: %v", err), http.StatusBadRequest) + if err := json.NewDecoder(r.Body).Decode(&rawReq); err != nil { + http.Error(w, fmt.Sprintf("invalid request: %v", err), http.StatusBadRequest) return } // Validate required fields - if req.Sender == (common.Address{}) { - http.Error(w, "missing sender", http.StatusBadRequest) + if rawReq.Sender == "" || !common.IsHexAddress(rawReq.Sender) { + http.Error(w, "missing or invalid sender address", http.StatusBadRequest) return } - if req.OutputToken == (common.Address{}) { - http.Error(w, "missing outputToken", http.StatusBadRequest) + if rawReq.OutputToken == "" || !common.IsHexAddress(rawReq.OutputToken) { + http.Error(w, "missing or invalid outputToken", http.StatusBadRequest) return } - if req.InputAmt == nil || req.InputAmt.Sign() <= 0 { + + // Parse big.Int fields + inputAmt, ok := new(big.Int).SetString(rawReq.InputAmt, 10) + if !ok || inputAmt.Sign() <= 0 { http.Error(w, "invalid inputAmt", http.StatusBadRequest) return } - if req.UserAmtOut == nil || req.UserAmtOut.Sign() <= 0 { + userAmtOut, ok := new(big.Int).SetString(rawReq.UserAmtOut, 10) + if !ok { http.Error(w, "invalid userAmtOut", http.StatusBadRequest) return } - if req.Deadline == nil || req.Deadline.Sign() <= 0 { + deadline, ok := new(big.Int).SetString(rawReq.Deadline, 10) + if !ok || deadline.Sign() <= 0 { http.Error(w, "invalid deadline", http.StatusBadRequest) return } + req := ETHSwapRequest{ + OutputToken: common.HexToAddress(rawReq.OutputToken), + InputAmt: inputAmt, + UserAmtOut: userAmtOut, + Sender: common.HexToAddress(rawReq.Sender), + Deadline: deadline, + } + result, err := s.HandleETHSwap(r.Context(), req) if err != nil { - s.logger.Error("HandleETHSwap error", "error", err) - http.Error(w, fmt.Sprintf("internal error: %v", err), http.StatusInternalServerError) + http.Error(w, fmt.Sprintf("ETH swap failed: %v", err), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") - if result.Status == "error" { - w.WriteHeader(http.StatusBadRequest) - } - if err := json.NewEncoder(w).Encode(result); err != nil { - s.logger.Error("failed to encode response", "error", err) - } + _ = json.NewEncoder(w).Encode(result) } } diff --git a/tools/preconf-rpc/fastswap/fastswap_test.go b/tools/preconf-rpc/fastswap/fastswap_test.go index 72bf9005c..4dd761b2f 100644 --- a/tools/preconf-rpc/fastswap/fastswap_test.go +++ b/tools/preconf-rpc/fastswap/fastswap_test.go @@ -277,17 +277,15 @@ func TestHandleSwap(t *testing.T) { svc.SetExecutorDeps(mockSigner, mockEnqueuer, mockTracker) req := fastswap.SwapRequest{ - Intent: fastswap.Intent{ - User: common.HexToAddress("0xUserAddress"), - InputToken: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), - OutputToken: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), - InputAmt: big.NewInt(1000000000), - UserAmtOut: big.NewInt(500000000000000000), - Recipient: common.HexToAddress("0xRecipientAddress"), - Deadline: big.NewInt(1700000000), - Nonce: big.NewInt(1), - }, - Signature: []byte{0x01, 0x02, 0x03, 0x04}, + User: common.HexToAddress("0xUserAddress"), + InputToken: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + OutputToken: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + InputAmt: big.NewInt(1000000000), + UserAmtOut: big.NewInt(500000000000000000), + Recipient: common.HexToAddress("0xRecipientAddress"), + Deadline: big.NewInt(1700000000), + Nonce: big.NewInt(1), + Signature: []byte{0x01, 0x02, 0x03, 0x04}, } ctx := context.Background() @@ -317,12 +315,10 @@ func TestHandleSwap_NoExecutorDeps(t *testing.T) { // No executor deps set req := fastswap.SwapRequest{ - Intent: fastswap.Intent{ - User: common.HexToAddress("0xUserAddress"), - InputToken: common.HexToAddress("0xInputToken"), - InputAmt: big.NewInt(1000), - }, - Signature: []byte{0x01, 0x02}, + User: common.HexToAddress("0xUserAddress"), + InputToken: common.HexToAddress("0xInputToken"), + InputAmt: big.NewInt(1000), + Signature: []byte{0x01, 0x02}, } ctx := context.Background() @@ -395,18 +391,16 @@ func TestHandler(t *testing.T) { handler := svc.Handler() - // Use raw JSON with proper big.Int encoding (numbers, not quoted strings) + // Use raw JSON with flattened request structure reqJSON := `{ - "intent": { - "user": "0x0000000000000000000000000000000000000001", - "inputToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "outputToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "inputAmt": 1000000000, - "userAmtOut": 500000000000000000, - "recipient": "0x0000000000000000000000000000000000000002", - "deadline": 1700000000, - "nonce": 1 - }, + "user": "0x0000000000000000000000000000000000000001", + "inputToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "outputToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "inputAmt": 1000000000, + "userAmtOut": 500000000000000000, + "recipient": "0x0000000000000000000000000000000000000002", + "deadline": 1700000000, + "nonce": 1, "signature": "AQIDBA==" }` @@ -449,37 +443,31 @@ func TestHandler_MissingFields(t *testing.T) { }{ { name: "missing user", - reqBody: map[string]interface{}{"intent": map[string]interface{}{}}, - expected: "missing intent.user", + reqBody: map[string]interface{}{}, + expected: "missing user address", }, { name: "missing inputToken", reqBody: map[string]interface{}{ - "intent": map[string]interface{}{ - "user": "0x1234567890123456789012345678901234567890", - }, + "user": "0x1234567890123456789012345678901234567890", }, - expected: "missing intent.inputToken", + expected: "missing inputToken", }, { name: "missing outputToken", reqBody: map[string]interface{}{ - "intent": map[string]interface{}{ - "user": "0x1234567890123456789012345678901234567890", - "inputToken": "0x1234567890123456789012345678901234567890", - }, + "user": "0x1234567890123456789012345678901234567890", + "inputToken": "0x1234567890123456789012345678901234567890", }, - expected: "missing intent.outputToken", + expected: "missing outputToken", }, { name: "missing signature", reqBody: map[string]interface{}{ - "intent": map[string]interface{}{ - "user": "0x1234567890123456789012345678901234567890", - "inputToken": "0x1234567890123456789012345678901234567890", - "outputToken": "0x1234567890123456789012345678901234567890", - "inputAmt": 1000, // Use numeric value, not string - }, + "user": "0x1234567890123456789012345678901234567890", + "inputToken": "0x1234567890123456789012345678901234567890", + "outputToken": "0x1234567890123456789012345678901234567890", + "inputAmt": 1000, }, expected: "missing signature", }, @@ -517,13 +505,13 @@ func TestETHHandler(t *testing.T) { handler := svc.ETHHandler() - // Use raw JSON with proper big.Int encoding (numbers, not quoted strings) + // ETH handler expects string values for numeric fields reqJSON := `{ "outputToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "inputAmt": 1000000000000000000, - "userAmtOut": 2000000000, + "inputAmt": "1000000000000000000", + "userAmtOut": "2000000000", "sender": "0x0000000000000000000000000000000000000001", - "deadline": 1700000000 + "deadline": "1700000000" }` req := httptest.NewRequest(http.MethodPost, "/fastswap/eth", strings.NewReader(reqJSON)) @@ -567,20 +555,21 @@ func TestETHHandler_MissingFields(t *testing.T) { { name: "missing sender", reqBody: map[string]interface{}{}, - expected: "missing sender", + expected: "missing or invalid sender", }, { name: "missing outputToken", reqBody: map[string]interface{}{ "sender": "0x1234567890123456789012345678901234567890", }, - expected: "missing outputToken", + expected: "missing or invalid outputToken", }, { name: "invalid inputAmt", reqBody: map[string]interface{}{ "sender": "0x1234567890123456789012345678901234567890", "outputToken": "0x1234567890123456789012345678901234567890", + "inputAmt": "invalid", }, expected: "invalid inputAmt", }, @@ -589,7 +578,8 @@ func TestETHHandler_MissingFields(t *testing.T) { reqBody: map[string]interface{}{ "sender": "0x1234567890123456789012345678901234567890", "outputToken": "0x1234567890123456789012345678901234567890", - "inputAmt": 1000, // Use numeric value + "inputAmt": "1000", + "userAmtOut": "invalid", }, expected: "invalid userAmtOut", }, @@ -598,8 +588,9 @@ func TestETHHandler_MissingFields(t *testing.T) { reqBody: map[string]interface{}{ "sender": "0x1234567890123456789012345678901234567890", "outputToken": "0x1234567890123456789012345678901234567890", - "inputAmt": 1000, // Use numeric value - "userAmtOut": 900, // Use numeric value + "inputAmt": "1000", + "userAmtOut": "900", + "deadline": "invalid", }, expected: "invalid deadline", }, From e4190da5b508d1ffc7c0540ad83870f9a4888a1a Mon Sep 17 00:00:00 2001 From: owen-eth Date: Wed, 28 Jan 2026 12:54:06 -0500 Subject: [PATCH 4/4] updated abi and go bindings --- contracts-abi/abi/FastSettlementV3.abi | 10 +++++++ .../FastSettlementV3/FastSettlementV3.go | 26 +++++++++---------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/contracts-abi/abi/FastSettlementV3.abi b/contracts-abi/abi/FastSettlementV3.abi index d228e23d8..1e51b8efd 100644 --- a/contracts-abi/abi/FastSettlementV3.abi +++ b/contracts-abi/abi/FastSettlementV3.abi @@ -308,6 +308,11 @@ "type": "function", "name": "initialize", "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + }, { "name": "_executor", "type": "address", @@ -690,6 +695,11 @@ "name": "BadNonce", "inputs": [] }, + { + "type": "error", + "name": "BadOwner", + "inputs": [] + }, { "type": "error", "name": "BadRecipient", diff --git a/contracts-abi/clients/FastSettlementV3/FastSettlementV3.go b/contracts-abi/clients/FastSettlementV3/FastSettlementV3.go index f8af0b1ff..31f6fd4b1 100644 --- a/contracts-abi/clients/FastSettlementV3/FastSettlementV3.go +++ b/contracts-abi/clients/FastSettlementV3/FastSettlementV3.go @@ -50,7 +50,7 @@ type IFastSettlementV3SwapCall struct { // Fastsettlementv3MetaData contains all meta data concerning the Fastsettlementv3 contract. var Fastsettlementv3MetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_permit2\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_weth\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"INTENT_TYPEHASH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PERMIT2\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIPermit2\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"UPGRADE_INTERFACE_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WETH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWETH\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WITNESS_TYPE_STRING\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowedSwapTargets\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"executeWithETH\",\"inputs\":[{\"name\":\"intent\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.Intent\",\"components\":[{\"name\":\"user\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"swapData\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.SwapCall\",\"components\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"executeWithPermit\",\"inputs\":[{\"name\":\"intent\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.Intent\",\"components\":[{\"name\":\"user\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"swapData\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.SwapCall\",\"components\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"executor\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_executor\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_treasury\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_initialSwapTargets\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"pendingOwner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proxiableUUID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"rescueTokens\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setExecutor\",\"inputs\":[{\"name\":\"_newExecutor\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setSwapTargets\",\"inputs\":[{\"name\":\"targets\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"allowed\",\"type\":\"bool[]\",\"internalType\":\"bool[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setTreasury\",\"inputs\":[{\"name\":\"_newTreasury\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"treasury\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"ExecutorUpdated\",\"inputs\":[{\"name\":\"oldExecutor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newExecutor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"IntentExecuted\",\"inputs\":[{\"name\":\"user\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"received\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferStarted\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SwapTargetsUpdated\",\"inputs\":[{\"name\":\"targets\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"allowed\",\"type\":\"bool[]\",\"indexed\":false,\"internalType\":\"bool[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TreasuryUpdated\",\"inputs\":[{\"name\":\"oldTreasury\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newTreasury\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ArrayLengthMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadCallTarget\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadExecutor\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadInputAmt\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadInputToken\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadNonce\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadRecipient\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadTreasury\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadUserAmtOut\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ERC1967InvalidImplementation\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967NonPayable\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ExpectedETHInput\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBalance\",\"inputs\":[{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InsufficientOut\",\"inputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"IntentExpired\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidETHAmount\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPermit2\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidWETH\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SafeERC20FailedOperation\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UUPSUnauthorizedCallContext\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UUPSUnsupportedProxiableUUID\",\"inputs\":[{\"name\":\"slot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedExecutor\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedSwapTarget\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_permit2\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_weth\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"INTENT_TYPEHASH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PERMIT2\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIPermit2\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"UPGRADE_INTERFACE_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WETH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWETH\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WITNESS_TYPE_STRING\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowedSwapTargets\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"executeWithETH\",\"inputs\":[{\"name\":\"intent\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.Intent\",\"components\":[{\"name\":\"user\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"swapData\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.SwapCall\",\"components\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"executeWithPermit\",\"inputs\":[{\"name\":\"intent\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.Intent\",\"components\":[{\"name\":\"user\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"swapData\",\"type\":\"tuple\",\"internalType\":\"structIFastSettlementV3.SwapCall\",\"components\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"executor\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_executor\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_treasury\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_initialSwapTargets\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"pendingOwner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proxiableUUID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"rescueTokens\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setExecutor\",\"inputs\":[{\"name\":\"_newExecutor\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setSwapTargets\",\"inputs\":[{\"name\":\"targets\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"allowed\",\"type\":\"bool[]\",\"internalType\":\"bool[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setTreasury\",\"inputs\":[{\"name\":\"_newTreasury\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"treasury\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"ExecutorUpdated\",\"inputs\":[{\"name\":\"oldExecutor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newExecutor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"IntentExecuted\",\"inputs\":[{\"name\":\"user\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"inputToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"outputToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"inputAmt\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"received\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"surplus\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferStarted\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SwapTargetsUpdated\",\"inputs\":[{\"name\":\"targets\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"allowed\",\"type\":\"bool[]\",\"indexed\":false,\"internalType\":\"bool[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TreasuryUpdated\",\"inputs\":[{\"name\":\"oldTreasury\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newTreasury\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ArrayLengthMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadCallTarget\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadExecutor\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadInputAmt\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadInputToken\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadNonce\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadRecipient\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadTreasury\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadUserAmtOut\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ERC1967InvalidImplementation\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967NonPayable\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ExpectedETHInput\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBalance\",\"inputs\":[{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InsufficientOut\",\"inputs\":[{\"name\":\"received\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"userAmtOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"IntentExpired\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidETHAmount\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPermit2\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidWETH\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SafeERC20FailedOperation\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UUPSUnauthorizedCallContext\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UUPSUnsupportedProxiableUUID\",\"inputs\":[{\"name\":\"slot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedExecutor\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedSwapTarget\",\"inputs\":[]}]", } // Fastsettlementv3ABI is the input ABI used to generate the binding from. @@ -603,25 +603,25 @@ func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) ExecuteWithPermit(in return _Fastsettlementv3.Contract.ExecuteWithPermit(&_Fastsettlementv3.TransactOpts, intent, signature, swapData) } -// Initialize is a paid mutator transaction binding the contract method 0x77a24f36. +// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. // -// Solidity: function initialize(address _executor, address _treasury, address[] _initialSwapTargets) returns() -func (_Fastsettlementv3 *Fastsettlementv3Transactor) Initialize(opts *bind.TransactOpts, _executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { - return _Fastsettlementv3.contract.Transact(opts, "initialize", _executor, _treasury, _initialSwapTargets) +// Solidity: function initialize(address _owner, address _executor, address _treasury, address[] _initialSwapTargets) returns() +func (_Fastsettlementv3 *Fastsettlementv3Transactor) Initialize(opts *bind.TransactOpts, _owner common.Address, _executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.contract.Transact(opts, "initialize", _owner, _executor, _treasury, _initialSwapTargets) } -// Initialize is a paid mutator transaction binding the contract method 0x77a24f36. +// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. // -// Solidity: function initialize(address _executor, address _treasury, address[] _initialSwapTargets) returns() -func (_Fastsettlementv3 *Fastsettlementv3Session) Initialize(_executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { - return _Fastsettlementv3.Contract.Initialize(&_Fastsettlementv3.TransactOpts, _executor, _treasury, _initialSwapTargets) +// Solidity: function initialize(address _owner, address _executor, address _treasury, address[] _initialSwapTargets) returns() +func (_Fastsettlementv3 *Fastsettlementv3Session) Initialize(_owner common.Address, _executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.Initialize(&_Fastsettlementv3.TransactOpts, _owner, _executor, _treasury, _initialSwapTargets) } -// Initialize is a paid mutator transaction binding the contract method 0x77a24f36. +// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. // -// Solidity: function initialize(address _executor, address _treasury, address[] _initialSwapTargets) returns() -func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) Initialize(_executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { - return _Fastsettlementv3.Contract.Initialize(&_Fastsettlementv3.TransactOpts, _executor, _treasury, _initialSwapTargets) +// Solidity: function initialize(address _owner, address _executor, address _treasury, address[] _initialSwapTargets) returns() +func (_Fastsettlementv3 *Fastsettlementv3TransactorSession) Initialize(_owner common.Address, _executor common.Address, _treasury common.Address, _initialSwapTargets []common.Address) (*types.Transaction, error) { + return _Fastsettlementv3.Contract.Initialize(&_Fastsettlementv3.TransactOpts, _owner, _executor, _treasury, _initialSwapTargets) } // RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.