71 lines
4.5 KiB
JavaScript
71 lines
4.5 KiB
JavaScript
import { Transaction, parseUnits } from 'ethers';
|
|
import { OptimismL1FeeOracle__factory } from './contracts';
|
|
import { getProvider } from './providers';
|
|
import { convertETHToTokenAmount } from './utils';
|
|
const DUMMY_ADDRESS = '0x1111111111111111111111111111111111111111';
|
|
const DUMMY_NONCE = '0x1111111111111111111111111111111111111111111111111111111111111111';
|
|
const DUMMY_WITHDRAW_DATA = '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111';
|
|
export class TornadoFeeOracle {
|
|
constructor(netId, rpcUrl, config) {
|
|
const { optimismL1FeeOracleAddress } = config;
|
|
if (optimismL1FeeOracleAddress) {
|
|
const provider = getProvider(netId, rpcUrl, config);
|
|
this.optimismL1FeeOracle = OptimismL1FeeOracle__factory.connect(optimismL1FeeOracleAddress, provider);
|
|
}
|
|
}
|
|
/**
|
|
* Calculate L1 fee for op-stack chains
|
|
*
|
|
* This is required since relayers would pay the full transaction fees for users
|
|
*/
|
|
fetchL1OptimismFee(tx) {
|
|
if (!this.optimismL1FeeOracle) {
|
|
return new Promise((resolve) => resolve(BigInt(0)));
|
|
}
|
|
if (!tx) {
|
|
// this tx is only used to simulate bytes size of the encoded tx so has nothing to with the accuracy
|
|
// inspired by the old style classic-ui calculation
|
|
tx = {
|
|
type: 0,
|
|
gasLimit: 1000000,
|
|
nonce: Number(DUMMY_NONCE),
|
|
data: DUMMY_WITHDRAW_DATA,
|
|
gasPrice: parseUnits('1', 'gwei'),
|
|
from: DUMMY_ADDRESS,
|
|
to: DUMMY_ADDRESS,
|
|
};
|
|
}
|
|
return this.optimismL1FeeOracle.getL1Fee.staticCall(Transaction.from(tx).unsignedSerialized);
|
|
}
|
|
/**
|
|
* We don't need to distinguish default refunds by tokens since most users interact with other defi protocols after withdrawal
|
|
* So we default with 1M gas which is enough for two or three swaps
|
|
* Using 30 gwei for default but it is recommended to supply cached gasPrice value from the UI
|
|
*/
|
|
defaultEthRefund(gasPrice, gasLimit) {
|
|
return (gasPrice ? BigInt(gasPrice) : parseUnits('30', 'gwei')) * BigInt(gasLimit || 1000000);
|
|
}
|
|
/**
|
|
* Calculates token amount for required ethRefund purchases required to calculate fees
|
|
*/
|
|
calculateTokenAmount(ethRefund, tokenPriceInEth, tokenDecimals) {
|
|
return convertETHToTokenAmount(ethRefund, tokenPriceInEth, tokenDecimals);
|
|
}
|
|
/**
|
|
* Warning: For tokens you need to check if the fees are above denomination
|
|
* (Usually happens for small denomination pool or if the gas price is high)
|
|
*/
|
|
calculateRelayerFee({ gasPrice, gasLimit = 600000, l1Fee = 0, denomination, ethRefund = BigInt(0), tokenPriceInWei, tokenDecimals = 18, relayerFeePercent = 0.33, isEth = true, premiumPercent = 20, }) {
|
|
const gasCosts = BigInt(gasPrice) * BigInt(gasLimit) + BigInt(l1Fee);
|
|
const relayerFee = (BigInt(denomination) * BigInt(Math.floor(10000 * relayerFeePercent))) / BigInt(10000 * 100);
|
|
if (isEth) {
|
|
// Add 20% premium
|
|
return ((gasCosts + relayerFee) * BigInt(premiumPercent ? 100 + premiumPercent : 100)) / BigInt(100);
|
|
}
|
|
const feeInEth = gasCosts + BigInt(ethRefund);
|
|
return (((convertETHToTokenAmount(feeInEth, tokenPriceInWei, tokenDecimals) + relayerFee) *
|
|
BigInt(premiumPercent ? 100 + premiumPercent : 100)) /
|
|
BigInt(100));
|
|
}
|
|
}
|
|
//# sourceMappingURL=feeOracle.js.map
|