diff --git a/docs/03_gas_calculation.md b/docs/03_gas_calculation.md new file mode 100644 index 0000000..573400a --- /dev/null +++ b/docs/03_gas_calculation.md @@ -0,0 +1,113 @@ +# Extending DeFi Protocol Interface for Gas Calculation + +## Overview + +This document outlines the process for gas estimation in the DeFi protocol registry. Each protocol is responsible for both generating the necessary transaction data (calldata) and estimating the gas required to execute the transaction. The gas estimation function is crucial for determining the cost of transactions across various blockchains and DeFi protocols. + +## Gas Estimation + +The gas estimation method allows a protocol to predict the gas required for executing a transaction. This is essential to avoid out-of-gas errors and to calculate transaction fees before submitting the transaction to the blockchain. + +### Method: `EstimateGas` + +The EstimateGas method is responsible for both generating the calldata for the transaction and estimating the gas required to execute it. Since the protocol already knows the action and parameters, it can generate the calldata internally and use it to estimate the gas. + +### Parameters + +* `ctx`: A context object for managing timeouts and cancellations. +* `chainID`: The blockchain ID where the transaction is being executed (e.g., Ethereum Mainnet, BSC). +* `action`: The specific operation, such as staking or swapping. +* `params`: The transaction parameters, including addresses and amounts. + +example implementation + +```go +// EstimateGas estimates the gas required for a protocol operation. +func (p *MyProtocol) EstimateGas(ctx context.Context, chainID *big.Int, action ContractAction, params TransactionParams) (*big.Int, string, error) { + // Generate calldata based on the action + calldata, err := p.GenerateCalldata(ctx, chainID, action, params) + if err != nil { + return nil, "", err + } + + // Create the message for gas estimation + msg := ethereum.CallMsg{ + From: params.FromAddress, // Address initiating the transaction + To: &p.contract, // Contract address of the protocol + Data: calldata, // Calldata generated by the protocol + Value: params.AmountIn, // For payable functions like staking + } + + // Use the Ethereum client to estimate gas + gasEstimate, err := p.rpcClient.EstimateGas(ctx, msg) + if err != nil { + return nil, "", err + } + + return gasEstimate, calldata, nil +} + +``` + +## Integrating Gas Estimation in the Protocol Registry + +To integrate gas estimation into the protocol registry, the `ProtocolRegistry` interface will include a method for estimating gas. The registry will pass the chain ID, action, and transaction parameters to the protocol's `EstimateGas` method. + +### Updated `ProtocolRegistry` Interface + +```go +// ProtocolRegistry defines methods for managing and accessing DeFi protocols. +type ProtocolRegistry interface { + // Other existing methods... + + // EstimateGas estimates the gas needed for a transaction within a protocol. + // returns the estimated gas, calldata and error (in case any) + EstimateGas(ctx context.Context, chainID *big.Int, action ContractAction, params TransactionParams) (*big.Int, string, error) +} +``` + +### Implementation of ProtocolRegistry + +The `ProtocolRegistry` implementation will call the `EstimateGas` method of the specific protocol, passing the necessary parameters (chain ID, action, and transaction parameters) for gas estimation. + +```go +// EstimateGas estimates the gas required for a transaction across any registered protocol. +func (r *ProtocolRegistry) EstimateGas(ctx context.Context, chainID *big.Int, action ContractAction, params TransactionParams) (*big.Int, string, error) { + protocol, err := r.GetProtocol(chainID, params.ToAddress) + if err != nil { + return nil, err + } + + return protocol.EstimateGas(ctx, chainID, action, params) +} +``` + +## Usage Example + +Here’s how a client would use the new gas estimation functionality within the registry. After specifying the action and transaction parameters, the client can call the EstimateGas method to predict the gas required for the transaction. + +```go +// Define transaction parameters +params := protocols.TransactionParams{ + FromAddress: common.HexToAddress("0xYourAddress"), + ToAddress: common.HexToAddress("0xContractAddress"), + AmountIn: big.NewInt(1000000000000000000), // 1 ETH +} + +// Estimate gas for the transaction using the registry +gasEstimate, calldata, err := registry.EstimateGas(context.Background(), big.NewInt(1), protocols.NativeStake, params) +if err != nil { + fmt.Errorf("Error estimating gas: %v", err) + return err +} + +// Validate gas estimate +if gasEstimate.Cmp(big.NewInt(0)) <= 0 { + return fmt.Errorf("invalid gas estimate: %s", gasEstimate) +} + +fmt.Printf("Estimated Gas: %s", gasEstimate.String()) +fmt.Printf("Calldata: %s", calldata) +``` + +By having each protocol internally generate the necessary calldata and use it for gas estimation, we streamline the gas calculation process. This approach minimizes the need for external inputs like calldata and focuses on the essential parameters for gas estimation, ensuring a seamless and efficient experience across different DeFi protocols.