From d962c3ca1a8ea945993f99d6fdea039d75aff44c Mon Sep 17 00:00:00 2001 From: pingke Date: Fri, 26 Jul 2024 11:42:27 +0800 Subject: [PATCH 01/13] add deploy script for integration test on L2 --- package.json | 2 + scripts/deployL2-it.js | 131 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 scripts/deployL2-it.js diff --git a/package.json b/package.json index 366048f..8118c00 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,8 @@ "deploy": "npx hardhat run scripts/deploy.js --network sepolia", "deployL2Dev": "npx hardhat run scripts/deployL2.js --network qkc_devnet", "deployL2Test": "npx hardhat run scripts/deployL2.js --network qkc_testnet" + "deployL2ITDev": "npx hardhat run scripts/deployL2-it.js --network qkc_devnet" + "deployL2ITTest": "npx hardhat run scripts/deployL2-it.js --network qkc_testnet" }, "workspaces": { "packages": [ diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js new file mode 100644 index 0000000..217e993 --- /dev/null +++ b/scripts/deployL2-it.js @@ -0,0 +1,131 @@ +const hre = require("hardhat"); +const dotenv = require("dotenv") +dotenv.config() + + +let ownerAddress = null; +let treasuryAddress = null; +const adminContractAddr = ""; +const storageContractProxy = ""; +const gasPrice = null; + +const config = [ + 17, // maxKvSizeBits, 131072 + 32, // shardSizeBits ~ 4G + 2, // randomChecks + 7200, // cutoff = 2/3 * target internal (3 hours), 3 * 3600 * 2/3 + 32, // diffAdjDivisor + 100, // treasuryShare, means 1% +]; +const storageCost = 1500000000000000; // storageCost - 1,500,000Gwei forever per blob - https://ethresear.ch/t/ethstorage-scaling-ethereum-storage-via-l2-and-da/14223/6#incentivization-for-storing-m-physical-replicas-1 +const dcfFactor = 340282366367469178095360967382638002176n; // dcfFactor, it mean 0.95 for yearly discount + +async function verifyContract(contract, args) { + // if (!process.env.ETHERSCAN_API_KEY) { + // return; + // } + // await hre.run("verify:verify", { + // address: contract, + // constructorArguments: args, + // }); +} + +async function deployContract() { + const startTime = Math.floor(new Date().getTime() / 1000); + + const [deployer] = await hre.ethers.getSigners(); + ownerAddress = deployer.address; + treasuryAddress = deployer.address; + + const StorageContract = await hre.ethers.getContractFactory("EthStorageContractL2"); + // refer to https://docs.google.com/spreadsheets/d/11DHhSang1UZxIFAKYw6_Qxxb-V40Wh1lsYjY2dbIP5k/edit#gid=0 + const implContract = await StorageContract.deploy( + config, + startTime, // startTime + storageCost, + dcfFactor, + { gasPrice: gasPrice } + ); + await implContract.deployed(); + const impl = implContract.address; + console.log("storage impl address is ", impl); + + const data = implContract.interface.encodeFunctionData("initialize", [ + 1572864, // minimumDiff 0.1 * 180 * 1024 * 1024 / 12 = 1572864 for 0.1 replicas that can have 1M IOs in one epoch + 3145728000000000000000n, // prepaidAmount - 50% * 2^39 / 131072 * 1500000Gwei, it also means 3145 ETH for half of the shard + 1048576, // nonceLimit 1024 * 1024 = 1M samples and finish sampling in 1.3s with IO rate 6144 MB/s: 4k * 2(random checks) / 6144 = 1.3s + treasuryAddress, // treasury + ownerAddress, + ]); + console.log(impl, ownerAddress, data); + const EthStorageUpgradeableProxy = await hre.ethers.getContractFactory("EthStorageUpgradeableProxy"); + const ethStorageProxy = await EthStorageUpgradeableProxy.deploy(impl, ownerAddress, data, { gasPrice: gasPrice }); + await ethStorageProxy.deployed(); + const admin = await ethStorageProxy.admin(); + + console.log("storage admin address is ", admin); + console.log("storage contract address is ", ethStorageProxy.address); + const receipt = await hre.ethers.provider.getTransactionReceipt(ethStorageProxy.deployTransaction.hash); + console.log( + "deployed in block number", + receipt.blockNumber, + "at", + new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) + ); + + // fund 50 qkc into the storage contract to give reward for empty mining + const ethStorage = StorageContract.attach(ethStorageProxy.address); + const tx = await ethStorage.sendValue({ value: hre.ethers.utils.parseEther("50") }); + await tx.wait(); + console.log("balance of " + ethStorage.address, await hre.ethers.provider.getBalance(ethStorage.address)); + + // verify contract + await verifyContract(ethStorageProxy.address); + await verifyContract(impl, [config, startTime, storageCost, dcfFactor]); +} + +async function updateContract() { + const StorageContract = await hre.ethers.getContractFactory("EthStorageContractL2"); + + // get start time + const ethStorage = StorageContract.attach(storageContractProxy); + const startTime = await ethStorage.startTime(); + + // deploy + const implContract = await StorageContract.deploy( + config, + startTime, // startTime + storageCost, + dcfFactor, + { gasPrice: gasPrice } + ); + await implContract.deployed(); + const impl = implContract.address; + console.log("storage impl address is ", impl); + + // set impl + const EthStorageAdmin = await hre.ethers.getContractAt("IProxyAdmin", adminContractAddr); + const tx = await EthStorageAdmin.upgradeAndCall(storageContractProxy, impl, "0x"); + await tx.wait(); + console.log("update contract success!"); + + // verify contract + await verifyContract(impl, [config, startTime, storageCost, dcfFactor]); +} + +async function main() { + if (!storageContractProxy) { + // create + await deployContract(); + } else { + // update + await updateContract(); + } +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); From 05a77bc80a0688f8cf7badf942d6a37a9a5c06ea Mon Sep 17 00:00:00 2001 From: pingke Date: Fri, 26 Jul 2024 14:45:13 +0800 Subject: [PATCH 02/13] fix bug --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8118c00..f8073eb 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "prettier:fix": "prettier --write contracts/**/*.sol test/**/*.js scripts/**/*.js", "deploy": "npx hardhat run scripts/deploy.js --network sepolia", "deployL2Dev": "npx hardhat run scripts/deployL2.js --network qkc_devnet", - "deployL2Test": "npx hardhat run scripts/deployL2.js --network qkc_testnet" - "deployL2ITDev": "npx hardhat run scripts/deployL2-it.js --network qkc_devnet" + "deployL2Test": "npx hardhat run scripts/deployL2.js --network qkc_testnet", + "deployL2ITDev": "npx hardhat run scripts/deployL2-it.js --network qkc_devnet", "deployL2ITTest": "npx hardhat run scripts/deployL2-it.js --network qkc_testnet" }, "workspaces": { From 00db5a4aa54dacee6806c5ad192206ec759ff4e6 Mon Sep 17 00:00:00 2001 From: pingke Date: Sun, 28 Jul 2024 17:40:28 +0800 Subject: [PATCH 03/13] add export contract address --- scripts/deployL2-it.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index 217e993..77ef591 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -1,3 +1,4 @@ +const fs = require('fs'); const hre = require("hardhat"); const dotenv = require("dotenv") dotenv.config() @@ -51,7 +52,7 @@ async function deployContract() { console.log("storage impl address is ", impl); const data = implContract.interface.encodeFunctionData("initialize", [ - 1572864, // minimumDiff 0.1 * 180 * 1024 * 1024 / 12 = 1572864 for 0.1 replicas that can have 1M IOs in one epoch + 1572864, // minimumDiff 0.1 * 180 (3 minutes) * 1024 * 1024 / 12 = 1572864 for 0.1 replicas that can have 1M IOs in one epoch 3145728000000000000000n, // prepaidAmount - 50% * 2^39 / 131072 * 1500000Gwei, it also means 3145 ETH for half of the shard 1048576, // nonceLimit 1024 * 1024 = 1M samples and finish sampling in 1.3s with IO rate 6144 MB/s: 4k * 2(random checks) / 6144 = 1.3s treasuryAddress, // treasury @@ -65,6 +66,7 @@ async function deployContract() { console.log("storage admin address is ", admin); console.log("storage contract address is ", ethStorageProxy.address); + fs.writeFileSync("exportcontractaddress.sh", "export ES_NODE_CONTRACT_ADDRESS="+ethStorageProxy.address); const receipt = await hre.ethers.provider.getTransactionReceipt(ethStorageProxy.deployTransaction.hash); console.log( "deployed in block number", From f8b03b5dda47209c21bcf2f2d46172265dc79e98 Mon Sep 17 00:00:00 2001 From: pingke Date: Sun, 28 Jul 2024 23:47:27 +0800 Subject: [PATCH 04/13] update --- scripts/deployL2-it.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index 77ef591..c48d362 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -66,7 +66,7 @@ async function deployContract() { console.log("storage admin address is ", admin); console.log("storage contract address is ", ethStorageProxy.address); - fs.writeFileSync("exportcontractaddress.sh", "export ES_NODE_CONTRACT_ADDRESS="+ethStorageProxy.address); + fs.writeFileSync(".caddr", ethStorageProxy.address); const receipt = await hre.ethers.provider.getTransactionReceipt(ethStorageProxy.deployTransaction.hash); console.log( "deployed in block number", From ba7a9e660467559458665897e11e2aa78b027e9f Mon Sep 17 00:00:00 2001 From: pingke Date: Tue, 30 Jul 2024 19:54:31 +0800 Subject: [PATCH 05/13] add wait for contract finalized --- scripts/deployL2-it.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index c48d362..f7f4fcc 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -84,6 +84,30 @@ async function deployContract() { // verify contract await verifyContract(ethStorageProxy.address); await verifyContract(impl, [config, startTime, storageCost, dcfFactor]); + + // wait for contract finalized + await waitForFinalized (receipt.blockNumber) +} + +async function waitForFinalized (number) { + if number == 0 { + return + } + + while (true) { + const block = await hre.ethers.provider.getBlock("finalized") + console.log( + "finalized block number is", + block.number, + "at", + new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) + ); + + if number > block.number{ + return + } + setTimeout( 60 * 1000) + } } async function updateContract() { From 7d1f4e73f336c4e6721e82b509a071f82ba89f58 Mon Sep 17 00:00:00 2001 From: pingke Date: Tue, 30 Jul 2024 20:02:31 +0800 Subject: [PATCH 06/13] fix --- scripts/deployL2-it.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index f7f4fcc..04022a6 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -91,11 +91,11 @@ async function deployContract() { async function waitForFinalized (number) { if number == 0 { - return + return; } while (true) { - const block = await hre.ethers.provider.getBlock("finalized") + const block = await hre.ethers.provider.getBlock("finalized"); console.log( "finalized block number is", block.number, @@ -104,9 +104,9 @@ async function waitForFinalized (number) { ); if number > block.number{ - return + return; } - setTimeout( 60 * 1000) + setTimeout( 60 * 1000); } } From 8732f8a0a97c189ad6b5b0334597aad5b2beebb6 Mon Sep 17 00:00:00 2001 From: pingke Date: Tue, 30 Jul 2024 20:33:15 +0800 Subject: [PATCH 07/13] fix --- scripts/deployL2-it.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index 04022a6..15b2886 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -89,8 +89,8 @@ async function deployContract() { await waitForFinalized (receipt.blockNumber) } -async function waitForFinalized (number) { - if number == 0 { +async function waitForFinalized(number) { + if (number == 0) { return; } @@ -103,10 +103,10 @@ async function waitForFinalized (number) { new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) ); - if number > block.number{ + if (number < block.number) { return; } - setTimeout( 60 * 1000); + setTimeout(60 * 1000); } } From c732f47851f39c4758e409220d27557906fdcc81 Mon Sep 17 00:00:00 2001 From: pingke Date: Tue, 30 Jul 2024 20:52:15 +0800 Subject: [PATCH 08/13] fix --- scripts/deployL2-it.js | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index 15b2886..32f9301 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -20,6 +20,7 @@ const config = [ ]; const storageCost = 1500000000000000; // storageCost - 1,500,000Gwei forever per blob - https://ethresear.ch/t/ethstorage-scaling-ethereum-storage-via-l2-and-da/14223/6#incentivization-for-storing-m-physical-replicas-1 const dcfFactor = 340282366367469178095360967382638002176n; // dcfFactor, it mean 0.95 for yearly discount +const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay)) async function verifyContract(contract, args) { // if (!process.env.ETHERSCAN_API_KEY) { @@ -86,28 +87,20 @@ async function deployContract() { await verifyContract(impl, [config, startTime, storageCost, dcfFactor]); // wait for contract finalized - await waitForFinalized (receipt.blockNumber) -} - -async function waitForFinalized(number) { - if (number == 0) { - return; - } - - while (true) { - const block = await hre.ethers.provider.getBlock("finalized"); - console.log( - "finalized block number is", - block.number, - "at", - new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) - ); - - if (number < block.number) { - return; - } - setTimeout(60 * 1000); + while (true) { + const block = await hre.ethers.provider.getBlock("finalized"); + console.log( + "finalized block number is", + block.number, + "at", + new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) + ); + + if (receipt.blockNumber < block.number) { + return; } + sleep(60*000); + } } async function updateContract() { From 5d3d193840daf4d83564d72b18141f24f8602021 Mon Sep 17 00:00:00 2001 From: pingke Date: Wed, 31 Jul 2024 00:10:45 +0800 Subject: [PATCH 09/13] update --- scripts/deployL2-it.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index 32f9301..156541b 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -20,7 +20,6 @@ const config = [ ]; const storageCost = 1500000000000000; // storageCost - 1,500,000Gwei forever per blob - https://ethresear.ch/t/ethstorage-scaling-ethereum-storage-via-l2-and-da/14223/6#incentivization-for-storing-m-physical-replicas-1 const dcfFactor = 340282366367469178095360967382638002176n; // dcfFactor, it mean 0.95 for yearly discount -const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay)) async function verifyContract(contract, args) { // if (!process.env.ETHERSCAN_API_KEY) { @@ -87,19 +86,20 @@ async function deployContract() { await verifyContract(impl, [config, startTime, storageCost, dcfFactor]); // wait for contract finalized + const i = 1 while (true) { const block = await hre.ethers.provider.getBlock("finalized"); - console.log( - "finalized block number is", - block.number, - "at", - new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) - ); + setTimeout( () => + console.log( + "finalized block number is", + block.number, + "at", + new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) + ), 60000 * i++); if (receipt.blockNumber < block.number) { return; } - sleep(60*000); } } From 3a83dc2ef205cae6580eb3ac8fbff04a395b860e Mon Sep 17 00:00:00 2001 From: pingke Date: Wed, 31 Jul 2024 12:45:32 +0800 Subject: [PATCH 10/13] update timeout --- scripts/deployL2-it.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index 156541b..53452d6 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -66,7 +66,6 @@ async function deployContract() { console.log("storage admin address is ", admin); console.log("storage contract address is ", ethStorageProxy.address); - fs.writeFileSync(".caddr", ethStorageProxy.address); const receipt = await hre.ethers.provider.getTransactionReceipt(ethStorageProxy.deployTransaction.hash); console.log( "deployed in block number", @@ -86,21 +85,19 @@ async function deployContract() { await verifyContract(impl, [config, startTime, storageCost, dcfFactor]); // wait for contract finalized - const i = 1 - while (true) { + intervalId = setInterval(function (){ const block = await hre.ethers.provider.getBlock("finalized"); - setTimeout( () => - console.log( - "finalized block number is", - block.number, - "at", - new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) - ), 60000 * i++); - + console.log( + "finalized block number is", + block.number, + "at", + new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) + ); if (receipt.blockNumber < block.number) { - return; + fs.writeFileSync(".caddr", ethStorageProxy.address); + clearInterval(intervalId) } - } + }, 60000); } async function updateContract() { From 2b96b8c56c086804d851a344033e967f764c530f Mon Sep 17 00:00:00 2001 From: pingke Date: Wed, 31 Jul 2024 14:30:56 +0800 Subject: [PATCH 11/13] resolve comments --- scripts/deployL2-it.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index 53452d6..fc71923 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -53,7 +53,7 @@ async function deployContract() { const data = implContract.interface.encodeFunctionData("initialize", [ 1572864, // minimumDiff 0.1 * 180 (3 minutes) * 1024 * 1024 / 12 = 1572864 for 0.1 replicas that can have 1M IOs in one epoch - 3145728000000000000000n, // prepaidAmount - 50% * 2^39 / 131072 * 1500000Gwei, it also means 3145 ETH for half of the shard + 24576000000000000000n, // prepaidAmount - 50% * 2^32 / 131072 * 1500000Gwei, it also means 3145 ETH for half of the shard 1048576, // nonceLimit 1024 * 1024 = 1M samples and finish sampling in 1.3s with IO rate 6144 MB/s: 4k * 2(random checks) / 6144 = 1.3s treasuryAddress, // treasury ownerAddress, From 05a6677a9751da85df81e9a38d3acd3649e2ca9d Mon Sep 17 00:00:00 2001 From: pingke Date: Thu, 1 Aug 2024 15:29:57 +0800 Subject: [PATCH 12/13] fix build --- scripts/deployL2-it.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index fc71923..4f9dedd 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -85,7 +85,7 @@ async function deployContract() { await verifyContract(impl, [config, startTime, storageCost, dcfFactor]); // wait for contract finalized - intervalId = setInterval(function (){ + var intervalId = setInterval(async function (){ const block = await hre.ethers.provider.getBlock("finalized"); console.log( "finalized block number is", From 7fddf63730a8e4ee4aeeacef6bbd85920ab6bf9f Mon Sep 17 00:00:00 2001 From: pingke Date: Thu, 1 Aug 2024 15:50:25 +0800 Subject: [PATCH 13/13] resolve comments --- scripts/deployL2-it.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/scripts/deployL2-it.js b/scripts/deployL2-it.js index 4f9dedd..848b9c6 100644 --- a/scripts/deployL2-it.js +++ b/scripts/deployL2-it.js @@ -86,16 +86,20 @@ async function deployContract() { // wait for contract finalized var intervalId = setInterval(async function (){ - const block = await hre.ethers.provider.getBlock("finalized"); - console.log( - "finalized block number is", - block.number, - "at", - new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) - ); - if (receipt.blockNumber < block.number) { - fs.writeFileSync(".caddr", ethStorageProxy.address); - clearInterval(intervalId) + try { + const block = await hre.ethers.provider.getBlock("finalized"); + console.log( + "finalized block number is", + block.number, + "at", + new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) + ); + if (receipt.blockNumber < block.number) { + fs.writeFileSync(".caddr", ethStorageProxy.address); + clearInterval(intervalId); + } + } catch (e) { + console.error(`EthStorage: get finalized block failed!`, e.message);g } }, 60000); }