Skip to content

Commit

Permalink
feat(hardhat): add deployment persistence to hardhat node
Browse files Browse the repository at this point in the history
- Add volume mappings for deployments, artifacts and cache
- Implement manual deployment file saving
- Update hardhat configuration for proper deployment paths

This change ensures that deployed contracts persist between container
restarts by saving deployment data to mounted volumes.

Note: Block persistence still requires a different solution (Ganache/Geth/Besu)
as Hardhat Network doesn't support state persistence.

Related issue: #669
  • Loading branch information
mpaya5 committed Dec 4, 2024
1 parent 655ece3 commit a5f713b
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 20 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,11 @@ nginx/ssl/*.key
nginx/ssl/*.crt

# Hardhat files
hardhat/cache
hardhat/artifacts
hardhat/cache/*
hardhat/artifacts/*
hardhat/.openzeppelin
hardhat/coverage
hardhat/coverage.json
hardhat/typechain
hardhat/typechain-types
hardhat/deployments/*
18 changes: 13 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,19 @@ services:
ports:
- "${HARDHAT_PORT:-8545}:8545"
volumes:
- ./hardhat/contracts:/app/contracts
- ./hardhat/scripts:/app/scripts
- ./hardhat/test:/app/test
- ./hardhat/hardhat.config.js:/app/hardhat.config.js
- ./hardhat/artifacts:/app/artifacts
- ./hardhat/contracts:/app/contracts:ro
- ./hardhat/scripts:/app/scripts:ro
- ./hardhat/test:/app/test:ro
- ./hardhat/hardhat.config.js:/app/hardhat.config.js:ro
- ./hardhat/deploy:/app/deploy:ro
- hardhat_artifacts:/app/artifacts
- hardhat_cache:/app/cache
- hardhat_deployments:/app/deployments
environment:
- HARDHAT_NETWORK=hardhat
restart: always

volumes:
hardhat_artifacts:
hardhat_cache:
hardhat_deployments:
22 changes: 13 additions & 9 deletions docker/Dockerfile.hardhat
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,22 @@ RUN npm install --ignore-scripts

COPY ./hardhat .

# Change ownership of the app directory to the non-root user
RUN chown -R hardhat-user:hardhat-group /app
# Create directories and set permissions BEFORE switching user
RUN mkdir -p /app/deployments/localhost && \
mkdir -p /app/deployments/hardhat && \
mkdir -p /app/artifacts/build-info && \
mkdir -p /app/cache && \
chown -R hardhat-user:hardhat-group /app && \
chmod -R 777 /app/deployments && \
chmod -R 777 /app/artifacts && \
chmod -R 777 /app/cache

ENV PATH="/app/node_modules/.bin:${PATH}"

RUN echo -e '#!/bin/sh\necho "Compiling contracts..."\nnpx hardhat compile --force\necho "Starting Hardhat node..."\nexec ./node_modules/.bin/hardhat node --network hardhat' > /app/start.sh && \
chmod +x /app/start.sh && \
ls -la /app/start.sh
# Copy the start script from hardhat/scripts instead of creating it
COPY ./hardhat/scripts/start.sh /app/start.sh
RUN chmod +x /app/start.sh

EXPOSE 8545

# Switch to non-root user
USER hardhat-user

CMD ["/app/start.sh"]
CMD ["/app/start.sh"]
37 changes: 37 additions & 0 deletions hardhat/deploy/001_deploy_contracts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module.exports = async function ({ getNamedAccounts, deployments, network }) {
const { deploy, save, getArtifact } = deployments;
const { deployer } = await getNamedAccounts();

console.log("Starting deployment of GhostContract...");

const result = await deploy('GhostContract', {
from: deployer,
args: [],
log: true,
deterministicDeployment: false,
gasPrice: 0,
gasLimit: 5000000,
waitConfirmations: 1
});

const artifact = await getArtifact('GhostContract');
const deploymentData = {
address: result.address,
abi: artifact.abi,
bytecode: artifact.bytecode,
transactionHash: result.transactionHash
};

const fs = require('fs');
const path = require('path');
const deploymentDir = path.join('./deployments', network.name);
const deploymentFile = path.join(deploymentDir, 'GhostContract.json');

fs.mkdirSync(deploymentDir, { recursive: true });

fs.writeFileSync(deploymentFile, JSON.stringify(deploymentData, null, 2));

console.log(`Deployment successful! Contract deployed at: ${result.address}`);
};

module.exports.tags = ['GhostContract'];
18 changes: 14 additions & 4 deletions hardhat/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require("@nomicfoundation/hardhat-toolbox");
require("hardhat-deploy");

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
Expand All @@ -21,15 +22,24 @@ module.exports = {
chainId: 31337,
gasPrice: 0,
initialBaseFeePerGas: 0,
accounts: {
count: 1
}
blockGasLimit: 30000000,
live: false,
saveDeployments: true,
allowUnlimitedContractSize: true,
tags: ['local']
}
},
paths: {
sources: "./contracts",
tests: "./test",
cache: "./cache",
artifacts: "./artifacts"
artifacts: "./artifacts",
deploy: "./deploy",
deployments: "./deployments"
},
namedAccounts: {
deployer: {
default: 0
}
}
};
3 changes: 3 additions & 0 deletions hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,8 @@
},
"engines": {
"node": ">=18.0.0"
},
"devDependencies": {
"hardhat-deploy": "^0.14.0"
}
}
21 changes: 21 additions & 0 deletions hardhat/scripts/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh

echo "Checking and compiling contracts if needed..."
npx hardhat compile

echo "Starting Hardhat node..."
npx hardhat node --hostname 0.0.0.0 --no-deploy &

# Wait for the node to start
sleep 5

# Check if the contract is already deployed (using hardhat network)
if [ ! -f "/app/deployments/hardhat/GhostContract.json" ]; then
echo "Running deployments..."
npx hardhat deploy
else
echo "Contracts already deployed, skipping deployment..."
fi

# Keep the container running
wait

0 comments on commit a5f713b

Please sign in to comment.