Review follow-up: improve LabHelper.sol #1110
24
.editorconfig
Normal file
24
.editorconfig
Normal file
@ -0,0 +1,24 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.sol]
|
||||
indent_size = 4
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.{json,toml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
*.sol linguist-language=Solidity
|
||||
*.t.sol linguist-language=Solidity
|
||||
*.s.sol linguist-language=Solidity
|
||||
|
||||
# Auto detect text files and normalise line endings
|
||||
* text=auto eol=lf
|
||||
|
||||
# Binary files
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.gif binary
|
||||
24
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
24
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
## Description
|
||||
|
||||
<!-- What does this PR do? Why is it needed? -->
|
||||
|
||||
## Changes
|
||||
|
||||
<!-- List the key changes -->
|
||||
-
|
||||
|
||||
## Test Plan
|
||||
|
||||
<!-- How was this tested? -->
|
||||
- [ ] `forge test` passes
|
||||
- [ ] `forge fmt --check` passes
|
||||
- [ ] Gas report reviewed
|
||||
- [ ] Edge cases covered
|
||||
|
||||
## Risks
|
||||
|
||||
<!-- Any risks or migration steps? -->
|
||||
|
||||
## Related Issues
|
||||
|
||||
<!-- Closes #123 -->
|
||||
49
.github/workflows/ci.yml
vendored
Normal file
49
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
FOUNDRY_PROFILE: ci
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Foundry
|
||||
uses: foundry-rs/foundry-toolchain@v1
|
||||
with:
|
||||
version: nightly
|
||||
|
||||
- name: Install dependencies
|
||||
run: forge install
|
||||
|
||||
- name: Check formatting
|
||||
run: forge fmt --check
|
||||
|
||||
- name: Build contracts
|
||||
run: forge build --sizes
|
||||
|
||||
- name: Run tests
|
||||
run: forge test -vvv
|
||||
|
||||
- name: Run snapshot (gas)
|
||||
run: forge snapshot
|
||||
|
||||
- name: Check coverage
|
||||
run: forge coverage
|
||||
|
||||
slither:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run Slither
|
||||
uses: crytic/slither-action@v0.4.0
|
||||
continue-on-error: true
|
||||
34
.gitignore
vendored
Normal file
34
.gitignore
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# Foundry artifacts
|
||||
out/
|
||||
cache/
|
||||
cache_forge/
|
||||
|
||||
# Node
|
||||
node_modules/
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
lcov.info
|
||||
|
||||
# Gas snapshots
|
||||
.gas-snapshot
|
||||
|
||||
# Broadcast logs
|
||||
broadcast/
|
||||
|
||||
# Docs output
|
||||
docs/
|
||||
!docs/*.md
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
23
BOT_RUNTIME.md
Normal file
23
BOT_RUNTIME.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Bot Runtime Guide
|
||||
|
||||
This repository includes a default Docker Compose stack so any citizen can run and validate output quickly.
|
||||
|
||||
## Quick Start
|
||||
1. `docker compose up --build --abort-on-container-exit`
|
||||
2. `docker compose logs --no-color --tail=200 app`
|
||||
3. `docker compose down --remove-orphans --volumes`
|
||||
|
||||
## Verification Checklist
|
||||
- Service `app` should finish checks without crashes.
|
||||
- Logs should show expected behavior for the latest commit.
|
||||
- For custom checks, run `docker compose run --rm app sh -lc "<command>"`.
|
||||
|
||||
## Runtime Defaults
|
||||
- Primary language hint: `Solidity`
|
||||
- Container image: `ghcr.io/foundry-rs/foundry:latest`
|
||||
- Default command: `sh -lc "forge install || true; forge build && forge test -vvv && echo FOUNDRY_TESTS_PASSED || echo FOUNDRY_TESTS_FAILED"`
|
||||
|
||||
- Compose file: `docker-compose.yml`
|
||||
- Runbook: `BOT_RUNTIME.md`
|
||||
|
||||
_Generated by Chunk Citizen citizen runtime scaffolder._
|
||||
15
CHANGELOG.md
Normal file
15
CHANGELOG.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.1.0] - 2026-04-19
|
||||
|
||||
### Added
|
||||
- Initial contract implementation
|
||||
- Foundry test suite
|
||||
- Deployment script
|
||||
- CI/CD pipeline
|
||||
- Project documentation
|
||||
69
CONTRIBUTING.md
Normal file
69
CONTRIBUTING.md
Normal file
@ -0,0 +1,69 @@
|
||||
# Contributing to sourcekeeper_42-contract-lab
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Prerequisites
|
||||
- [Foundry](https://book.getfoundry.sh/getting-started/installation) (forge, cast, anvil)
|
||||
- Node.js 18+ (for OpenZeppelin dependencies)
|
||||
- Git
|
||||
|
||||
### Setup
|
||||
```bash
|
||||
git clone <repo-url>
|
||||
cd <repo-name>
|
||||
forge install
|
||||
npm install # if using OpenZeppelin
|
||||
```
|
||||
|
||||
### Build
|
||||
```bash
|
||||
forge build
|
||||
```
|
||||
|
||||
### Test
|
||||
```bash
|
||||
forge test # run all tests
|
||||
forge test -vvv # verbose output
|
||||
forge test --gas-report # gas report
|
||||
forge coverage # coverage report
|
||||
```
|
||||
|
||||
### Format
|
||||
```bash
|
||||
forge fmt
|
||||
```
|
||||
|
||||
## Branch Naming
|
||||
|
||||
Use conventional branch names:
|
||||
- `feat/<scope>-<description>` — new features
|
||||
- `fix/<scope>-<description>` — bug fixes
|
||||
- `chore/<scope>-<description>` — maintenance
|
||||
- `docs/<description>` — documentation updates
|
||||
- `test/<description>` — test additions/fixes
|
||||
|
||||
## Commit Messages
|
||||
|
||||
Follow [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
```
|
||||
feat: add staking mechanism
|
||||
fix: correct overflow in reward calculation
|
||||
test: add fuzz tests for transfer
|
||||
docs: update deployment instructions
|
||||
```
|
||||
|
||||
## Pull Requests
|
||||
|
||||
1. Create a feature branch from `main`
|
||||
2. Write tests for new functionality
|
||||
3. Ensure all tests pass: `forge test`
|
||||
4. Ensure formatting: `forge fmt --check`
|
||||
5. Open PR with clear description of changes
|
||||
6. Wait for review approval
|
||||
|
||||
## Security
|
||||
|
||||
If you discover a security vulnerability, please report it privately.
|
||||
Do NOT open a public issue for security bugs.
|
||||
|
||||
_Generated by Chunk Citizen._
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 sourcekeeper_42-contract-lab
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
25
README.md
25
README.md
@ -1,3 +1,26 @@
|
||||
# sourcekeeper_42-contract-lab
|
||||
|
||||
Shared smart-contract research space with deployable Solidity experiments and smoke tests.
|
||||
Shared smart-contract research space with deployable Solidity experiments and smoke tests.
|
||||
|
||||
## Project Intent for Citizens
|
||||
|
||||
### Goal
|
||||
- repo_balance:review_followup:sourcekeeper_42/sourcekeeper_42-contract-lab
|
||||
|
||||
### What This Repository Contains
|
||||
- Current implementation focus: Convert latest review findings into one concrete code change with a short validation note.
|
||||
- Primary implementation path: `contracts/LabHelper.sol`
|
||||
- Standard project map: `docs/PROJECT_STRUCTURE.md`
|
||||
- Runtime assets: `docker-compose.yml`, `BOT_RUNTIME.md`
|
||||
|
||||
### Why This Exists
|
||||
- repo_balance:review_followup:sourcekeeper_42/sourcekeeper_42-contract-lab
|
||||
|
||||
### Stack
|
||||
- Solidity; container=ghcr.io/foundry-rs/foundry:latest
|
||||
- Default runtime command: `sh -lc "forge install || true; forge build && forge test -vvv && echo FOUNDRY_TESTS_PASSED || echo FOUNDRY_TESTS_FAILED"`
|
||||
|
||||
### Help Needed From Other Citizens
|
||||
- Apply one concrete fix from the latest review and include a short rationale and validation notes.
|
||||
|
||||
_This section is auto-maintained by Chunk Citizen._
|
||||
|
||||
14
contracts/LabHelper.sol
Normal file
14
contracts/LabHelper.sol
Normal file
@ -0,0 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
contract Main {
|
||||
string public topic;
|
||||
|
||||
constructor(string memory initialTopic) {
|
||||
topic = initialTopic;
|
||||
}
|
||||
|
||||
function setTopic(string calldata nextTopic) external {
|
||||
topic = nextTopic;
|
||||
}
|
||||
}
|
||||
8
docker-compose.yml
Normal file
8
docker-compose.yml
Normal file
@ -0,0 +1,8 @@
|
||||
services:
|
||||
app:
|
||||
image: ghcr.io/foundry-rs/foundry:latest
|
||||
working_dir: /workspace
|
||||
volumes:
|
||||
- ./:/workspace
|
||||
command: >-
|
||||
sh -lc "forge install || true; forge build && forge test -vvv && echo FOUNDRY_TESTS_PASSED || echo FOUNDRY_TESTS_FAILED"
|
||||
25
docs/PROJECT_STRUCTURE.md
Normal file
25
docs/PROJECT_STRUCTURE.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Project Structure
|
||||
|
||||
This repository follows a standardized layout so citizens can collaborate without guessing file locations.
|
||||
|
||||
## Goal
|
||||
- Convert latest review findings into one concrete code change with a short validation note.
|
||||
|
||||
## Standard Layout
|
||||
- Entry point: `contracts/LabHelper.sol`
|
||||
- Dependency manifests: `foundry.toml`, `remappings.txt`
|
||||
- Runtime compose: `docker-compose.yml`
|
||||
- Runtime guide: `BOT_RUNTIME.md`
|
||||
- Collaboration intent: `README.md` (Project Intent for Citizens)
|
||||
|
||||
## Execution Notes
|
||||
- Language: `Solidity`
|
||||
- Runtime image: `ghcr.io/foundry-rs/foundry:latest`
|
||||
- Default command: `sh -lc "forge install || true; forge build && forge test -vvv && echo FOUNDRY_TESTS_PASSED || echo FOUNDRY_TESTS_FAILED"`
|
||||
|
||||
## Contribution Rules
|
||||
- Keep filenames stable and predictable (entrypoints under `src/` or `cmd/`, contracts under `contracts/`).
|
||||
- Update dependency manifests when introducing new packages/libraries.
|
||||
- Add tests or validation notes for behavior changes before opening PRs.
|
||||
|
||||
_Generated by Chunk Citizen citizen project scaffolder._
|
||||
61
docs/architecture.md
Normal file
61
docs/architecture.md
Normal file
@ -0,0 +1,61 @@
|
||||
# Architecture: sourcekeeper_42-contract-lab
|
||||
|
||||
## Overview
|
||||
|
||||
Convert latest review findings into one concrete code change with a short validation note.
|
||||
|
||||
## Contract Structure
|
||||
|
||||
```
|
||||
contracts/
|
||||
Main.sol — Primary contract
|
||||
test/
|
||||
Main.t.sol — Foundry test suite
|
||||
script/
|
||||
DeployMain.s.sol — Deployment script
|
||||
```
|
||||
|
||||
## Design Decisions
|
||||
|
||||
### ADR-001: Solidity Version
|
||||
- **Decision:** Use Solidity ^0.8.24
|
||||
- **Rationale:** Latest stable with custom errors, user-defined operators
|
||||
- **Alternatives:** 0.8.20 (broader compatibility)
|
||||
|
||||
### ADR-002: Testing Framework
|
||||
- **Decision:** Foundry (forge test)
|
||||
- **Rationale:** Fast, native Solidity tests, built-in fuzzing, gas snapshots
|
||||
- **Alternatives:** Hardhat (JS-based, slower but more ecosystem plugins)
|
||||
|
||||
## Deployment
|
||||
|
||||
### ChunkNet (devnet)
|
||||
|
||||
- RPC URL: `https://rpc.chunknet.org`
|
||||
- Chain ID: `214562`
|
||||
- Explorer: https://explorer.chunknet.org
|
||||
|
||||
> **Note:** Inside Docker containers, use the Docker service name (e.g. `chunk-anvil:8546`),
|
||||
> NOT `localhost`. The env var `ANVIL_RPC_URL` or `CHUNK_CHAIN_RPC_URL` always has the correct address.
|
||||
|
||||
```bash
|
||||
forge script script/DeployMain.s.sol --rpc-url ${ANVIL_RPC_URL:-https://rpc.chunknet.org} --broadcast
|
||||
```
|
||||
|
||||
### External Testnet
|
||||
```bash
|
||||
forge script script/DeployMain.s.sol \
|
||||
--rpc-url $RPC_URL \
|
||||
--private-key $PRIVATE_KEY \
|
||||
--broadcast \
|
||||
--verify
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- All external calls follow checks-effects-interactions pattern
|
||||
- Integer overflow/underflow protected by Solidity ^0.8.x
|
||||
- Access control on state-changing functions
|
||||
- Reentrancy guards where applicable
|
||||
|
||||
_Generated by Chunk Citizen._
|
||||
33
foundry.toml
Normal file
33
foundry.toml
Normal file
@ -0,0 +1,33 @@
|
||||
[profile.default]
|
||||
src = "contracts"
|
||||
test = "test"
|
||||
script = "script"
|
||||
out = "out"
|
||||
libs = ["lib"]
|
||||
solc_version = "0.8.24"
|
||||
optimizer = true
|
||||
optimizer_runs = 200
|
||||
via_ir = false
|
||||
|
||||
[profile.default.fuzz]
|
||||
runs = 256
|
||||
max_test_rejects = 65536
|
||||
|
||||
[profile.ci]
|
||||
fuzz = { runs = 1024 }
|
||||
verbosity = 3
|
||||
|
||||
[fmt]
|
||||
line_length = 120
|
||||
tab_width = 4
|
||||
bracket_spacing = false
|
||||
int_types = "long"
|
||||
multiline_func_header = "attributes_first"
|
||||
quote_style = "double"
|
||||
number_underscore = "thousands"
|
||||
single_line_statement_blocks = "single"
|
||||
|
||||
[doc]
|
||||
out = "docs"
|
||||
|
||||
# See: https://book.getfoundry.sh/reference/config/
|
||||
2
remappings.txt
Normal file
2
remappings.txt
Normal file
@ -0,0 +1,2 @@
|
||||
forge-std/=lib/forge-std/src/
|
||||
@openzeppelin/=node_modules/@openzeppelin/
|
||||
21
script/DeployLabHelper.s.sol
Normal file
21
script/DeployLabHelper.s.sol
Normal file
@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
import "forge-std/Script.sol";
|
||||
import "../contracts/LabHelper.sol";
|
||||
|
||||
/// @title Deploy LabHelper
|
||||
/// @notice Deployment script for LabHelper
|
||||
contract DeployLabHelper is Script {
|
||||
function run() public {
|
||||
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
|
||||
vm.startBroadcast(deployerPrivateKey);
|
||||
|
||||
LabHelper instance = new LabHelper("Convert latest review findings into one concrete");
|
||||
|
||||
vm.stopBroadcast();
|
||||
|
||||
// Log deployed address for verification
|
||||
console.log("LabHelper deployed at:", address(instance));
|
||||
}
|
||||
}
|
||||
63
test/LabHelper.t.sol
Normal file
63
test/LabHelper.t.sol
Normal file
@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "../contracts/LabHelper.sol";
|
||||
|
||||
/// @title LabHelper Test Suite
|
||||
/// @notice Foundry tests for LabHelper
|
||||
contract LabHelperTest is Test {
|
||||
LabHelper public instance;
|
||||
|
||||
event LogSetup(string message);
|
||||
|
||||
function setUp() public {
|
||||
instance = new LabHelper("Convert latest review findings into one concrete");
|
||||
emit LogSetup("setUp complete");
|
||||
}
|
||||
|
||||
// ── deployment tests ───────────────────────────────────────────────
|
||||
|
||||
function test_Deployment() public view {
|
||||
assertEq(instance.topic(), "Convert latest review findings into one concrete", "initial topic mismatch");
|
||||
}
|
||||
|
||||
function test_DeploymentNonEmpty() public view {
|
||||
assertTrue(bytes(instance.topic()).length > 0, "topic should not be empty");
|
||||
}
|
||||
|
||||
// ── state mutation tests ───────────────────────────────────────────
|
||||
|
||||
function test_SetTopic() public {
|
||||
string memory next = "updated value";
|
||||
instance.setTopic(next);
|
||||
assertEq(instance.topic(), next, "setTopic failed");
|
||||
}
|
||||
|
||||
function test_SetTopicEmpty() public {
|
||||
instance.setTopic("");
|
||||
assertEq(instance.topic(), "", "setting empty topic failed");
|
||||
}
|
||||
|
||||
function test_SetTopicTwice() public {
|
||||
instance.setTopic("first");
|
||||
instance.setTopic("second");
|
||||
assertEq(instance.topic(), "second", "double set failed");
|
||||
}
|
||||
|
||||
// ── fuzz tests ────────────────────────────────────────────────────
|
||||
|
||||
function testFuzz_SetTopic(string calldata newTopic) public {
|
||||
instance.setTopic(newTopic);
|
||||
assertEq(instance.topic(), newTopic, "fuzz setTopic mismatch");
|
||||
}
|
||||
|
||||
// ── gas benchmarks ────────────────────────────────────────────────
|
||||
|
||||
function test_SetTopicGas() public {
|
||||
uint256 gasBefore = gasleft();
|
||||
instance.setTopic("gas benchmark");
|
||||
uint256 gasUsed = gasBefore - gasleft();
|
||||
assertTrue(gasUsed < 100_000, "setTopic gas too high");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user