Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: get gas parameters from statechain event #4125

Merged
merged 2 commits into from
Oct 17, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 36 additions & 20 deletions bouncer/shared/gaslimit_ccm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { signAndSendTxEthSilent } from './send_eth';
// on the lenght of the message.
const MIN_BASE_GAS_OVERHEAD = 100000;
const BASE_GAS_OVERHEAD_BUFFER = 20000;
const ETHEREUM_BASE_FEE_MULTIPLIER = 2;
const CFE_GAS_LIMIT_CAP = 10000000;
// Arbitrary gas consumption values for testing. The total default gas used is then ~360-380k depending on the parameters.
let DEFAULT_GAS_CONSUMPTION = 260000;
Expand Down Expand Up @@ -131,6 +130,20 @@ async function testGasLimitSwap(
},
() => swapScheduledObserved,
);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const broadcastIdToTxPayload: { [key: string]: any } = {};
const broadcastRequesthandle = observeEvent(
'ethereumBroadcaster:TransactionBroadcastRequest',
chainflipApi,
(event) => {
broadcastIdToTxPayload[event.data.broadcastAttemptId.broadcastId] =
event.data.transactionPayload;
return false;
},
() => swapScheduledObserved,
);

await send(sourceAsset, depositAddress);

const {
Expand All @@ -141,36 +154,33 @@ async function testGasLimitSwap(
!(
swapId in swapIdToEgressAmount &&
swapId in swapIdToEgressId &&
swapIdToEgressId[swapId] in egressIdToBroadcastId
swapIdToEgressId[swapId] in egressIdToBroadcastId &&
egressIdToBroadcastId[swapIdToEgressId[swapId]] in broadcastIdToTxPayload
)
) {
await sleep(3000);
}
swapScheduledObserved = true;
await Promise.all([swapExecutedHandle, swapEgressHandle, ccmBroadcastHandle]);
await Promise.all([
swapExecutedHandle,
swapEgressHandle,
ccmBroadcastHandle,
broadcastRequesthandle,
]);

const egressBudgetAmount =
sourceAsset !== Assets.ETH
? Number(swapIdToEgressAmount[swapId].replace(/,/g, ''))
: messageMetadata.gasBudget;

const { baseFee, priorityFee } = await getChainFees();

// On the state chain the gasLimit is calculated from the egressBudget and the MaxFeePerGas
// max_fee_per_gas = 2 * baseFee + priorityFee
// gasLimitBudget = egressBudgetAmount / (1 * baseFee + priorityFee)
const currentFeePerGas = baseFee + priorityFee;
const maxFeePerGas = ETHEREUM_BASE_FEE_MULTIPLIER * baseFee + priorityFee;
const gasLimitBudget = egressBudgetAmount / currentFeePerGas;
const txPayload = broadcastIdToTxPayload[egressIdToBroadcastId[swapIdToEgressId[swapId]]];
const maxFeePerGas = Number(txPayload.maxFeePerGas.replace(/,/g, ''));
const gasLimitBudget = Number(txPayload.gasLimit.replace(/,/g, ''));

const byteLength = Web3.utils.hexToBytes(messageMetadata.message).length;

const minGasLimitRequired = gasConsumption + MIN_BASE_GAS_OVERHEAD + byteLength * GAS_PER_BYTE;

console.log(
`${tag} baseFee: ${baseFee}, priorityFee: ${priorityFee}, maxFeePerGas: ${maxFeePerGas}`,
);

// This is a very rough approximation for the gas limit required. A buffer is added to account for that.
if (minGasLimitRequired + BASE_GAS_OVERHEAD_BUFFER >= gasLimitBudget) {
observeCcmReceived(
Expand All @@ -186,7 +196,9 @@ async function testGasLimitSwap(
}
});
// Expect Broadcast Aborted
console.log(`${tag} Gas budget is too low. Expecting BroadcastAborted event.`);
console.log(
`${tag} Gas budget of ${gasLimitBudget} is too low. Expecting BroadcastAborted event.`,
);
await observeEvent(
'ethereumBroadcaster:BroadcastAborted',
await getChainflipApi(),
Expand All @@ -199,6 +211,8 @@ async function testGasLimitSwap(
}`,
);
} else if (minGasLimitRequired < gasLimitBudget) {
console.log(`${tag} Gas budget ${gasLimitBudget}. Expecting successful broadcast.`);

const ccmReceived = await observeCcmReceived(
sourceAsset,
destAsset,
Expand All @@ -217,18 +231,20 @@ async function testGasLimitSwap(

// Priority fee is not fully deterministic so we just log it for now
if (tx.maxFeePerGas !== maxFeePerGas.toString()) {
console.log(
`${tag} Max fee per gas in the transaction ${tx.maxFeePerGas} different than expected ${maxFeePerGas}`,
throw new Error(
`${tag} Tx Max fee per gas ${tx.maxFeePerGas} different than expected ${maxFeePerGas}`,
);
}
if (Math.trunc(tx.gas) !== Math.min(Math.trunc(gasLimitBudget), CFE_GAS_LIMIT_CAP)) {
throw new Error(`${tag} Gas limit in the transaction is different than the one expected!`);
if (tx.gas !== Math.min(gasLimitBudget, CFE_GAS_LIMIT_CAP)) {
throw new Error(`${tag} Tx gas limit ${tx.gas} different than expected ${gasLimitBudget}`);
}
// This should not happen by definition, as maxFeePerGas * gasLimit < egressBudgetAmount
if (totalFee > egressBudgetAmount) {
throw new Error(`${tag} Transaction fee paid is higher than the budget paid by the user!`);
}
console.log(`${tag} Swap success! TxHash: ${ccmReceived?.txHash as string}!`);
} else {
console.log(`${tag} Budget too tight, can't determine if swap should succeed.`);
}
}

Expand Down