Skip to content

Commit

Permalink
Call optimism Gas Price Oracle to get L1 fee when transfer all native…
Browse files Browse the repository at this point in the history
… token
  • Loading branch information
10gic committed Jun 22, 2024
1 parent ed6a051 commit a34064e
Showing 1 changed file with 54 additions and 2 deletions.
56 changes: 54 additions & 2 deletions cmd/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ func validationTransferCmdOpts() bool {
return true
}

const gasUsedByTransferEth = 21000 // The gas used by any transfer is always 21000
// https://docs.optimism.io/builders/tools/build/oracles#gas-oracle
var l1GasPriceOracle = common.HexToAddress("0x420000000000000000000000000000000000000F")

const gasUsedByTransferEth = 21000 // The gas used by ETH transfer tx is 21000

func getGasPrice(client *ethclient.Client) (*big.Int, error) {
var gasPrice *big.Int
Expand Down Expand Up @@ -126,17 +129,53 @@ var transferCmd = &cobra.Command{
if transferAmt == "all" {
// transfer all balance (only reserve some gas just pay for this tx) to target address
fromAddr := extractAddressFromPrivateKey(buildPrivateKeyFromHex(globalOptPrivateKey))

// Get current balance
balance, err := globalClient.EthClient.BalanceAt(ctx, fromAddr, nil)
checkErr(err)

log.Printf("balance of %v is %v wei", fromAddr.String(), balance.String())

gasMayUsed := big.NewInt(0).Mul(gasPrice, big.NewInt(gasUsedByTransferEth))
var gasLimit = globalOptGasLimit
if globalOptGasLimit == 0 {
// If globalOptGasLimit is not specified, use the default value gasUsedByTransferEth
gasLimit = gasUsedByTransferEth
}
gasMayUsed := big.NewInt(0).Mul(gasPrice, big.NewInt(int64(gasLimit)))

if gasMayUsed.Cmp(balance) > 0 {
log.Fatalf("insufficient balance %v, can not pay for gas %v", balance, gasMayUsed)
}

l1GasPriceOracleExisted, err := isContractAddress(globalClient.EthClient, l1GasPriceOracle)
if err != nil {
log.Fatalf("isContractAddress failed %v", err)
}
// If l1GasPriceOracle is existed in current chain, the current chain is probability L2 chain, and need L1 fee when submit tx
// We must subtract `L2 fee + L1 fee` if use want transfer 'all' native token
if l1GasPriceOracleExisted {
// Estimate L1 Fee
privateKey := buildPrivateKeyFromHex(globalOptPrivateKey)
fromAddress := extractAddressFromPrivateKey(privateKey)
toAddr := common.HexToAddress(targetAddress)
signedTx, err := BuildSignedTx(globalClient.EthClient, privateKey, &fromAddress, &toAddr, big.NewInt(0).Sub(balance, gasMayUsed), gasPrice, common.FromHex(transferHexData), nil)
if err != nil {
log.Fatalf("BuildSignedTx fail: %v", err)
}
rawTx, err := GenRawTx(signedTx)
if err != nil {
log.Fatalf("GenRawTx fail: %v", err)
}
l1Fee, err := getL1Fee(globalClient.RpcClient, rawTx)
if err != nil {
log.Fatalf("getL1Fee failed %v", err)
}
log.Printf("L2 fee %v", gasMayUsed.String())
log.Printf("L1 fee %v", l1Fee.String())
// L2 fee + L1 fee
gasMayUsed.Add(gasMayUsed, l1Fee)
}

amountBigInt := big.NewInt(0).Sub(balance, gasMayUsed)
amount = bigInt2Decimal(amountBigInt)

Expand All @@ -163,3 +202,16 @@ func TransferHelper(rcpClient *rpc.Client, client *ethclient.Client, privateKeyH
var toAddr = common.HexToAddress(toAddress)
return Transact(rcpClient, client, buildPrivateKeyFromHex(privateKeyHex), &toAddr, amountInWei, gasPrice, data)
}

// getL1Fee call contract function getL1Fee to get the L1 fee
func getL1Fee(rcpClient *rpc.Client, rawTx string) (*big.Int, error) {
txInputData, err := buildTxInputData("getL1Fee(bytes)", []string{rawTx})
if err != nil {
return nil, err
}
output, err := Call(rcpClient, l1GasPriceOracle, txInputData)
if err != nil {
return nil, err
}
return new(big.Int).SetBytes(output), nil
}

0 comments on commit a34064e

Please sign in to comment.