From 8ea50648bd7e0143cdce93a1cba6ca870ad04ffe Mon Sep 17 00:00:00 2001 From: kamalbuilds Date: Sat, 25 Jan 2025 20:57:42 +0530 Subject: [PATCH 1/3] create a statemachine pattern --- contracts/solidity_patterns/StateMachine.sol | 68 ++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 contracts/solidity_patterns/StateMachine.sol diff --git a/contracts/solidity_patterns/StateMachine.sol b/contracts/solidity_patterns/StateMachine.sol new file mode 100644 index 0000000..3612958 --- /dev/null +++ b/contracts/solidity_patterns/StateMachine.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "@nilfoundation/smart-contracts/contracts/NilBase.sol"; + +contract StateMachine is NilBase { + enum Stages { + Initialize, + Processing, + Completed, + Failed + } + + Stages public currentStage; + + uint256 public processValue; + mapping(address => bool) public hasParticipated; + + event StageAdvanced(Stages newStage); + event ProcessValueUpdated(uint256 newValue); + + modifier atStage(Stages _stage) { + require(currentStage == _stage, "Invalid stage"); + _; + } + + modifier transitionAfter() { + _; + _nextStage(); + } + + constructor() { + currentStage = Stages.Initialize; + } + + function startProcess() external atStage(Stages.Initialize) transitionAfter { + processValue = 0; + emit ProcessValueUpdated(processValue); + } + + function participate() external atStage(Stages.Processing) { + require(!hasParticipated[msg.sender], "Already participated"); + + hasParticipated[msg.sender] = true; + processValue += 1; + + emit ProcessValueUpdated(processValue); + + if (processValue >= 5) { + currentStage = Stages.Completed; + emit StageAdvanced(Stages.Completed); + } + } + + function _nextStage() internal { + currentStage = Stages(uint(currentStage) + 1); + emit StageAdvanced(currentStage); + } + + function reset() external onlyInternal { + require(currentStage == Stages.Completed || currentStage == Stages.Failed, + "Can only reset from Completed or Failed state"); + currentStage = Stages.Initialize; + processValue = 0; + emit StageAdvanced(Stages.Initialize); + emit ProcessValueUpdated(processValue); + } +} \ No newline at end of file From e320130c6606338d1e70d7163484ce861cb80e58 Mon Sep 17 00:00:00 2001 From: kamalbuilds Date: Sat, 25 Jan 2025 20:58:09 +0530 Subject: [PATCH 2/3] make a cli pattern call --- scripts/create-pattern.js | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 scripts/create-pattern.js diff --git a/scripts/create-pattern.js b/scripts/create-pattern.js new file mode 100644 index 0000000..ef3af49 --- /dev/null +++ b/scripts/create-pattern.js @@ -0,0 +1,40 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); + +const PATTERNS = { + 'access': 'AccessRestriction.sol', + 'state': 'StateMachine.sol', + 'guard': 'GuardCheck.sol', + 'proxy': 'ProxyDelegate.sol', + 'check': 'CheckEffectsInteraction.sol' +}; + +function createPattern(patternName, projectPath) { + if (!PATTERNS[patternName]) { + console.error(`Invalid pattern name. Available patterns: ${Object.keys(PATTERNS).join(', ')}`); + process.exit(1); + } + + const templatePath = path.join(__dirname, '..', 'contracts', 'solidity_patterns', PATTERNS[patternName]); + const destPath = path.join(projectPath, 'contracts', 'patterns', PATTERNS[patternName]); + + // Create directories if they don't exist + fs.mkdirSync(path.join(projectPath, 'contracts', 'patterns'), { recursive: true }); + + // Copy pattern file + fs.copyFileSync(templatePath, destPath); + console.log(`Created ${patternName} pattern at: ${destPath}`); +} + +// Get command line arguments +const patternName = process.argv[2]; +const projectDir = process.argv[3] || '.'; + +if (!patternName) { + console.error('Please specify a pattern name'); + console.log(`Available patterns: ${Object.keys(PATTERNS).join(', ')}`); + process.exit(1); +} + +createPattern(patternName.toLowerCase(), path.resolve(projectDir)); \ No newline at end of file From f5359ae62192b74645357bdf40eee3cfa11fc06b Mon Sep 17 00:00:00 2001 From: kamalbuilds Date: Sat, 25 Jan 2025 20:58:22 +0530 Subject: [PATCH 3/3] add script to the cli --- scripts/cli.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/cli.js b/scripts/cli.js index bf84e92..433fc88 100755 --- a/scripts/cli.js +++ b/scripts/cli.js @@ -51,9 +51,22 @@ function copyFile(srcFilePath, destFilePath) { } } +function addPatternCommand() { + const packageJsonPath = path.join(projectPath, 'package.json'); + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + + // Add create-pattern command to scripts + packageJson.scripts = packageJson.scripts || {}; + packageJson.scripts['create-pattern'] = 'node scripts/create-pattern.js'; + + fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); +} + createPackageJson(templatePath, projectPath); copyFile('.env.example', '.env'); copyFile('ignition/modules/Incrementer.ts', 'ignition/modules/Incrementer.ts'); copyFile('contracts/Incrementer.sol', 'contracts/Incrementer.sol'); +copyFile('scripts/create-pattern.js', 'scripts/create-pattern.js'); +addPatternCommand(); console.log('Project setup complete!');