-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(relayer): cost estimation (#16707)
- Loading branch information
1 parent
68bd435
commit 6baf7fd
Showing
9 changed files
with
273 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
193 changes: 193 additions & 0 deletions
193
packages/relayer/pkg/http/get_recommended_processing_fees.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
package http | ||
|
||
import ( | ||
"context" | ||
"math/big" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/cyberhorsey/webutils" | ||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559" | ||
"github.com/ethereum/go-ethereum/params" | ||
"github.com/labstack/echo/v4" | ||
) | ||
|
||
type getRecommendedProcessingFeesResponse struct { | ||
Fees []fee `json:"fees"` | ||
} | ||
|
||
type fee struct { | ||
Type string `json:"type"` | ||
Amount string `json:"amount"` | ||
DestChainID uint64 `json:"destChainID"` | ||
} | ||
|
||
type FeeType uint64 | ||
|
||
// gas limits | ||
var ( | ||
Eth FeeType = 900000 | ||
ERC20NotDeployed FeeType = 1650000 | ||
ERC20Deployed FeeType = 1000000 | ||
ERC721NotDeployed FeeType = 2500000 | ||
ERC721Deployed FeeType = 1500000 | ||
ERC1155NotDeployed FeeType = 2650000 | ||
ERC1155Deployed FeeType = 1650000 | ||
) | ||
|
||
var ( | ||
feeTypes = []FeeType{ | ||
Eth, | ||
ERC20Deployed, | ||
ERC20NotDeployed, | ||
ERC721Deployed, | ||
ERC721NotDeployed, | ||
ERC1155Deployed, | ||
ERC1155NotDeployed} | ||
) | ||
|
||
func (f FeeType) String() string { | ||
switch f { | ||
case Eth: | ||
return "eth" | ||
case ERC20NotDeployed: | ||
return "erc20NotDeployed" | ||
case ERC20Deployed: | ||
return "erc20Deployed" | ||
case ERC721Deployed: | ||
return "erc721Deployed" | ||
case ERC721NotDeployed: | ||
return "erc721NotDeployed" | ||
case ERC1155NotDeployed: | ||
return "erc1155NotDeployed" | ||
case ERC1155Deployed: | ||
return "erc1155Deployed" | ||
default: | ||
return "" | ||
} | ||
} | ||
|
||
type layer int | ||
|
||
const ( | ||
Layer1 layer = iota | ||
Layer2 layer = iota | ||
) | ||
|
||
// getBlockInfoResponse | ||
// | ||
// returns block info for the chains | ||
// | ||
// @Summary Get block info | ||
// @ID get-block-info | ||
// @Accept json | ||
// @Produce json | ||
// @Success 200 {object} getBlockInfoResponse | ||
// @Router /blockInfo [get] | ||
func (srv *Server) GetRecommendedProcessingFees(c echo.Context) error { | ||
fees := make([]fee, 0) | ||
|
||
srcChainID, err := srv.srcEthClient.ChainID(c.Request().Context()) | ||
if err != nil { | ||
return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) | ||
} | ||
|
||
destChainID, err := srv.destEthClient.ChainID(c.Request().Context()) | ||
if err != nil { | ||
return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) | ||
} | ||
|
||
srcGasTipCap, err := srv.srcEthClient.SuggestGasTipCap(c.Request().Context()) | ||
if err != nil { | ||
return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) | ||
} | ||
|
||
srcBaseFee, err := srv.getDestChainBaseFee(c.Request().Context(), Layer1, srcChainID) | ||
if err != nil { | ||
return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) | ||
} | ||
|
||
destBaseFee, err := srv.getDestChainBaseFee(c.Request().Context(), Layer2, destChainID) | ||
if err != nil { | ||
return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) | ||
} | ||
|
||
destGasTipCap, err := srv.destEthClient.SuggestGasTipCap(c.Request().Context()) | ||
if err != nil { | ||
return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) | ||
} | ||
|
||
for _, f := range feeTypes { | ||
fees = append(fees, fee{ | ||
Type: f.String(), | ||
Amount: srv.getCost(c.Request().Context(), uint64(f), srcGasTipCap, srcBaseFee, Layer1).String(), | ||
DestChainID: srcChainID.Uint64(), | ||
}) | ||
|
||
fees = append(fees, fee{ | ||
Type: f.String(), | ||
Amount: srv.getCost(c.Request().Context(), uint64(f), destGasTipCap, destBaseFee, Layer2).String(), | ||
DestChainID: destChainID.Uint64(), | ||
}) | ||
} | ||
|
||
resp := getRecommendedProcessingFeesResponse{ | ||
Fees: fees, | ||
} | ||
|
||
return c.JSON(http.StatusOK, resp) | ||
} | ||
|
||
func (srv *Server) getCost( | ||
ctx context.Context, | ||
gasLimit uint64, | ||
gasTipCap *big.Int, | ||
baseFee *big.Int, | ||
destLayer layer, | ||
) *big.Int { | ||
cost := new(big.Int).Mul( | ||
new(big.Int).SetUint64(gasLimit), | ||
new(big.Int).Add(gasTipCap, baseFee)) | ||
|
||
if destLayer == Layer2 { | ||
return cost | ||
} | ||
|
||
costRat := new(big.Rat).SetInt(cost) | ||
|
||
multiplierRat := new(big.Rat).SetFloat64(srv.processingFeeMultiplier) | ||
|
||
costRat.Mul(costRat, multiplierRat) | ||
|
||
costAfterMultiplier := new(big.Int).Div(costRat.Num(), costRat.Denom()) | ||
|
||
return costAfterMultiplier | ||
} | ||
|
||
func (srv *Server) getDestChainBaseFee(ctx context.Context, l layer, chainID *big.Int) (*big.Int, error) { | ||
blk, err := srv.destEthClient.BlockByNumber(ctx, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var baseFee *big.Int | ||
|
||
// if layerL1 bridge, we need to calc basefee on Layer 2, since it's the dest chain | ||
if l == Layer1 { | ||
gasUsed := uint32(blk.GasUsed()) | ||
timeSince := uint64(time.Since(time.Unix(int64(blk.Time()), 0))) | ||
bf, err := srv.taikoL2.GetBasefee(&bind.CallOpts{Context: ctx}, timeSince, gasUsed) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
baseFee = bf.Basefee | ||
} else { | ||
cfg := params.NetworkIDToChainConfigOrDefault(chainID) | ||
baseFee = eip1559.CalcBaseFee(cfg, blk.Header()) | ||
} | ||
|
||
return baseFee, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.