Upgrade to v5 schema

Now uses:
* ipld direct_by_leaf StateDB for basic queries
* trie_by_cid StateDB for trie slice and proof queries

Also:
* vulcanize => cerc refactor
* Backend method to close dbs
* state tests are in multiple packages, to allow separate ginkgo suites
* removes gap-filler module
* integration tests and github workflows
* run stack-orchestrator for testnet
* fix various issues with tests, hardhat server, dockerfile
* fix cmd flags / env vars
* fix flaky tests and clean up code
* remove unused code, scripts
* remove outdated docs
* update version
This commit is contained in:
2023-05-25 21:39:48 +08:00
parent ec6707c6ab
commit 6d7487152c
84 changed files with 5118 additions and 17644 deletions
+3 -2
View File
@@ -1,4 +1,5 @@
FROM node:14
# Downgrade from 18.16, see https://github.com/NomicFoundation/hardhat/issues/3877
FROM node:18.15-slim
ARG ETH_ADDR
ENV ETH_ADDR $ETH_ADDR
@@ -11,4 +12,4 @@ RUN npm run compile && ls -lah
EXPOSE 3000
ENTRYPOINT ["npm", "start"]
ENTRYPOINT ["node", "src/index.js"]
+1
View File
@@ -1,5 +1,6 @@
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor() ERC20("Gold", "GLD") {
_mint(msg.sender, 1000000000000000000000);
+13 -10
View File
@@ -16,6 +16,16 @@ task("accounts", "Prints the list of accounts", async () => {
/**
* @type import('hardhat/config').HardhatUserConfig
*/
const localNetwork = {
url: process.env.ETH_ADDR || "http://127.0.0.1:8545",
chainId: Number(process.env.ETH_CHAIN_ID) || 99,
};
if (process.env.DEPLOYER_PRIVATE_KEY) {
localNetwork["accounts"] = [process.env.DEPLOYER_PRIVATE_KEY];
}
module.exports = {
solidity: {
version: "0.8.0",
@@ -30,14 +40,7 @@ module.exports = {
}
},
networks: {
local: {
url: 'http://127.0.0.1:8545',
chainId: 99
},
docker: {
url: process.env.ETH_ADDR,
chainId: 99
}
}
local: localNetwork
},
defaultNetwork: "local"
};
+2939 -14573
View File
File diff suppressed because it is too large Load Diff
+6 -8
View File
@@ -4,23 +4,21 @@
"main": "index.js",
"scripts": {
"compile": "npx hardhat compile",
"start": "HARDHAT_NETWORK=docker node src/index.js",
"start:local": "ETH_ADDR=http://127.0.0.1:8545 npm run start",
"test": "echo \"Error: no test specified\" && exit 1"
"start": "node src/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"description": "Solidity contract deployment server for integration testing",
"dependencies": {
"@openzeppelin/contracts": "^4.0.0",
"fastify": "^3.14.2",
"hardhat": "^2.2.0",
"fastify": "^4.0.0",
"hardhat": "^2.14.0",
"solidity-create2-deployer": "^0.4.0"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@nomiclabs/hardhat-waffle": "^2.0.4",
"chai": "^4.3.4",
"ethereum-waffle": "^3.3.0",
"ethers": "^5.1.0"
-18
View File
@@ -1,18 +0,0 @@
const hre = require("hardhat");
async function main() {
// await hre.run('compile');
// We get the contract to deploy
const GLDToken = await hre.ethers.getContractFactory("GLDToken");
const token = await GLDToken.deploy();
await token.deployed();
console.log("GLDToken deployed to:", token.address, token.deployTransaction.hash);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
-36
View File
@@ -1,36 +0,0 @@
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
const hre = require("hardhat");
async function main() {
// Hardhat always runs the compile task when running scripts with its command
// line interface.
//
// If this script is run directly using `node` you may want to call compile
// manually to make sure everything is compiled
// await hre.run('compile');
// We get the contract to deploy
const Greeter = await hre.ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, Hardhat!");
await greeter.deployed();
console.log("Greeter deployed to:", greeter.address, "; tx hash: ", greeter.deployTransaction.hash);
const result = await greeter.setGreeting("Hello 123!");
console.log("Greeter updated", "; tx hash: ", result.hash, "; block hash: ", result.blockHash);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
+100 -128
View File
@@ -2,8 +2,8 @@ const fastify = require('fastify')({ logger: true });
const hre = require("hardhat");
const {
deployContract,
isDeployed
deployContract,
isDeployed
} = require("solidity-create2-deployer");
const { getStorageSlotKey, deployCreate2Factory } = require('./utils');
@@ -12,175 +12,147 @@ const CREATE2_FACTORY_ADDRESS = '0x4a27c059FD7E383854Ea7DE6Be9c390a795f6eE3'
// readiness check
fastify.get('/v1/healthz', async (req, reply) => {
reply
.code(200)
.header('Content-Type', 'application/json; charset=utf-8')
.send({ success: true })
reply
.code(200)
.header('Content-Type', 'application/json; charset=utf-8')
.send({ success: true })
});
fastify.get('/v1/deployContract', async (req, reply) => {
const GLDToken = await hre.ethers.getContractFactory("GLDToken");
const token = await GLDToken.deploy();
await token.deployed();
return {
address: token.address,
txHash: token.deployTransaction.hash,
blockNumber: token.deployTransaction.blockNumber,
blockHash: token.deployTransaction.blockHash,
}
});
fastify.get('/v1/destroyContract', async (req, reply) => {
const addr = req.query.addr;
const Token = await hre.ethers.getContractFactory("GLDToken");
const token = await Token.attach(addr);
await token.destroy();
const blockNum = await hre.ethers.provider.getBlockNumber()
return {
blockNumber: blockNum,
}
})
fastify.get('/v1/sendEth', async (req, reply) => {
const to = req.query.to;
const value = req.query.value;
const to = req.query.to;
const value = hre.ethers.utils.parseEther(req.query.value);
const [owner] = await hre.ethers.getSigners();
const tx = await owner.sendTransaction({
to,
value: hre.ethers.utils.parseEther(value)
});
await tx.wait(1)
const owner = await hre.ethers.getSigner();
const tx = await owner.sendTransaction({to, value}).then(tx => tx.wait());
// console.log(tx);
// const coinbaseBalance = await hre.ethers.provider.getBalance(owner.address);
// const receiverBalance = await hre.ethers.provider.getBalance(to);
// console.log(coinbaseBalance.toString(), receiverBalance.toString());
return {
from: tx.from,
to: tx.to,
//value: tx.value.toString(),
txHash: tx.hash,
blockNumber: tx.blockNumber,
blockHash: tx.blockHash,
}
return {
from: tx.from,
to: tx.to,
txHash: tx.hash,
blockNumber: tx.blockNumber,
blockHash: tx.blockHash,
}
});
fastify.get('/v1/deploySLVContract', async (req, reply) => {
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.deploy();
const receipt = await token.deployTransaction.wait();
function contractCreator(name) {
return async (req, reply) => {
const contract = await hre.ethers.getContractFactory(name);
const instance = await contract.deploy();
const rct = await instance.deployTransaction.wait();
return {
address: token.address,
txHash: token.deployTransaction.hash,
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
address: instance.address,
txHash: rct.transactionHash,
blockNumber: rct.blockNumber,
blockHash: rct.blockHash,
}
});
}
}
fastify.get('/v1/destroySLVContract', async (req, reply) => {
function contractDestroyer(name) {
return async (req, reply) => {
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = SLVToken.attach(addr);
const tx = await token.destroy();
const receipt = await tx.wait();
const contract = await hre.ethers.getContractFactory(name);
const instance = contract.attach(addr);
const rct = await instance.destroy().then(tx => tx.wait());
return {
blockNumber: receipt.blockNumber,
blockNumber: rct.blockNumber,
}
})
}
}
fastify.get('/v1/deployContract', contractCreator("GLDToken"));
fastify.get('/v1/destroyContract', contractDestroyer("GLDToken"));
fastify.get('/v1/deploySLVContract', contractCreator("SLVToken"));
fastify.get('/v1/destroySLVContract', contractDestroyer("SLVToken"));
fastify.get('/v1/incrementCountA', async (req, reply) => {
const addr = req.query.addr;
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const tx = await token.incrementCountA();
const receipt = await tx.wait();
const tx = await token.incrementCountA();
const receipt = await tx.wait();
return {
blockNumber: receipt.blockNumber,
}
return {
blockNumber: receipt.blockNumber,
}
});
fastify.get('/v1/incrementCountB', async (req, reply) => {
const addr = req.query.addr;
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const tx = await token.incrementCountB();
const receipt = await tx.wait();
const tx = await token.incrementCountB();
const receipt = await tx.wait();
return {
blockNumber: receipt.blockNumber,
}
return {
blockNumber: receipt.blockNumber,
}
});
fastify.get('/v1/getStorageKey', async (req, reply) => {
const contract = req.query.contract;
const label = req.query.label;
const contract = req.query.contract;
const label = req.query.label;
const key = await getStorageSlotKey(contract, label)
const key = await getStorageSlotKey(contract, label)
return {
key
}
return {
key
}
});
fastify.get('/v1/create2Contract', async (req, reply) => {
const contract = req.query.contract;
const salt = req.query.salt;
const contract = req.query.contract;
const salt = req.query.salt;
const provider = hre.ethers.provider;
const signer = await hre.ethers.getSigner();
const isFactoryDeployed = await isDeployed(CREATE2_FACTORY_ADDRESS, provider);
const provider = hre.ethers.provider;
const signer = await hre.ethers.getSigner();
const isFactoryDeployed = await isDeployed(CREATE2_FACTORY_ADDRESS, provider);
if (!isFactoryDeployed) {
await deployCreate2Factory(provider, signer)
}
if (!isFactoryDeployed) {
await deployCreate2Factory(provider, signer);
}
const contractFactory = await hre.ethers.getContractFactory(contract);
const bytecode = contractFactory.bytecode;
const constructorTypes = [];
const constructorArgs = [];
const contractFactory = await hre.ethers.getContractFactory(contract);
const bytecode = contractFactory.bytecode;
const constructorTypes = [];
const constructorArgs = [];
const { txHash, address, receipt } = await deployContract({
salt,
contractBytecode: bytecode,
constructorTypes: constructorTypes,
constructorArgs: constructorArgs,
signer
});
const createArgs = {
salt,
contractBytecode: bytecode,
constructorTypes: constructorTypes,
constructorArgs: constructorArgs,
signer
};
const { txHash, address, receipt } = await deployContract(createArgs);
const success = await isDeployed(address, provider);
const success = await isDeployed(address, provider);
if (success) {
return {
address,
txHash,
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
}
if (success) {
return {
address,
txHash,
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
}
}
});
async function main() {
try {
await fastify.listen(3000, '0.0.0.0');
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
try {
await fastify.listen({ port: 3000, host: '0.0.0.0' });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
}
process.on('SIGINT', () => fastify.close().then(() => process.exit(1)));
main();
+8 -7
View File
@@ -1,7 +1,8 @@
const { artifacts } = require("hardhat")
const { utils, BigNumber } = require("ethers")
const { deployFactory } = require("solidity-create2-deployer");
const { deployFactory, isDeployed } = require("solidity-create2-deployer");
// Hardcoded account which solidity-create2-deployer uses to deploy its factory
const CREATE2_FACTORY_ACCOUNT = '0x2287Fa6efdEc6d8c3E0f4612ce551dEcf89A357A';
async function getStorageLayout(contractName) {
@@ -38,17 +39,17 @@ async function getStorageSlotKey(contractName, variableName) {
};
async function deployCreate2Factory(provider, signer) {
// Send eth to account as required to deploy create2 factory contract.
// Fund hardcoded account before deploying factory
let tx = {
to: CREATE2_FACTORY_ACCOUNT,
value: utils.parseEther('0.01')
}
await signer.sendTransaction(tx).then(tx => tx.wait());
const txResponse = await signer.sendTransaction(tx);
await txResponse.wait()
// Deploy create2 factory contract.
await deployFactory(provider)
const address = await deployFactory(provider);
// solidity-create2-deployer doesn't await the deploy tx
while (!await isDeployed(address, provider));
return address;
}
module.exports = { getStorageSlotKey, deployCreate2Factory }
-14
View File
@@ -1,14 +0,0 @@
const { expect } = require("chai");
describe("Greeter", function() {
it("Should return the new greeting once it's changed", async function() {
const Greeter = await ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, world!");
await greeter.deployed();
expect(await greeter.greet()).to.equal("Hello, world!");
await greeter.setGreeting("Hola, mundo!");
expect(await greeter.greet()).to.equal("Hola, mundo!");
});
});