Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Added Arbitrum gas results handling feature #138

Merged
merged 1 commit into from
Feb 15, 2022
Merged
Show file tree
Hide file tree
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
28 changes: 28 additions & 0 deletions contracts/ArbitrumGasCosts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Arbitrum Gas Costs

This file compares the gas costs between one BLS transaction to BLSExpander.blsCallMultiSameCallerContractFunction
and multiple regular ERC20 token transfers. If 31 transfers are aggregated inside one BLS transaction, then a comparison
will be made between that one BLS transaction and 31 normal token transfers.

### Table Fields:
* Commit - git commit the gas results were computed for
* Tx Type - "BLS" for BLS aggregated transactions or "Normal" for normal token transfers
* Number Txs - Number of transactions aggregated in one BLS transaction
* Units - Units may vary slightly from run to run, but should remain close to constant if the bls-wallet implementation stays the same.
* L1 Calldata Units Used - number of calldata units stored on L1 for the transaction(s)
* L1 Transaction Units - number of distinct transactions (always 1 for BLS transactions)
* L2 Computation Units - number of computation units used on L2
* L2 Storage Units - number of L2 storage units used
* Cost - All costs are denominated in ETH according to current Arbitrum mainnet prices
* L1 Calldata Cost - Cost of the transaction due to storing calldata on L1
* L2 Tx Cost - Cost of sending the transactions (the more transactions sent, the higher this cost)
* L2 Storage Cost - Cost of storing data in L2
* L2 Computation Cost - Cost of computation on L2
* Total Cost - Total cost of either the BLS transaction, or all of the normal token transfers
* Tx Hash - Hash of the transaction on the Arbitrum Testnet

### Results
| Commit | Tx Type | Number Txs | L1 Calldata Units Used | L1 Transaction Units | L2 Computation Units | L2 Storage Units | L1 Calldata Cost | L2 Tx Cost | L2 Storage Cost | L2 Computation Cost | Total Cost (ETH) | Tx Hash |
| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |---------------------| ----------- |------------------|
| 116c920b2469d279773c2546b0f00575828c11c2 | BLS | 31 | 23388 | 1 | 312116 | 1 | 0.0015691 | 0.0001342 | 0.0000292 | 0.0001821 | 0.0019145 | 0xae4c5f62536743630eab5056671296e130bcd9d64650013a86c268fd59c6bc81 |
| 116c920b2469d279773c2546b0f00575828c11c2 | Normal | 31 | 60388 | 31 | 25730 | 0 | 0.0040514 | 0.0041596 | 0.0000000 | 0.0000150 | 0.0082260 | 0x78cfceea76233ed83a49d67919ec4e6ce30d71a15cbcb64821514a1eabed257c |
6 changes: 4 additions & 2 deletions contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"@openzeppelin/contracts": "^4.3.2",
"dotenv": "^10.0.0",
"ethers": "^5.5.1",
"hardhat": "^2.6.7"
"hardhat": "^2.6.7",
"web3": "^1.7.0"
jacque006 marked this conversation as resolved.
Show resolved Hide resolved
},
"devDependencies": {
"@nomiclabs/hardhat-etherscan": "^2.1.3",
Expand Down Expand Up @@ -46,6 +47,7 @@
"solidity-coverage": "^0.7.16",
"ts-node": "^10.1.0",
"typechain": "^5.1.2",
"typescript": "^4.3.5"
"typescript": "^4.3.5",
"web3-utils": "^1.7.0"
}
}
95 changes: 54 additions & 41 deletions contracts/scripts/test/measure_gas.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* eslint-disable no-process-exit */

import { BigNumber } from "ethers";
import { solidityPack } from "ethers/lib/utils";
import { Bundle } from "../../clients/src";
import Fixture from "../../shared/helpers/Fixture";
import TokenHelper from "../../shared/helpers/TokenHelper";
import { processGasResultsToFile } from "../util/arbitrum_gas_util";
import { network } from "hardhat";

let fx: Fixture;
let th: TokenHelper;
Expand All @@ -16,7 +16,7 @@ async function main() {
}

async function logGasForTransfers() {
const transferCounts = [29, 30, 31];
const transferCounts = [31];
console.log("Batch transfers for: ", transferCounts);
for (let i = 0; i < transferCounts.length; i++) {
const transferCount = transferCounts[i];
Expand All @@ -33,85 +33,98 @@ async function logGasForTransfers() {
th = new TokenHelper(fx);
const blsWallets = await th.walletTokenSetup();

// encode transfer to consecutive addresses of 1*10^-18 of a token
// signed by first bls wallet
const txs: Bundle[] = [];
const startNonce: number = (await blsWallets[0].Nonce()).toNumber();
let nonce = startNonce;
const nonce: number = (await blsWallets[0].Nonce()).toNumber();
console.log(
"airdropper balance before",
await th.testToken.balanceOf(blsWallets[0].address),
);

const AddressZero = "0x" + "0".repeat(40);

console.log("Signing txs from nonce", nonce);

const actionsArr = [];
const encodedFunctions = [];
const testAddress = "0x" + (1).toString(16).padStart(40, "0");
const testAmount = BigNumber.from(1).toHexString();
for (let i = 0; i < transferCount; i++) {
const tx = blsWallets[i].sign({
nonce: BigNumber.from(nonce++),
actions: [
{
ethValue: BigNumber.from(0),
contractAddress: th.testToken.address,
encodedFunction: th.testToken.interface.encodeFunctionData(
"transfer",
[
"0x" + (i + 1).toString(16).padStart(40, "0"),
BigNumber.from(i).toHexString(),
],
),
},
],
});
encodedFunctions.push(
th.testToken.interface.encodeFunctionData("transfer", [
testAddress,
testAmount,
]),
);

txs.push(tx);
actionsArr.push({
ethValue: BigNumber.from(0),
contractAddress: th.testToken.address,
encodedFunction: encodedFunctions[i],
});
}

const aggTx = fx.blsWalletSigner.aggregate(txs);
const operation = {
nonce: BigNumber.from(nonce),
actions: actionsArr,
};
const tx = blsWallets[0].sign(operation);

const aggTx = fx.blsWalletSigner.aggregate([tx]);
console.log("Done signing & aggregating.");

const encodedFunction = solidityPack(
["bytes"],
[txs[0].operations[0].actions[0].encodedFunction],
[tx.operations[0].actions[0].encodedFunction],
);

const methodId = encodedFunction.slice(0, 10);
const encodedParamSets = encodedFunctions.map(
(encFunction) => `0x${encFunction.slice(10)}`,
);

const encodedParamSets = txs.map((tx) => `0x${encodedFunction.slice(10)}`);
try {
const publicKeyHash = fx.blsWalletSigner.getPublicKeyHash(
const publicKey = fx.blsWalletSigner.getPublicKey(
blsWallets[0].privateKey,
);

console.log("Estimating...", fx.blsExpander.address);
const gasEstimate =
await fx.blsExpander.estimateGas.blsCallMultiSameCallerContractFunction(
publicKeyHash,
startNonce,
publicKey,
nonce,
aggTx.signature,
AddressZero,
Array(txs.length).fill(0),
th.testToken.address,
methodId,
encodedParamSets,
);

console.log("Sending...");
console.log("Sending Agg Tx...");
gasResults.estimate = gasEstimate.toNumber();
const response =
await fx.blsExpander.blsCallMultiSameCallerContractFunction(
publicKeyHash,
startNonce,
publicKey,
nonce,
aggTx.signature,
AddressZero,
Array(txs.length).fill(0),
th.testToken.address,
methodId,
encodedParamSets,
);
gasResults.limit = (response.gasLimit as BigNumber).toNumber();
console.log("waiting");
console.log("Waiting");
const receipt = await response.wait();

// Store gas results to file if testing on Arbitrum network
if (network.name === "arbitrum_testnet") {
console.log("Sending normal token transfer...");
const normalResponse = await th.testToken
.connect(th.fx.signers[0])
.transfer(testAddress, testAmount);
const normalTransferReceipt = await normalResponse.wait();

await processGasResultsToFile(
receipt.transactionHash,
normalTransferReceipt.transactionHash,
transferCount,
);
}

gasResults.used = (receipt.gasUsed as BigNumber).toNumber();
gasResults.txHash = receipt.transactionHash;
console.log("Done\n");
Expand Down
Loading