Add integration tests for API to change addresses watched by geth
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||
|
||||
contract SLVToken is ERC20 {
|
||||
uint256 private countA;
|
||||
uint256 private countB;
|
||||
|
||||
constructor() ERC20("Silver", "SLV") {}
|
||||
|
||||
function incrementCountA() public {
|
||||
countA = countA + 1;
|
||||
}
|
||||
|
||||
function incrementCountB() public {
|
||||
countB = countB + 1;
|
||||
}
|
||||
|
||||
receive() external payable {}
|
||||
|
||||
function destroy() public {
|
||||
selfdestruct(payable(msg.sender));
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,18 @@ task("accounts", "Prints the list of accounts", async () => {
|
||||
* @type import('hardhat/config').HardhatUserConfig
|
||||
*/
|
||||
module.exports = {
|
||||
solidity: "0.8.0",
|
||||
solidity: {
|
||||
version: "0.8.0",
|
||||
settings: {
|
||||
outputSelection: {
|
||||
'*': {
|
||||
'*': [
|
||||
'abi', 'storageLayout',
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
local: {
|
||||
url: 'http://127.0.0.1:8545',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const fastify = require('fastify')({ logger: true });
|
||||
const hre = require("hardhat");
|
||||
|
||||
const { getStorageSlotKey } = require('./utils');
|
||||
|
||||
// readiness check
|
||||
fastify.get('/v1/healthz', async (req, reply) => {
|
||||
@@ -63,6 +64,72 @@ fastify.get('/v1/sendEth', async (req, reply) => {
|
||||
}
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
return {
|
||||
address: token.address,
|
||||
txHash: token.deployTransaction.hash,
|
||||
blockNumber: receipt.blockNumber,
|
||||
blockHash: receipt.blockHash,
|
||||
}
|
||||
});
|
||||
|
||||
fastify.get('/v1/destroySLVContract', 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();
|
||||
|
||||
return {
|
||||
blockNumber: receipt.blockNumber,
|
||||
}
|
||||
})
|
||||
|
||||
fastify.get('/v1/incrementCountA', async (req, reply) => {
|
||||
const addr = req.query.addr;
|
||||
|
||||
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
|
||||
const token = await SLVToken.attach(addr);
|
||||
|
||||
const tx = await token.incrementCountA();
|
||||
const receipt = await tx.wait();
|
||||
|
||||
return {
|
||||
blockNumber: receipt.blockNumber,
|
||||
}
|
||||
});
|
||||
|
||||
fastify.get('/v1/incrementCountB', async (req, reply) => {
|
||||
const addr = req.query.addr;
|
||||
|
||||
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
|
||||
const token = await SLVToken.attach(addr);
|
||||
|
||||
const tx = await token.incrementCountB();
|
||||
const receipt = await tx.wait();
|
||||
|
||||
return {
|
||||
blockNumber: receipt.blockNumber,
|
||||
}
|
||||
});
|
||||
|
||||
fastify.get('/v1/getStorageKey', async (req, reply) => {
|
||||
const contract = req.query.contract;
|
||||
const label = req.query.label;
|
||||
|
||||
const key = await getStorageSlotKey(contract, label)
|
||||
|
||||
return {
|
||||
key
|
||||
}
|
||||
});
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
await fastify.listen(3000, '0.0.0.0');
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
const { artifacts } = require("hardhat")
|
||||
const { utils, BigNumber } = require("ethers")
|
||||
|
||||
|
||||
async function getStorageLayout(contractName) {
|
||||
const artifact = await artifacts.readArtifact(contractName);
|
||||
const buildInfo = await artifacts.getBuildInfo(`${artifact.sourceName}:${artifact.contractName}`);
|
||||
|
||||
if (!buildInfo) {
|
||||
throw new Error('storageLayout not present in compiler output.');
|
||||
}
|
||||
|
||||
const output = buildInfo.output;
|
||||
const { storageLayout } = output.contracts[artifact.sourceName][artifact.contractName];
|
||||
|
||||
if (!storageLayout) {
|
||||
throw new Error('Contract hasn\'t been compiled.');
|
||||
}
|
||||
|
||||
return storageLayout;
|
||||
};
|
||||
|
||||
async function getStorageSlotKey(contractName, variableName) {
|
||||
storageLayout = await getStorageLayout(contractName)
|
||||
|
||||
const { storage } = storageLayout;
|
||||
const targetState = storage.find((state) => state.label === variableName);
|
||||
|
||||
// Throw if state variable could not be found in storage layout.
|
||||
if (!targetState) {
|
||||
throw new Error('Variable not present in storage layout.');
|
||||
}
|
||||
|
||||
key = utils.hexlify(BigNumber.from(targetState.slot));
|
||||
return key
|
||||
};
|
||||
Reference in New Issue
Block a user