-
Install & build:
npm i && npm run build && npm test
-
Deploy locally (Hardhat default):
npm run deploy # Addresses will print: # Token: 0x5FbDB2... # StakeManager: 0xe7f1725...
-
Stake (approve → stake):
// inside a Hardhat script or console const token = await ethers.getContractAt("StubToken", "0x5FbDB2315678afecb367f032d93F642f64180aa3"); const stake = await ethers.getContractAt("StakeManager", "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512"); const [owner, user] = await ethers.getSigners(); // fund user (local only) await token.transfer(user.address, ethers.parseEther("100")); // approve + stake 50 STB await token.connect(user).approve(await stake.getAddress(), ethers.parseEther("50")); await stake.connect(user).stake(ethers.parseEther("50")); // check await stake.stakeOf(user.address); // 50e18
-
Trigger a burn (authority only):
// deployer is the initial burnAuthority await stake.burnFromStake(user.address, ethers.parseEther("10"), "policy/demo"); // effects: user stake −10, StakeManager token balance −10, totalSupply −10
-
Sample GraphQL query (is this address flagged?):
{ flag(id: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8") { flagged sources lastSource lastTaggedAt } } -
Subgraph deploy (Hosted Service):
Tip: You can also use the Hardhat console for quick experiments:
npx hardhat console
cd graph npm i # Edit subgraph.yaml → set network, source.address, startBlock npm run codegen && npm run build # Auth once graph auth --product hosted-service <ACCESS_TOKEN> # Deploy $env:SUBGRAPH_NAME="your-acc/stake-burn"; npm run deploy
This is a minimal but complete blockchain project that demonstrates token staking with special authority controls. Think of it as a "proof of concept" for systems where users can lock up tokens, but a designated authority can burn some of those locked tokens under certain conditions.
- StubToken: A basic ERC-20 token that can be burned (perfect for testing)
- StakeManager: Users lock their tokens here, and a special "burn authority" can burn portions of staked tokens
- The Graph Subgraph: Tracks when addresses get "tagged" and answers the question "is this address flagged?"
The burning mechanism actually reduces the total token supply, making it a real economic penalty rather than just moving tokens around.
# Install everything
npm install
# Build the contracts
npm run build
# Run the tests (should all pass)
npm test
# Deploy locally and see the magic
npm run deployUsers first need to approve the StakeManager to spend their tokens, then they can stake:
// Approve first (this is standard ERC-20 stuff)
await token.approve(stakeManagerAddress, amount);
// Then stake
await stakeManager.stake(amount);The StakeManager tracks how much each user has staked and holds all the tokens.
By default, the deployer becomes the "burn authority" - the only address that can:
- Tag addresses (emits
AddressTaggedevent) - Burn tokens from someone's stake
// Tag an address (just flags it, no burning)
await stakeManager.tagAddress(userAddress, "fraud-detection-batch-7");
// Burn from someone's stake (reduces their stake AND total supply)
await stakeManager.burnFromStake(userAddress, burnAmount, "policy-violation-2024");The subgraph watches for AddressTagged events and builds a simple database that answers: "has this address been flagged?"
When you run npm run deploy, you'll see these addresses:
- StubToken (STB):
0x5FbDB2315678afecb367f032d93F642f64180aa3 - StakeManager:
0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 - Deployer/Authority:
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
I've included a demo script that shows the whole flow in action:
npm run demoThis will:
- Deploy fresh contracts
- Transfer tokens to a test user
- Have the user stake some tokens
- Have the authority tag the user
- Have the authority burn some of the user's staked tokens
- Show you the before/after numbers
You'll see the total supply actually decrease when tokens are burned - that's the real economic impact.
For a real testnet deployment (like Sepolia):
-
Copy
.env.exampleto.env -
Fill in your values:
SEPOLIA_RPC_URL: Get this from Infura, Alchemy, or similarPRIVATE_KEY: Your test wallet's private key (never use mainnet keys!)ETHERSCAN_API_KEY: Optional, for contract verification
-
Deploy:
npx hardhat run scripts/deploy.js --network sepoliaSave the addresses that get printed - you'll need them for the subgraph.
The subgraph tracks AddressTagged events and lets you query if an address has been flagged.
The subgraph is already configured for local development:
cd graph
npm install
npm run codegen
npm run buildFor testnet, you'll need to:
-
Update
graph/subgraph.yaml:- Change
networkfromlocalhosttosepolia - Update
source.addresswith your deployed StakeManager address - Set
startBlockto the block number right after your deployment
- Change
-
Deploy to The Graph's hosted service:
# Authenticate (one-time setup)
graph auth --product hosted-service YOUR_ACCESS_TOKEN
# Set your subgraph name
$env:SUBGRAPH_NAME="your-username/stake-burn" # Windows
# or
export SUBGRAPH_NAME="your-username/stake-burn" # Linux/Mac
# Deploy
npm run deployOnce deployed, you can ask the subgraph if an address has been flagged:
{
flag(id: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8") {
flagged
sources
lastSource
lastTaggedAt
}
}If flagged is true, that address has been tagged at least once. The sources array shows all the reasons it was tagged.
├── contracts/
│ ├── StubToken.sol # Basic ERC-20 with burning
│ └── StakeManager.sol # The main staking contract
├── test/
│ └── StakeManager.t.js # Tests covering all functionality
├── scripts/
│ ├── deploy.js # Deployment script
│ └── demo.js # Demo showing the full workflow
├── graph/ # The Graph subgraph
│ ├── schema.graphql # Data model
│ ├── subgraph.yaml # Configuration
│ ├── src/mapping.ts # Event handling logic
│ └── abis/ # Contract ABIs
└── README.md # This file
The test suite covers:
- Basic staking and unstaking
- Authority-only burning (non-authority calls should fail)
- Supply reduction when tokens are burned
AddressTaggedevents being emitted correctly
Run npm test to see all tests pass.
- Approvals: Users must approve the StakeManager before staking (standard ERC-20)
- Authority: Only the designated
burnAuthoritycan tag/burn - Supply Math: Burns reduce both the user's stake AND the total token supply
- Subgraph IDs: Always use lowercase addresses when querying the subgraph
- Network Mismatch: Make sure your subgraph network matches where you deployed
This pattern is useful for:
- Governance systems where bad actors can have their stake slashed
- Insurance protocols where premiums can be burned for violations
- Reputation systems where flagged addresses are tracked
- Educational purposes to understand authority patterns in DeFi
The key insight is that burning from staked balances creates real economic consequences, not just token movements.