Skip to content

Commit

Permalink
build: add deployment cost in gas benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
CJ42 committed Sep 29, 2023
1 parent f099ac2 commit 1c0b07c
Show file tree
Hide file tree
Showing 5 changed files with 307 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.pull_request.number }}
body-file: "./benchmark.md"
body-file: "./gas_benchmark.md"
204 changes: 204 additions & 0 deletions gas_benchmark_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
{
"deployment_costs": {
"UniversalProfile": 3000497,
"KeyManager": 3439409,
"LSP1DelegateUP": 1623804,
"LSP7Mintable": 2354082,
"LSP8Mintable": 2476554
},
"runtime_costs": {
"EOA_owner": {
"execute": {
"case_1": {
"description": "Transfer 1 LYX to an EOA without data",
"gas_cost": 37537
},
"case_2": {
"description": "Transfer 1 LYX to a UP without data",
"gas_cost": 36639
},
"case_3": {
"description": "Transfer 1 LYX to an EOA with 256 bytes of data",
"gas_cost": 42210
},
"case_4": {
"description": "Transfer 1 LYX to a UP with 256 bytes of data",
"gas_cost": 44855
},
"case_5": {
"description": "Transfer 0.1 LYX to 3x EOA without data",
"gas_cost": 70862
},
"case_6": {
"description": "Transfer 0.1 LYX to 3x UP without data",
"gas_cost": 75680
},
"case_7": {
"description": "Transfer 0.1 LYX to 3x EOA with 256 bytes of data",
"gas_cost": 84814
},
"case_8": {
"description": "Transfer 0.1 LYX to 3x UPs with 256 bytes of data",
"gas_cost": 100285
}
},
"setData": {
"case_1": {
"description": "Set a 20 bytes long value",
"gas_cost": 49971
},
"case_2": {
"description": "Set a 60 bytes long value",
"gas_cost": 95293
},
"case_3": {
"description": "Set a 160 bytes long value",
"gas_cost": 164465
},
"case_4": {
"description": "Set a 300 bytes long value",
"gas_cost": 279676
},
"case_5": {
"description": "Set a 600 bytes long value",
"gas_cost": 484136
},
"case_6": {
"description": "Change the value of a data key already set",
"gas_cost": 32859
},
"case_7": {
"description": "Remove the value of a data key already set",
"gas_cost": 27333
},
"case_8": {
"description": "Set 2 data keys of 20 bytes long value",
"gas_cost": 78454
},
"case_9": {
"description": "Set 2 data keys of 100 bytes long value",
"gas_cost": 260618
},
"case_10": {
"description": "Set 3 data keys of 20 bytes long value",
"gas_cost": 105171
},
"case_11": {
"description": "Change the value of three data keys already set of 20 bytes long value",
"gas_cost": 45459
},
"case_12": {
"description": "Remove the value of three data keys already set",
"gas_cost": 41360
}
},
"tokens": {
"case_1": {
"description": "Minting a LSP7Token to a UP (No Delegate) from an EOA",
"gas_cost": 91982
},
"case_2": {
"description": "Minting a LSP7Token to an EOA from an EOA",
"gas_cost": 59289
},
"case_3": {
"description": "Transferring an LSP7Token from a UP to another UP (No Delegate)",
"gas_cost": 100092
},
"case_4": {
"description": "Minting a LSP8Token to a UP (No Delegate) from an EOA ",
"gas_cost": 159126
},
"case_5": {
"description": "Minting a LSP8Token to an EOA from an EOA ",
"gas_cost": 126433
},
"case_6": {
"description": "Transferring an LSP8Token from a UP to another UP (No Delegate)",
"gas_cost": 148899
}
}
},
"KeyManager_owner": {
"execute": {
"case_1": {
"description": "LYX transfer --> to an EOA",
"main_controller": 60408,
"restricted_controller": 73899
},
"case_2": {
"description": "LYX transfer --> to a UP",
"main_controller": 62010,
"restricted_controller": 76988
},
"case_3": {
"description": "LSP7 token transfer --> to an EOA",
"main_controller": 117832,
"restricted_controller": 132523
},
"case_4": {
"description": "LSP7 token transfer --> to a UP",
"main_controller": 254217,
"restricted_controller": 268908
},
"case_5": {
"description": "LSP8 NFT transfer --> to an EOA",
"main_controller": 182075,
"restricted_controller": 196743
},
"case_6": {
"description": "LSP8 NFT transfer --> to a UP",
"main_controller": 301707,
"restricted_controller": 316375
}
},
"setData": {
"case_1": {
"description": "Update Profile details (LSP3Profile Metadata)",
"main_controller": 68545,
"restricted_controller": 78544
},
"case_2": {
"description": "Add a new controller with permission to `SET_DATA` + 3x allowed data keys: <br/> `AddressPermissions[]` <br/> + `AddressPermissions[index]` <br/> + `AddressPermissions:Permissions:<controller>` <br/> + `AddressPermissions:AllowedERC725YDataKeys:<controller`)",
"main_controller": 211942,
"restricted_controller": 221582
},
"case_3": {
"description": "Update permissions of previous controller. Allow it now to `SUPER_SETDATA`",
"main_controller": 53432,
"restricted_controller": 56415
},
"case_4": {
"description": "Remove a controller: <br/> 1. decrease `AddressPermissions[]` Array length <br/> 2. remove the controller address at `AddressPermissions[index]` <br/> 3. set \"0x\" for the controller permissions under AddressPermissions:Permissions:<controller-address>",
"main_controller": 80426,
"restricted_controller": 91493
},
"case_5": {
"description": "Write 5x new LSP12 Issued Assets",
"main_controller": 68098,
"restricted_controller": 102702
},
"case_6": {
"description": "Update 3x data keys (first 3)",
"main_controller": 127385,
"restricted_controller": 161466
},
"case_7": {
"description": "Update 3x data keys (middle 3)",
"main_controller": 107473,
"restricted_controller": 145620
},
"case_8": {
"description": "Update 3x data keys (last 3)",
"main_controller": 127385,
"restricted_controller": 170953
},
"case_9": {
"description": "Set 2 x new data keys + add 3x new controllers",
"main_controller": 815830,
"restricted_controller": 876099
}
}
}
}
}
32 changes: 29 additions & 3 deletions scripts/ci/gas_benchmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ task('gas-benchmark', 'Benchmark gas usage of the smart contracts based on prede
const currentBenchmark = JSON.parse(fs.readFileSync(args.compare, 'utf8'));
const baseBenchmark = JSON.parse(fs.readFileSync(args.against, 'utf8'));

const deploymentCosts: Row[] = [];

const casesEOAExecute: Row[] = [];
const casesEOASetData: Row[] = [];
const casesEOATokens: Row[] = [];
Expand All @@ -40,6 +42,22 @@ task('gas-benchmark', 'Benchmark gas usage of the smart contracts based on prede
return `${formatNumber(gasDiff)} ${emoji}`;
};

// Deployment costs
for (const [key, value] of Object.entries(currentBenchmark['deployment_costs'])) {
const gasCost: any = value;
const gasDiff = gasCost - baseBenchmark['deployment_costs'][key];

deploymentCosts.push([key, value + ` (${displayGasDiff(gasDiff)})`]);
}

const generatedDeploymentCostsTable = getMarkdownTable({
table: {
head: ['Deployed contracts', '⛽ Deployment cost'],
body: deploymentCosts,
},
alignment: [Align.Left],
});

// EOA - execute
for (const [key, value] of Object.entries(
currentBenchmark['runtime_costs']['EOA_owner']['execute'],
Expand Down Expand Up @@ -162,8 +180,16 @@ task('gas-benchmark', 'Benchmark gas usage of the smart contracts based on prede
⛽ I am the Gas Bot Reporter. I keep track of the gas costs of common interactions using Universal Profiles 🆙 !
📊 Here is a summary of the gas cost with the code introduced by this PR.
## ⛽📊 Gas Benchmark Report
### Deployment Costs
${generatedDeploymentCostsTable}
### Runtime Costs
<details>
<summary>⛽📊 See Gas Benchmark report of Using UniversalProfile owned by an 🔑 EOA</summary>
<summary>UniversalProfile owned by an 🔑 EOA</summary>
### 🔀 \`execute\` scenarios
Expand All @@ -180,7 +206,7 @@ ${generatedEOATokensTable}
</details>
<details>
<summary>⛽📊 See Gas Benchmark report of Using UniversalProfile owned by an 🔒📄 LSP6KeyManager</summary>
<summary>UniversalProfile owned by a 🔒📄 LSP6KeyManager</summary>
### 🔀 \`execute\` scenarios
Expand All @@ -194,7 +220,7 @@ ${generatedKeyManagerSetDataTable}
`;

const file = 'new_gas_benchmark.md';
const file = 'gas_benchmark.md';

fs.writeFileSync(file, markdownContent, 'utf8');
});
10 changes: 5 additions & 5 deletions scripts/ci/gas_benchmark_template.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"deployment_costs": {
"Universal Profile": "",
"Key Manager": "",
"LSP1 Delegate UP": "",
"LSP7 Digital Asset": "",
"LSP8 Identifiable Digital Asset": ""
"UniversalProfile": "",
"KeyManager": "",
"LSP1DelegateUP": "",
"LSP7Mintable": "",
"LSP8Mintable": ""
},
"runtime_costs": {
"EOA_owner": {
Expand Down
72 changes: 68 additions & 4 deletions tests/Benchmark.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { expect } from 'chai';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';

import {
LSP1UniversalReceiverDelegateUP,
LSP1UniversalReceiverDelegateUP__factory,
LSP6KeyManager,

Check warning on line 9 in tests/Benchmark.test.ts

View workflow job for this annotation

GitHub Actions / build

'LSP6KeyManager' is defined but never used

Check warning on line 9 in tests/Benchmark.test.ts

View workflow job for this annotation

GitHub Actions / build

'LSP6KeyManager' is defined but never used
LSP6KeyManager__factory,
LSP7Mintable,
LSP7Mintable__factory,
Expand Down Expand Up @@ -79,6 +81,69 @@ describe('⛽📊 Gas Benchmark', () => {
fs.writeFileSync('./gas_benchmark_result.json', JSON.stringify(gasBenchmark, null, 2));
});

describe('Deployment costs', () => {
it('deploy contracts + save deployment costs', async () => {
const accounts = await ethers.getSigners();

// Universal Profile
const universalProfile = await new UniversalProfile__factory(accounts[0]).deploy(
accounts[0].address,
);

const universalProfileDeployTransaction = universalProfile.deployTransaction;
const universalProfileDeploymentReceipt = await universalProfileDeployTransaction.wait();

gasBenchmark['deployment_costs']['UniversalProfile'] =
universalProfileDeploymentReceipt.gasUsed.toNumber();

// Key Manager
const keyManager = await new LSP6KeyManager__factory(accounts[0]).deploy(
universalProfile.address,
);

const keyManagerDeployTransaction = keyManager.deployTransaction;
const keyManagerDeploymentReceipt = await keyManagerDeployTransaction?.wait();

gasBenchmark['deployment_costs']['KeyManager'] =
keyManagerDeploymentReceipt?.gasUsed.toNumber();

// LSP1 Delegate
const lsp1Delegate = await new LSP1UniversalReceiverDelegateUP__factory(accounts[0]).deploy();

const lsp1DelegateDeployTransaction = lsp1Delegate.deployTransaction;
const lsp1DelegateDeploymentReceipt = await lsp1DelegateDeployTransaction.wait();

gasBenchmark['deployment_costs']['LSP1DelegateUP'] =
lsp1DelegateDeploymentReceipt.gasUsed.toNumber();

// LSP7 Token (Mintable preset)
const lsp7Mintable = await new LSP7Mintable__factory(accounts[0]).deploy(
'Token',
'MTKN',
accounts[0].address,
false,
);

const lsp7DeployTransaction = lsp7Mintable.deployTransaction;
const lsp7DeploymentReceipt = await lsp7DeployTransaction.wait();

gasBenchmark['deployment_costs']['LSP7Mintable'] = lsp7DeploymentReceipt.gasUsed.toNumber();

// LSP8 NFT (Mintable preset)
const lsp8Mintable = await new LSP8Mintable__factory(accounts[0]).deploy(
'My NFT',
'MNFT',
accounts[0].address,
LSP8_TOKEN_ID_TYPES.NUMBER,
);

const lsp8DeployTransaction = lsp8Mintable.deployTransaction;
const lsp8DeploymentReceipt = await lsp8DeployTransaction.wait();

gasBenchmark['deployment_costs']['LSP8Mintable'] = lsp8DeploymentReceipt.gasUsed.toNumber();
});
});

describe('UniversalProfile', () => {
let context: UniversalProfileContext;

Expand Down Expand Up @@ -154,7 +219,7 @@ describe('⛽📊 Gas Benchmark', () => {
});

describe('execute Array', () => {
let universalProfile1, universalProfile2, universalProfile3;
let universalProfile1: UniversalProfile, universalProfile2, universalProfile3;

before(async () => {
context = await buildUniversalProfileContext(ethers.utils.parseEther('50'));
Expand Down Expand Up @@ -615,9 +680,8 @@ describe('⛽📊 Gas Benchmark', () => {
const deployedContracts = await setupProfileWithKeyManagerWithURD(context.accounts[2]);
aliceUP = deployedContracts[0] as UniversalProfile;

const lsp1Delegate = await new LSP1UniversalReceiverDelegateUP__factory(
context.accounts[0],
).deploy();
const lsp1Delegate: LSP1UniversalReceiverDelegateUP =
await new LSP1UniversalReceiverDelegateUP__factory(context.accounts[0]).deploy();

// the function `setupKeyManager` gives ALL PERMISSIONS to the owner as the first data key
// We also setup the following:
Expand Down

0 comments on commit 1c0b07c

Please sign in to comment.