From 6a2a30662314efda1802dbc51cdaadaef801adc4 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Wed, 4 Dec 2024 12:30:33 +0100 Subject: [PATCH 01/13] create the CanvasOnchain contract and write the test --- package.json | 1 + packages/hardhat/contracts/CanvasOnchain.sol | 131 +++++++++++++++++++ packages/hardhat/hardhat.config.ts | 1 + packages/hardhat/test/CanvasOnchain.ts | 83 ++++++++++++ yarn.lock | 12 ++ 5 files changed, 228 insertions(+) create mode 100644 packages/hardhat/contracts/CanvasOnchain.sol create mode 100644 packages/hardhat/test/CanvasOnchain.ts diff --git a/package.json b/package.json index a569f19..2436d72 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ }, "packageManager": "yarn@3.2.3", "devDependencies": { + "@nomicfoundation/hardhat-network-helpers": "^1.0.12", "husky": "^9.1.6", "lint-staged": "^15.2.10" }, diff --git a/packages/hardhat/contracts/CanvasOnchain.sol b/packages/hardhat/contracts/CanvasOnchain.sol new file mode 100644 index 0000000..2d20754 --- /dev/null +++ b/packages/hardhat/contracts/CanvasOnchain.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract PixelCanvas is Ownable { + // Canvas Dimensions + uint256 public constant CANVAS_WIDTH = 64; + uint256 public constant CANVAS_HEIGHT = 64; + + // Color Palette (Limited Options) + enum Color { + WHITE, + BLACK, + RED, + GREEN, + BLUE, + YELLOW, + PURPLE, + ORANGE + } + + // Pixel Structure + struct Pixel { + address author; + Color color; + uint256 timestamp; + } + + // 2D Mapping to store pixels + Pixel[CANVAS_WIDTH][CANVAS_HEIGHT] public canvas; + + // Events + event PixelPlaced(address indexed author, uint256 x, uint256 y, Color color); + + // Constructor to initialize default Buidlguidl Batch11 drawing + constructor() Ownable(msg.sender){ + + // Initial drawing representing Buidlguidl Batch11 logo + initializeBuidlGuidlLogo(); + } + + /** + * @dev Initialize a default Buidlguidl Batch11 inspired pixel art + * This is a simplified representation and can be customized + */ + function initializeBuidlGuidlLogo() private { + // B letter representation + for (uint256 x = 10; x < 20; x++) { + for (uint256 y = 10; y < 50; y++) { + canvas[x][y] = Pixel({ + author: owner(), + color: Color.BLUE, + timestamp: block.timestamp + }); + } + } + + // 11 representation with some pixels + for (uint256 x = 30; x < 40; x++) { + for (uint256 y = 20; y < 30; y++) { + canvas[x][y] = Pixel({ + author: owner(), + color: Color.GREEN, + timestamp: block.timestamp + }); + } + } + + // Add some distinctive pixels to represent Buidlguidl spirit + canvas[32][25] = Pixel({ + author: owner(), + color: Color.RED, + timestamp: block.timestamp + }); + } + + /** + * @dev Place a pixel on the canvas + * @param x X-coordinate of the pixel + * @param y Y-coordinate of the pixel + * @param color Color of the pixel + */ + function placePixel(uint256 x, uint256 y, Color color) external { + // Validate pixel coordinates + require(x < CANVAS_WIDTH, "X coordinate out of bounds"); + require(y < CANVAS_HEIGHT, "Y coordinate out of bounds"); + + // Update pixel + canvas[x][y] = Pixel({ + author: msg.sender, + color: color, + timestamp: block.timestamp + }); + + // Emit event + emit PixelPlaced(msg.sender, x, y, color); + } + + /** + * @dev Get pixel information + * @param x X-coordinate of the pixel + * @param y Y-coordinate of the pixel + * @return Pixel details + */ + function getPixel(uint256 x, uint256 y) external view returns (Pixel memory) { + require(x < CANVAS_WIDTH, "X coordinate out of bounds"); + require(y < CANVAS_HEIGHT, "Y coordinate out of bounds"); + return canvas[x][y]; + } + + /** + * @dev Reset a specific pixel (only owner) + * @param x X-coordinate of the pixel + * @param y Y-coordinate of the pixel + */ + function resetPixel(uint256 x, uint256 y) external onlyOwner { + require(x < CANVAS_WIDTH, "X coordinate out of bounds"); + require(y < CANVAS_HEIGHT, "Y coordinate out of bounds"); + + delete canvas[x][y]; + } + + /** + * @dev Get canvas snapshot (useful for viewing entire canvas) + * @return Array of pixels + */ + function getCanvasSnapshot() external view returns (Pixel[CANVAS_WIDTH][CANVAS_HEIGHT] memory) { + return canvas; + } +} diff --git a/packages/hardhat/hardhat.config.ts b/packages/hardhat/hardhat.config.ts index e82e01b..878af2f 100644 --- a/packages/hardhat/hardhat.config.ts +++ b/packages/hardhat/hardhat.config.ts @@ -7,6 +7,7 @@ import "@typechain/hardhat"; import "hardhat-gas-reporter"; import "solidity-coverage"; import "@nomicfoundation/hardhat-verify"; +import "@nomicfoundation/hardhat-network-helpers"; import "hardhat-deploy"; import "hardhat-deploy-ethers"; diff --git a/packages/hardhat/test/CanvasOnchain.ts b/packages/hardhat/test/CanvasOnchain.ts new file mode 100644 index 0000000..2ced047 --- /dev/null +++ b/packages/hardhat/test/CanvasOnchain.ts @@ -0,0 +1,83 @@ +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; +import { expect } from "chai"; +import hre from "hardhat"; + +describe("PixelCanvas", function () { + async function deployPixelCanvas() { + const [owner, user1, user2] = await hre.ethers.getSigners(); + const pixel = await hre.ethers.getContractFactory("PixelCanvas"); + const Pixel = await pixel.deploy(); + return { owner, user1, user2, Pixel }; + } + + describe("Deployment", function () { + it("Should set the correct owner", async function () { + const { owner, Pixel } = await loadFixture(deployPixelCanvas); + expect(await Pixel.owner()).to.equal(owner.address); + }); + + it("Should initialize canvas with predefined pixels", async function () { + // Check a few predefined pixels from initializeBuidlGuidlLogo() + const { owner, Pixel } = await loadFixture(deployPixelCanvas); + const bluePixel = await Pixel.canvas(15, 25); + expect(bluePixel.color).to.equal(4); // Blue is enum index 1 + expect(bluePixel.author).to.equal(owner.address); + }); + }); + + describe("Pixel Placement", function () { + it("Should allow placing a pixel", async function () { + const x = 10; + const y = 20; + const color = 2; // Red from enum + const { user1, Pixel } = await loadFixture(deployPixelCanvas); + // Place pixel from user1 + await Pixel.connect(user1).placePixel(x, y, color); + + const pixel = await Pixel.canvas(x, y); + expect(pixel.author).to.equal(user1.address); + expect(pixel.color).to.equal(color); + }); + + it("Should reject out-of-bounds pixel placement", async function () { + const { Pixel } = await loadFixture(deployPixelCanvas); + await expect(Pixel.placePixel(64, 10, 0)).to.be.revertedWith("X coordinate out of bounds"); + + await expect(Pixel.placePixel(10, 64, 0)).to.be.revertedWith("Y coordinate out of bounds"); + }); + + it("Should emit PixelPlaced event", async function () { + const x = 30; + const y = 40; + + const color = 3; // Green from enum + const { user1, Pixel } = await loadFixture(deployPixelCanvas); + await expect(Pixel.connect(user1).placePixel(x, y, color)) + .to.emit(Pixel, "PixelPlaced") + .withArgs(user1.address, x, y, color); + }); + }); + + describe("Pixel Retrieval", function () { + it("Should retrieve pixel information", async function () { + const x = 12; + const y = 15; + const color = 4; // Blue from enum + const { user1, Pixel } = await loadFixture(deployPixelCanvas); + await Pixel.connect(user1).placePixel(x, y, color); + + const pixel = await Pixel.getPixel(x, y); + expect(pixel.author).to.equal(user1.address); + expect(pixel.color).to.equal(color); + }); + }); + + describe("Canvas Snapshot", function () { + it("Should return full canvas snapshot", async function () { + const { Pixel } = await loadFixture(deployPixelCanvas); + const snapshot = await Pixel.getCanvasSnapshot(); + expect(snapshot.length).to.equal(64); + expect(snapshot[0].length).to.equal(64); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index e0de057..0e96696 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1739,6 +1739,17 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/hardhat-network-helpers@npm:^1.0.12": + version: 1.0.12 + resolution: "@nomicfoundation/hardhat-network-helpers@npm:1.0.12" + dependencies: + ethereumjs-util: ^7.1.4 + peerDependencies: + hardhat: ^2.9.5 + checksum: 7e1b91789dd4e73464b4eec919b1e67c6d482dd7534f4f7cae73fb5bdddd69f2a47143754b34385b098a1df0f4875cd4d2e1109fc3d847db76f4b0a9a44bd959 + languageName: node + linkType: hard + "@nomicfoundation/hardhat-verify@npm:^2.0.10": version: 2.0.10 resolution: "@nomicfoundation/hardhat-verify@npm:2.0.10" @@ -11941,6 +11952,7 @@ __metadata: version: 0.0.0-use.local resolution: "se-2@workspace:." dependencies: + "@nomicfoundation/hardhat-network-helpers": ^1.0.12 husky: ^9.1.6 lint-staged: ^15.2.10 react-icons: ^5.3.0 From 8ba8d1d14c98278a854057f4c10a593d815851c6 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Wed, 4 Dec 2024 14:53:32 +0100 Subject: [PATCH 02/13] remove the reset function --- packages/hardhat/contracts/CanvasOnchain.sol | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/hardhat/contracts/CanvasOnchain.sol b/packages/hardhat/contracts/CanvasOnchain.sol index 2d20754..9679698 100644 --- a/packages/hardhat/contracts/CanvasOnchain.sol +++ b/packages/hardhat/contracts/CanvasOnchain.sol @@ -109,17 +109,8 @@ contract PixelCanvas is Ownable { return canvas[x][y]; } - /** - * @dev Reset a specific pixel (only owner) - * @param x X-coordinate of the pixel - * @param y Y-coordinate of the pixel - */ - function resetPixel(uint256 x, uint256 y) external onlyOwner { - require(x < CANVAS_WIDTH, "X coordinate out of bounds"); - require(y < CANVAS_HEIGHT, "Y coordinate out of bounds"); - - delete canvas[x][y]; - } + + /** * @dev Get canvas snapshot (useful for viewing entire canvas) From 5a7ec9d3d42016e861c2904e82d35376e4c528d5 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Thu, 5 Dec 2024 05:38:36 +0100 Subject: [PATCH 03/13] add a readme file for the description in the hardhat folder --- packages/hardhat/Readme.md | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 packages/hardhat/Readme.md diff --git a/packages/hardhat/Readme.md b/packages/hardhat/Readme.md new file mode 100644 index 0000000..23b036f --- /dev/null +++ b/packages/hardhat/Readme.md @@ -0,0 +1,48 @@ +## PixelCanvas: Decentralized Collaborative Pixel Art Smart Contract + +### Contract Overview +A collaborative on-chain pixel art platform implemented as an Ethereum smart contract, enabling users to create and modify a shared 64x64 pixel canvas. + +### Technical Specifications +- **Blockchain**: Ethereum +- **Solidity Version**: ^0.8.20 +- **Dependencies**: OpenZeppelin Ownable +- **Canvas Dimensions**: 64x64 pixels +- **Color Palette**: 8 predefined colors + +### Key Components + +#### Pixel Structure +```solidity +struct Pixel { + address author; // Address of pixel creator + Color color; // Chosen color from enum + uint256 timestamp;// Block timestamp of pixel placement +} + +Core Functionalities +1. Pixel Placement + +Function: placePixel(uint256 x, uint256 y, Color color) +Validates coordinate boundaries +Allows user to place a single pixel +Emits PixelPlaced event for tracking + +2. Canvas Retrieval + +getPixel(x, y): Retrieves individual pixel information +getCanvasSnapshot(): Returns entire canvas state + +3. Initialization +Test the CanvasOnchain contract +Includes default Buidlguidl Batch11 logo on contract deployment +Demonstrates initial canvas state + +Known Limitations + +Fixed 64x64 canvas size +Limited 8-color palette +No pixel modification after placement + + + From b9ad0e1264440dbaaf5350f8e83260826a254037 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Thu, 5 Dec 2024 14:30:59 +0100 Subject: [PATCH 04/13] write the deploy script and deploy to hardhat localhost --- package.json | 1 + packages/hardhat/deploy/canvasOnchain.ts | 52 +++++++ packages/hardhat/hardhat.config.ts | 4 +- packages/hardhat/package.json | 1 + packages/nextjs/scaffold.config.ts | 2 +- yarn.lock | 186 +++++++++++++++++++++++ 6 files changed, 243 insertions(+), 3 deletions(-) create mode 100644 packages/hardhat/deploy/canvasOnchain.ts diff --git a/package.json b/package.json index 2436d72..39f78b3 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "node": ">=18.18.0" }, "dependencies": { + "hardhat": "^2.22.17", "react-icons": "^5.3.0" } } diff --git a/packages/hardhat/deploy/canvasOnchain.ts b/packages/hardhat/deploy/canvasOnchain.ts new file mode 100644 index 0000000..e21f428 --- /dev/null +++ b/packages/hardhat/deploy/canvasOnchain.ts @@ -0,0 +1,52 @@ +import { ethers, network, run } from "hardhat"; +import { ContractFactory } from "ethers"; + +async function main() { + // Get the account that will deploy the contract + const [deployer] = await ethers.getSigners(); + + console.log("Deploying PixelCanvas contract with the account:", deployer.address); + + // Check deployer's balance + const balance = await ethers.provider.getBalance(deployer.address); + console.log("Account balance:", ethers.formatEther(balance), "ETH"); + + // Get the contract factory for PixelCanvas + const PixelCanvasFactory: ContractFactory = await ethers.getContractFactory("PixelCanvas"); + + // Deploy the contract + const pixelCanvas = await PixelCanvasFactory.deploy(); + + // Wait for the contract to be deployed + await pixelCanvas.waitForDeployment(); + + // Get the deployed contract address + const contractAddress = await pixelCanvas.getAddress(); + + console.log("PixelCanvas deployed to:", contractAddress); + + // Verify the contract on Etherscan only on supported networks + if (network.name !== "hardhat" && network.name !== "localhost") { + console.log("Waiting for block confirmations..."); + await new Promise(resolve => setTimeout(resolve, 45000)); // 45 seconds + + try { + await run("verify:verify", { + address: contractAddress, + constructorArguments: [], + }); + console.log("Contract verified on Etherscan"); + } catch (error) { + console.error("Verification failed:", error); + } + } +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error("Deployment error:", error); + process.exit(1); + }); + +export default main; diff --git a/packages/hardhat/hardhat.config.ts b/packages/hardhat/hardhat.config.ts index 878af2f..f922c82 100644 --- a/packages/hardhat/hardhat.config.ts +++ b/packages/hardhat/hardhat.config.ts @@ -34,7 +34,7 @@ const config: HardhatUserConfig = { }, ], }, - defaultNetwork: "localhost", + defaultNetwork: "sepolia", namedAccounts: { deployer: { // By default, it will take the first Hardhat account as the deployer @@ -55,7 +55,7 @@ const config: HardhatUserConfig = { accounts: [deployerPrivateKey], }, sepolia: { - url: `https://rpc2.sepolia.org`, + url: `https://eth-sepolia.g.alchemy.com/v2/FIQ1qwifmra7ZqdkVHnZ2lHQAKG8j4Yd`, accounts: [deployerPrivateKey], }, arbitrum: { diff --git a/packages/hardhat/package.json b/packages/hardhat/package.json index c60c8d1..538a0a6 100644 --- a/packages/hardhat/package.json +++ b/packages/hardhat/package.json @@ -7,6 +7,7 @@ "check-types": "tsc --noEmit --incremental", "compile": "hardhat compile", "deploy": "hardhat deploy", + "deploy:canvas": "hardhat run deploy/canvasOnchain.ts --network sepolia", "fork": "MAINNET_FORKING_ENABLED=true hardhat node --network hardhat --no-deploy", "generate": "hardhat run scripts/generateAccount.ts", "flatten": "hardhat flatten", diff --git a/packages/nextjs/scaffold.config.ts b/packages/nextjs/scaffold.config.ts index c3f0f71..bfe43d2 100644 --- a/packages/nextjs/scaffold.config.ts +++ b/packages/nextjs/scaffold.config.ts @@ -10,7 +10,7 @@ export type ScaffoldConfig = { const scaffoldConfig = { // The networks on which your DApp is live - targetNetworks: [chains.optimism], + targetNetworks: [chains.sepolia], // The interval at which your front-end polls the RPC servers for new data // it has no effect if you only target the local network (default is 4000) diff --git a/yarn.lock b/yarn.lock index 0e96696..953c05a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1591,6 +1591,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr-darwin-arm64@npm:0.6.5": + version: 0.6.5 + resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.6.5" + checksum: fb4ec67761fa044156fac5bcc0540312e93c6b1a8086d9871fb88cfc880fcc0f8db58a9ae8cab0fb9b74b3cb54571053f7016039c4730f5186c088102f5a43c6 + languageName: node + linkType: hard + "@nomicfoundation/edr-darwin-x64@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-darwin-x64@npm:0.5.2" @@ -1598,6 +1605,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr-darwin-x64@npm:0.6.5": + version: 0.6.5 + resolution: "@nomicfoundation/edr-darwin-x64@npm:0.6.5" + checksum: 31444f48aee4e9c522da4dc799665b2d11432ca9aa27510161f1833b6f566714cecf8e99649d4209556a8346ab2ae521060ebd47ce21dad31a3f2a5d053607f0 + languageName: node + linkType: hard + "@nomicfoundation/edr-linux-arm64-gnu@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.5.2" @@ -1605,6 +1619,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr-linux-arm64-gnu@npm:0.6.5": + version: 0.6.5 + resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.6.5" + checksum: c7059092122dd58ad38f0fa2d577b9c822424f335c217bf11c01b05257f6de7788f9db15546d2f3cbb6ba3cf0a6062d113d093f0000fd2e13fc1e2033b39c4ad + languageName: node + linkType: hard + "@nomicfoundation/edr-linux-arm64-musl@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.5.2" @@ -1612,6 +1633,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr-linux-arm64-musl@npm:0.6.5": + version: 0.6.5 + resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.6.5" + checksum: 4d011d07c2d63f36bea81d935eb29a41815ddc2570e60c6b62668a96442b00e03285ed7fea2afd40554ef3f4a2f45b8123d8623f05862ecc6d9a4c7c606cdff4 + languageName: node + linkType: hard + "@nomicfoundation/edr-linux-x64-gnu@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.5.2" @@ -1619,6 +1647,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr-linux-x64-gnu@npm:0.6.5": + version: 0.6.5 + resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.6.5" + checksum: d20616245f643cc930c9b10e2969a550f39a506c5e77d69dca2ecfd23b23bfbae4fe63a7d8add355e2c79b3624c130270cbd24cba0ae42583b087019e7d2e3fa + languageName: node + linkType: hard + "@nomicfoundation/edr-linux-x64-musl@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.5.2" @@ -1626,6 +1661,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr-linux-x64-musl@npm:0.6.5": + version: 0.6.5 + resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.6.5" + checksum: 4e47f0e5b5176cc500c4a5beff526688a26be69d9ac2d6176c432a7ca51da4270f3b3f6738771a13c68149c66c94dcf4b719c33cf97edf96a15ddabbbc22ba1c + languageName: node + linkType: hard + "@nomicfoundation/edr-win32-x64-msvc@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.5.2" @@ -1633,6 +1675,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr-win32-x64-msvc@npm:0.6.5": + version: 0.6.5 + resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.6.5" + checksum: ae953433f5e45e96f0448219716b7e204fc18e8b0b7f840e4158daf26e75163de528cb74940ded25b24a1f23af82993ff312ddcde120d94acecaaaf7e87f7eb7 + languageName: node + linkType: hard + "@nomicfoundation/edr@npm:^0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr@npm:0.5.2" @@ -1648,6 +1697,21 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr@npm:^0.6.5": + version: 0.6.5 + resolution: "@nomicfoundation/edr@npm:0.6.5" + dependencies: + "@nomicfoundation/edr-darwin-arm64": 0.6.5 + "@nomicfoundation/edr-darwin-x64": 0.6.5 + "@nomicfoundation/edr-linux-arm64-gnu": 0.6.5 + "@nomicfoundation/edr-linux-arm64-musl": 0.6.5 + "@nomicfoundation/edr-linux-x64-gnu": 0.6.5 + "@nomicfoundation/edr-linux-x64-musl": 0.6.5 + "@nomicfoundation/edr-win32-x64-msvc": 0.6.5 + checksum: 5390da27b59836b64a4f5975e02dc803a70c5ba82dd29795366a79b62b53927f69d43aaf533ec0e5f56a613c29c5edea4b188059d80caf51db9cd7bd9da9fb0a + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-common@npm:4.0.4": version: 4.0.4 resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.4" @@ -4983,6 +5047,15 @@ __metadata: languageName: node linkType: hard +"chokidar@npm:^4.0.0": + version: 4.0.1 + resolution: "chokidar@npm:4.0.1" + dependencies: + readdirp: ^4.0.1 + checksum: 193da9786b0422a895d59c7552195d15c6c636e6a2293ae43d09e34e243e24ccd02d693f007c767846a65abbeae5fea6bfacb8fc2ddec4ea4d397620d552010d + languageName: node + linkType: hard + "chownr@npm:^1.1.4": version: 1.1.4 resolution: "chownr@npm:1.1.4" @@ -7149,6 +7222,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.4.2": + version: 6.4.2 + resolution: "fdir@npm:6.4.2" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 517ad31c495f1c0778238eef574a7818788efaaf2ce1969ffa18c70793e2951a9763dfa2e6720b8fcef615e602a3cbb47f9b8aea9da0b02147579ab36043f22f + languageName: node + linkType: hard + "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -8017,6 +8102,68 @@ __metadata: languageName: node linkType: hard +"hardhat@npm:^2.22.17": + version: 2.22.17 + resolution: "hardhat@npm:2.22.17" + dependencies: + "@ethersproject/abi": ^5.1.2 + "@metamask/eth-sig-util": ^4.0.0 + "@nomicfoundation/edr": ^0.6.5 + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-tx": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + "@nomicfoundation/solidity-analyzer": ^0.1.0 + "@sentry/node": ^5.18.1 + "@types/bn.js": ^5.1.0 + "@types/lru-cache": ^5.1.0 + adm-zip: ^0.4.16 + aggregate-error: ^3.0.0 + ansi-escapes: ^4.3.0 + boxen: ^5.1.2 + chokidar: ^4.0.0 + ci-info: ^2.0.0 + debug: ^4.1.1 + enquirer: ^2.3.0 + env-paths: ^2.2.0 + ethereum-cryptography: ^1.0.3 + ethereumjs-abi: ^0.6.8 + find-up: ^5.0.0 + fp-ts: 1.19.3 + fs-extra: ^7.0.1 + immutable: ^4.0.0-rc.12 + io-ts: 1.10.4 + json-stream-stringify: ^3.1.4 + keccak: ^3.0.2 + lodash: ^4.17.11 + mnemonist: ^0.38.0 + mocha: ^10.0.0 + p-map: ^4.0.0 + picocolors: ^1.1.0 + raw-body: ^2.4.1 + resolve: 1.17.0 + semver: ^6.3.0 + solc: 0.8.26 + source-map-support: ^0.5.13 + stacktrace-parser: ^0.1.10 + tinyglobby: ^0.2.6 + tsort: 0.0.1 + undici: ^5.14.0 + uuid: ^8.3.2 + ws: ^7.4.6 + peerDependencies: + ts-node: "*" + typescript: "*" + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + bin: + hardhat: internal/cli/bootstrap.js + checksum: 52fe0b846c6e5808adf85c7704dfb13bfd22368f54b9ade3ba7719e60ea725a6558715f79e4eb92071ef71d1e66bdd02ff0138f71aedf3fea77784ed5ae11809 + languageName: node + linkType: hard + "has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": version: 1.0.2 resolution: "has-bigints@npm:1.0.2" @@ -9001,6 +9148,13 @@ __metadata: languageName: node linkType: hard +"json-stream-stringify@npm:^3.1.4": + version: 3.1.6 + resolution: "json-stream-stringify@npm:3.1.6" + checksum: ce873e09fe18461960b7536f63e2f913a2cb242819513856ed1af58989d41846976e7177cb1fe3c835220023aa01e534d56b6d5c3290a5b23793a6f4cb93785e + languageName: node + linkType: hard + "json5@npm:^1.0.2": version: 1.0.2 resolution: "json5@npm:1.0.2" @@ -10855,6 +11009,13 @@ __metadata: languageName: node linkType: hard +"picocolors@npm:^1.1.0": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 + languageName: node + linkType: hard + "picomatch@npm:^2.0.4, picomatch@npm:^2.0.7, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" @@ -10862,6 +11023,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: a7a5188c954f82c6585720e9143297ccd0e35ad8072231608086ca950bee672d51b0ef676254af0788205e59bd4e4deb4e7708769226bed725bf13370a7d1464 + languageName: node + linkType: hard + "pidtree@npm:~0.6.0": version: 0.6.0 resolution: "pidtree@npm:0.6.0" @@ -11554,6 +11722,13 @@ __metadata: languageName: node linkType: hard +"readdirp@npm:^4.0.1": + version: 4.0.2 + resolution: "readdirp@npm:4.0.2" + checksum: 309376e717f94fb7eb61bec21e2603243a9e2420cd2e9bf94ddf026aefea0d7377ed1a62f016d33265682e44908049a55c3cfc2307450a1421654ea008489b39 + languageName: node + linkType: hard + "readdirp@npm:~3.3.0": version: 3.3.0 resolution: "readdirp@npm:3.3.0" @@ -11953,6 +12128,7 @@ __metadata: resolution: "se-2@workspace:." dependencies: "@nomicfoundation/hardhat-network-helpers": ^1.0.12 + hardhat: ^2.22.17 husky: ^9.1.6 lint-staged: ^15.2.10 react-icons: ^5.3.0 @@ -12882,6 +13058,16 @@ __metadata: languageName: node linkType: hard +"tinyglobby@npm:^0.2.6": + version: 0.2.10 + resolution: "tinyglobby@npm:0.2.10" + dependencies: + fdir: ^6.4.2 + picomatch: ^4.0.2 + checksum: 7e2ffe262ebc149036bdef37c56b32d02d52cf09efa7d43dbdab2ea3c12844a4da881058835ce4c74d1891190e5ad5ec5133560a11ec8314849b68ad0d99d3f4 + languageName: node + linkType: hard + "tmp@npm:0.0.33": version: 0.0.33 resolution: "tmp@npm:0.0.33" From f61835f3f5eefb6038a59689757253d3f00c8682 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Thu, 5 Dec 2024 15:15:10 +0100 Subject: [PATCH 05/13] updates --- .../hardhat/contracts/{CanvasOnchain.sol => PixelCanvas.sol} | 0 packages/hardhat/deploy/{canvasOnchain.ts => PixelCanvas.ts} | 0 packages/hardhat/hardhat.config.ts | 2 +- packages/hardhat/package.json | 1 - packages/nextjs/scaffold.config.ts | 2 +- 5 files changed, 2 insertions(+), 3 deletions(-) rename packages/hardhat/contracts/{CanvasOnchain.sol => PixelCanvas.sol} (100%) rename packages/hardhat/deploy/{canvasOnchain.ts => PixelCanvas.ts} (100%) diff --git a/packages/hardhat/contracts/CanvasOnchain.sol b/packages/hardhat/contracts/PixelCanvas.sol similarity index 100% rename from packages/hardhat/contracts/CanvasOnchain.sol rename to packages/hardhat/contracts/PixelCanvas.sol diff --git a/packages/hardhat/deploy/canvasOnchain.ts b/packages/hardhat/deploy/PixelCanvas.ts similarity index 100% rename from packages/hardhat/deploy/canvasOnchain.ts rename to packages/hardhat/deploy/PixelCanvas.ts diff --git a/packages/hardhat/hardhat.config.ts b/packages/hardhat/hardhat.config.ts index f922c82..b66897f 100644 --- a/packages/hardhat/hardhat.config.ts +++ b/packages/hardhat/hardhat.config.ts @@ -34,7 +34,7 @@ const config: HardhatUserConfig = { }, ], }, - defaultNetwork: "sepolia", + defaultNetwork: "localhost", namedAccounts: { deployer: { // By default, it will take the first Hardhat account as the deployer diff --git a/packages/hardhat/package.json b/packages/hardhat/package.json index 538a0a6..c60c8d1 100644 --- a/packages/hardhat/package.json +++ b/packages/hardhat/package.json @@ -7,7 +7,6 @@ "check-types": "tsc --noEmit --incremental", "compile": "hardhat compile", "deploy": "hardhat deploy", - "deploy:canvas": "hardhat run deploy/canvasOnchain.ts --network sepolia", "fork": "MAINNET_FORKING_ENABLED=true hardhat node --network hardhat --no-deploy", "generate": "hardhat run scripts/generateAccount.ts", "flatten": "hardhat flatten", diff --git a/packages/nextjs/scaffold.config.ts b/packages/nextjs/scaffold.config.ts index bfe43d2..c3f0f71 100644 --- a/packages/nextjs/scaffold.config.ts +++ b/packages/nextjs/scaffold.config.ts @@ -10,7 +10,7 @@ export type ScaffoldConfig = { const scaffoldConfig = { // The networks on which your DApp is live - targetNetworks: [chains.sepolia], + targetNetworks: [chains.optimism], // The interval at which your front-end polls the RPC servers for new data // it has no effect if you only target the local network (default is 4000) From 29bc88a1d59a5ff2059a40badf5c1e6ca97a0065 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Fri, 6 Dec 2024 00:21:41 +0100 Subject: [PATCH 06/13] resolve issue --- packages/hardhat/Readme.md | 2 +- packages/hardhat/test/{CanvasOnchain.ts => PixelCanvas.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/hardhat/test/{CanvasOnchain.ts => PixelCanvas.ts} (100%) diff --git a/packages/hardhat/Readme.md b/packages/hardhat/Readme.md index 23b036f..7d11b9e 100644 --- a/packages/hardhat/Readme.md +++ b/packages/hardhat/Readme.md @@ -34,7 +34,7 @@ getPixel(x, y): Retrieves individual pixel information getCanvasSnapshot(): Returns entire canvas state 3. Initialization -Test the CanvasOnchain contract +Test the PixelCanvas contract Includes default Buidlguidl Batch11 logo on contract deployment Demonstrates initial canvas state diff --git a/packages/hardhat/test/CanvasOnchain.ts b/packages/hardhat/test/PixelCanvas.ts similarity index 100% rename from packages/hardhat/test/CanvasOnchain.ts rename to packages/hardhat/test/PixelCanvas.ts From 3125de989c76557a8387193dd1b78605cb6f5826 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Wed, 11 Dec 2024 21:10:39 +0100 Subject: [PATCH 07/13] update the changes --- packages/hardhat/contracts/PixelCanvas.sol | 82 ++++++++++++---------- packages/hardhat/deploy/PixelCanvas.ts | 52 -------------- packages/hardhat/hardhat.config.ts | 3 +- 3 files changed, 45 insertions(+), 92 deletions(-) delete mode 100644 packages/hardhat/deploy/PixelCanvas.ts diff --git a/packages/hardhat/contracts/PixelCanvas.sol b/packages/hardhat/contracts/PixelCanvas.sol index 9679698..a019832 100644 --- a/packages/hardhat/contracts/PixelCanvas.sol +++ b/packages/hardhat/contracts/PixelCanvas.sol @@ -27,11 +27,13 @@ contract PixelCanvas is Ownable { uint256 timestamp; } - // 2D Mapping to store pixels - Pixel[CANVAS_WIDTH][CANVAS_HEIGHT] public canvas; + // Mapping to store modified pixels +mapping(uint256 => mapping(uint256 => Pixel)) public canvas; + // Events event PixelPlaced(address indexed author, uint256 x, uint256 y, Color color); + event Withdrawal(address indexed owner, uint256 amount); // Constructor to initialize default Buidlguidl Batch11 drawing constructor() Ownable(msg.sender){ @@ -45,22 +47,21 @@ contract PixelCanvas is Ownable { * This is a simplified representation and can be customized */ function initializeBuidlGuidlLogo() private { - // B letter representation - for (uint256 x = 10; x < 20; x++) { - for (uint256 y = 10; y < 50; y++) { - canvas[x][y] = Pixel({ - author: owner(), - color: Color.BLUE, - timestamp: block.timestamp - }); - } + for (uint256 x = 10; x < 20; x++) { + for (uint256 y = 10; y < 50; y++) { + canvas[x][y] = Pixel({ + author: msg.sender, + color: Color.BLUE, + timestamp: block.timestamp + }); } + } // 11 representation with some pixels for (uint256 x = 30; x < 40; x++) { for (uint256 y = 20; y < 30; y++) { canvas[x][y] = Pixel({ - author: owner(), + author: msg.sender, color: Color.GREEN, timestamp: block.timestamp }); @@ -69,7 +70,7 @@ contract PixelCanvas is Ownable { // Add some distinctive pixels to represent Buidlguidl spirit canvas[32][25] = Pixel({ - author: owner(), + author: msg.sender, color: Color.RED, timestamp: block.timestamp }); @@ -81,21 +82,19 @@ contract PixelCanvas is Ownable { * @param y Y-coordinate of the pixel * @param color Color of the pixel */ - function placePixel(uint256 x, uint256 y, Color color) external { - // Validate pixel coordinates - require(x < CANVAS_WIDTH, "X coordinate out of bounds"); - require(y < CANVAS_HEIGHT, "Y coordinate out of bounds"); + function placePixel(uint256 x, uint256 y, Color color) external { + require(x < CANVAS_WIDTH, "X coordinate out of bounds"); + require(y < CANVAS_HEIGHT, "Y coordinate out of bounds"); - // Update pixel - canvas[x][y] = Pixel({ - author: msg.sender, - color: color, - timestamp: block.timestamp - }); + canvas[x][y] = Pixel({ + author: msg.sender, + color: color, + timestamp: block.timestamp + }); + + emit PixelPlaced(msg.sender, x, y, color); +} - // Emit event - emit PixelPlaced(msg.sender, x, y, color); - } /** * @dev Get pixel information @@ -104,19 +103,26 @@ contract PixelCanvas is Ownable { * @return Pixel details */ function getPixel(uint256 x, uint256 y) external view returns (Pixel memory) { - require(x < CANVAS_WIDTH, "X coordinate out of bounds"); - require(y < CANVAS_HEIGHT, "Y coordinate out of bounds"); - return canvas[x][y]; - } + require(x < CANVAS_WIDTH, "X coordinate out of bounds"); + require(y < CANVAS_HEIGHT, "Y coordinate out of bounds"); + return canvas[x][y]; +} - - - /** - * @dev Get canvas snapshot (useful for viewing entire canvas) - * @return Array of pixels - */ - function getCanvasSnapshot() external view returns (Pixel[CANVAS_WIDTH][CANVAS_HEIGHT] memory) { - return canvas; + + function withdraw() external onlyOwner { + uint256 balance = address(this).balance; + require(balance > 0, "No funds to withdraw"); + + // Transfer the balance to the owner + payable(owner()).transfer(balance); + + // Emit withdrawal event + emit Withdrawal(owner(), balance); } + + // Fallback and receive functions to accept Ether + fallback() external payable {} + + receive() external payable {} } diff --git a/packages/hardhat/deploy/PixelCanvas.ts b/packages/hardhat/deploy/PixelCanvas.ts deleted file mode 100644 index e21f428..0000000 --- a/packages/hardhat/deploy/PixelCanvas.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { ethers, network, run } from "hardhat"; -import { ContractFactory } from "ethers"; - -async function main() { - // Get the account that will deploy the contract - const [deployer] = await ethers.getSigners(); - - console.log("Deploying PixelCanvas contract with the account:", deployer.address); - - // Check deployer's balance - const balance = await ethers.provider.getBalance(deployer.address); - console.log("Account balance:", ethers.formatEther(balance), "ETH"); - - // Get the contract factory for PixelCanvas - const PixelCanvasFactory: ContractFactory = await ethers.getContractFactory("PixelCanvas"); - - // Deploy the contract - const pixelCanvas = await PixelCanvasFactory.deploy(); - - // Wait for the contract to be deployed - await pixelCanvas.waitForDeployment(); - - // Get the deployed contract address - const contractAddress = await pixelCanvas.getAddress(); - - console.log("PixelCanvas deployed to:", contractAddress); - - // Verify the contract on Etherscan only on supported networks - if (network.name !== "hardhat" && network.name !== "localhost") { - console.log("Waiting for block confirmations..."); - await new Promise(resolve => setTimeout(resolve, 45000)); // 45 seconds - - try { - await run("verify:verify", { - address: contractAddress, - constructorArguments: [], - }); - console.log("Contract verified on Etherscan"); - } catch (error) { - console.error("Verification failed:", error); - } - } -} - -main() - .then(() => process.exit(0)) - .catch(error => { - console.error("Deployment error:", error); - process.exit(1); - }); - -export default main; diff --git a/packages/hardhat/hardhat.config.ts b/packages/hardhat/hardhat.config.ts index b66897f..ba28b3b 100644 --- a/packages/hardhat/hardhat.config.ts +++ b/packages/hardhat/hardhat.config.ts @@ -7,7 +7,6 @@ import "@typechain/hardhat"; import "hardhat-gas-reporter"; import "solidity-coverage"; import "@nomicfoundation/hardhat-verify"; -import "@nomicfoundation/hardhat-network-helpers"; import "hardhat-deploy"; import "hardhat-deploy-ethers"; @@ -55,7 +54,7 @@ const config: HardhatUserConfig = { accounts: [deployerPrivateKey], }, sepolia: { - url: `https://eth-sepolia.g.alchemy.com/v2/FIQ1qwifmra7ZqdkVHnZ2lHQAKG8j4Yd`, + url: `https://ethereum-sepolia.blockpi.network/v1/rpc/public`, accounts: [deployerPrivateKey], }, arbitrum: { From c3d0dd89567ab64f38f720959209fef9c6bb9951 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Thu, 12 Dec 2024 01:28:10 +0100 Subject: [PATCH 08/13] update --- packages/hardhat/test/PixelCanvas.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/hardhat/test/PixelCanvas.ts b/packages/hardhat/test/PixelCanvas.ts index 2ced047..b78bfca 100644 --- a/packages/hardhat/test/PixelCanvas.ts +++ b/packages/hardhat/test/PixelCanvas.ts @@ -71,13 +71,4 @@ describe("PixelCanvas", function () { expect(pixel.color).to.equal(color); }); }); - - describe("Canvas Snapshot", function () { - it("Should return full canvas snapshot", async function () { - const { Pixel } = await loadFixture(deployPixelCanvas); - const snapshot = await Pixel.getCanvasSnapshot(); - expect(snapshot.length).to.equal(64); - expect(snapshot[0].length).to.equal(64); - }); - }); }); From 39ebc794f6e75d44c3d8bb23619cbcf561d914f2 Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Fri, 13 Dec 2024 21:47:21 +0100 Subject: [PATCH 09/13] update the contract and the readme files --- package.json | 1 - packages/hardhat/Readme.md | 19 +++++++----- packages/hardhat/contracts/PixelCanvas.sol | 15 ++++----- .../hardhat/deploy/00_deploy_your_contract.ts | 31 +++++++++++++------ 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 39f78b3..44fdb6f 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ }, "packageManager": "yarn@3.2.3", "devDependencies": { - "@nomicfoundation/hardhat-network-helpers": "^1.0.12", "husky": "^9.1.6", "lint-staged": "^15.2.10" }, diff --git a/packages/hardhat/Readme.md b/packages/hardhat/Readme.md index 7d11b9e..da8bb4b 100644 --- a/packages/hardhat/Readme.md +++ b/packages/hardhat/Readme.md @@ -1,7 +1,7 @@ ## PixelCanvas: Decentralized Collaborative Pixel Art Smart Contract ### Contract Overview -A collaborative on-chain pixel art platform implemented as an Ethereum smart contract, enabling users to create and modify a shared 64x64 pixel canvas. +PixelCanvas is an Ethereum smart contract that enables collaborative pixel art creation on a fixed 64x64 canvas with a predefined color palette. ### Technical Specifications - **Blockchain**: Ethereum @@ -29,20 +29,23 @@ Allows user to place a single pixel Emits PixelPlaced event for tracking 2. Canvas Retrieval - getPixel(x, y): Retrieves individual pixel information -getCanvasSnapshot(): Returns entire canvas state +initializeBuidlGuidlLogo(): Sets initial canvas state with Batch11 logo + +3. Contract Management +withdraw(): Allows owner to withdraw contract balance +Accepts Ether via fallback() and receive() functions -3. Initialization +4. Initialization Test the PixelCanvas contract Includes default Buidlguidl Batch11 logo on contract deployment Demonstrates initial canvas state -Known Limitations - -Fixed 64x64 canvas size -Limited 8-color palette +Current Limitations +Fixed canvas size (64x64) No pixel modification after placement +Limited to 8 colors +Only contract owner can withdraw funds diff --git a/packages/hardhat/contracts/PixelCanvas.sol b/packages/hardhat/contracts/PixelCanvas.sol index a019832..e4b02d6 100644 --- a/packages/hardhat/contracts/PixelCanvas.sol +++ b/packages/hardhat/contracts/PixelCanvas.sol @@ -111,15 +111,16 @@ mapping(uint256 => mapping(uint256 => Pixel)) public canvas; function withdraw() external onlyOwner { - uint256 balance = address(this).balance; - require(balance > 0, "No funds to withdraw"); + uint256 balance = address(this).balance; + require(balance > 0, "No funds to withdraw"); - // Transfer the balance to the owner - payable(owner()).transfer(balance); + + (bool success, ) = payable(owner()).call{value: balance}(""); + require(success, "Transfer failed"); - // Emit withdrawal event - emit Withdrawal(owner(), balance); - } + + emit Withdrawal(owner(), balance); +} // Fallback and receive functions to accept Ether fallback() external payable {} diff --git a/packages/hardhat/deploy/00_deploy_your_contract.ts b/packages/hardhat/deploy/00_deploy_your_contract.ts index 1fc13e0..740675b 100644 --- a/packages/hardhat/deploy/00_deploy_your_contract.ts +++ b/packages/hardhat/deploy/00_deploy_your_contract.ts @@ -3,7 +3,7 @@ import { DeployFunction } from "hardhat-deploy/types"; import { Contract } from "ethers"; // Update with your Batch number -const BATCH_NUMBER = "11"; +// const BATCH_NUMBER = "11"; /** * Deploys a contract named "deployYourContract" using the deployer account and @@ -25,10 +25,13 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn const { deployer } = await hre.getNamedAccounts(); const { deploy } = hre.deployments; - await deploy("BatchRegistry", { + // await deploy("BatchRegistry", { + // from: deployer, + // // Contract constructor arguments + // args: [deployer, BATCH_NUMBER], + await deploy("PixelCanvas", { from: deployer, - // Contract constructor arguments - args: [deployer, BATCH_NUMBER], + args: [], log: true, // autoMine: can be passed to the deploy function to make the deployment process faster on local networks by // automatically mining the contract deployment transaction. There is no effect on live networks. @@ -36,17 +39,25 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn }); // Get the deployed contract to interact with it after deploying. - const batchRegistry = await hre.ethers.getContract("BatchRegistry", deployer); - console.log("\nBatchRegistry deployed to:", await batchRegistry.getAddress()); - console.log("Remember to update the allow list!\n"); + // const batchRegistry = await hre.ethers.getContract("BatchRegistry", deployer); + // console.log("\nBatchRegistry deployed to:", await batchRegistry.getAddress()); + // console.log("Remember to update the allow list!\n"); + + const pixelCanvas = await hre.ethers.getContract("PixelCanvas", deployer); + console.log("\nPixelCanvas deployed to:", await pixelCanvas.getAddress()); // The GraduationNFT contract is deployed on the BatchRegistry constructor. - const batchGraduationNFTAddress = await batchRegistry.batchGraduationNFT(); - console.log("BatchGraduation NFT deployed to:", batchGraduationNFTAddress, "\n"); + // const batchGraduationNFTAddress = await batchRegistry.batchGraduationNFT(); + // console.log("BatchGraduation NFT deployed to:", batchGraduationNFTAddress, "\n"); + + // Verify initial canvas state + const canvasWidth = await pixelCanvas.CANVAS_WIDTH(); + const canvasHeight = await pixelCanvas.CANVAS_HEIGHT(); + console.log(`Canvas dimensions: ${canvasWidth}x${canvasHeight}`); }; export default deployYourContract; // Tags are useful if you have multiple deploy files and only want to run one of them. // e.g. yarn deploy --tags YourContract -deployYourContract.tags = ["BatchRegistry"]; +deployYourContract.tags = ["PixelCanvas"]; From 890ec2f322c6e1e18599336cb92e5404341ccade Mon Sep 17 00:00:00 2001 From: Abidoyesimze Date: Mon, 16 Dec 2024 03:03:17 +0100 Subject: [PATCH 10/13] update the deploy scripts --- package.json | 1 - .../hardhat/deploy/00_deploy_your_contract.ts | 27 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 44fdb6f..a569f19 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "node": ">=18.18.0" }, "dependencies": { - "hardhat": "^2.22.17", "react-icons": "^5.3.0" } } diff --git a/packages/hardhat/deploy/00_deploy_your_contract.ts b/packages/hardhat/deploy/00_deploy_your_contract.ts index 740675b..95d52ab 100644 --- a/packages/hardhat/deploy/00_deploy_your_contract.ts +++ b/packages/hardhat/deploy/00_deploy_your_contract.ts @@ -3,7 +3,7 @@ import { DeployFunction } from "hardhat-deploy/types"; import { Contract } from "ethers"; // Update with your Batch number -// const BATCH_NUMBER = "11"; +const BATCH_NUMBER = "11"; /** * Deploys a contract named "deployYourContract" using the deployer account and @@ -25,13 +25,16 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn const { deployer } = await hre.getNamedAccounts(); const { deploy } = hre.deployments; - // await deploy("BatchRegistry", { - // from: deployer, - // // Contract constructor arguments - // args: [deployer, BATCH_NUMBER], + await deploy("BatchRegistry", { + from: deployer, + // Contract constructor arguments + args: [deployer, BATCH_NUMBER], + log: true, + }); + await deploy("PixelCanvas", { from: deployer, - args: [], + args: [deployer], // Added deployer as an argument similar to BatchRegistry log: true, // autoMine: can be passed to the deploy function to make the deployment process faster on local networks by // automatically mining the contract deployment transaction. There is no effect on live networks. @@ -39,16 +42,16 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn }); // Get the deployed contract to interact with it after deploying. - // const batchRegistry = await hre.ethers.getContract("BatchRegistry", deployer); - // console.log("\nBatchRegistry deployed to:", await batchRegistry.getAddress()); - // console.log("Remember to update the allow list!\n"); + const batchRegistry = await hre.ethers.getContract("BatchRegistry", deployer); + console.log("\nBatchRegistry deployed to:", await batchRegistry.getAddress()); + console.log("Remember to update the allow list!\n"); const pixelCanvas = await hre.ethers.getContract("PixelCanvas", deployer); console.log("\nPixelCanvas deployed to:", await pixelCanvas.getAddress()); // The GraduationNFT contract is deployed on the BatchRegistry constructor. - // const batchGraduationNFTAddress = await batchRegistry.batchGraduationNFT(); - // console.log("BatchGraduation NFT deployed to:", batchGraduationNFTAddress, "\n"); + const batchGraduationNFTAddress = await batchRegistry.batchGraduationNFT(); + console.log("BatchGraduation NFT deployed to:", batchGraduationNFTAddress, "\n"); // Verify initial canvas state const canvasWidth = await pixelCanvas.CANVAS_WIDTH(); @@ -60,4 +63,4 @@ export default deployYourContract; // Tags are useful if you have multiple deploy files and only want to run one of them. // e.g. yarn deploy --tags YourContract -deployYourContract.tags = ["PixelCanvas"]; +deployYourContract.tags = ["BatchRegistry", "PixelCanvas"]; From be9b9c80e094412c653bc6b28e9f5edfabfd5aa5 Mon Sep 17 00:00:00 2001 From: phipsae Date: Tue, 17 Dec 2024 10:16:08 +0100 Subject: [PATCH 11/13] remove argument for deploying pixelCanva in deployment script --- packages/hardhat/deploy/00_deploy_your_contract.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/hardhat/deploy/00_deploy_your_contract.ts b/packages/hardhat/deploy/00_deploy_your_contract.ts index 95d52ab..d9f8943 100644 --- a/packages/hardhat/deploy/00_deploy_your_contract.ts +++ b/packages/hardhat/deploy/00_deploy_your_contract.ts @@ -34,7 +34,6 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn await deploy("PixelCanvas", { from: deployer, - args: [deployer], // Added deployer as an argument similar to BatchRegistry log: true, // autoMine: can be passed to the deploy function to make the deployment process faster on local networks by // automatically mining the contract deployment transaction. There is no effect on live networks. From ac1616590906026fce4d933ae1097c5c81b34d4d Mon Sep 17 00:00:00 2001 From: phipsae Date: Tue, 17 Dec 2024 10:38:39 +0100 Subject: [PATCH 12/13] reset yarn.lock file --- yarn.lock | 198 ------------------------------------------------------ 1 file changed, 198 deletions(-) diff --git a/yarn.lock b/yarn.lock index 953c05a..e0de057 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1591,13 +1591,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr-darwin-arm64@npm:0.6.5": - version: 0.6.5 - resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.6.5" - checksum: fb4ec67761fa044156fac5bcc0540312e93c6b1a8086d9871fb88cfc880fcc0f8db58a9ae8cab0fb9b74b3cb54571053f7016039c4730f5186c088102f5a43c6 - languageName: node - linkType: hard - "@nomicfoundation/edr-darwin-x64@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-darwin-x64@npm:0.5.2" @@ -1605,13 +1598,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr-darwin-x64@npm:0.6.5": - version: 0.6.5 - resolution: "@nomicfoundation/edr-darwin-x64@npm:0.6.5" - checksum: 31444f48aee4e9c522da4dc799665b2d11432ca9aa27510161f1833b6f566714cecf8e99649d4209556a8346ab2ae521060ebd47ce21dad31a3f2a5d053607f0 - languageName: node - linkType: hard - "@nomicfoundation/edr-linux-arm64-gnu@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.5.2" @@ -1619,13 +1605,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr-linux-arm64-gnu@npm:0.6.5": - version: 0.6.5 - resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.6.5" - checksum: c7059092122dd58ad38f0fa2d577b9c822424f335c217bf11c01b05257f6de7788f9db15546d2f3cbb6ba3cf0a6062d113d093f0000fd2e13fc1e2033b39c4ad - languageName: node - linkType: hard - "@nomicfoundation/edr-linux-arm64-musl@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.5.2" @@ -1633,13 +1612,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr-linux-arm64-musl@npm:0.6.5": - version: 0.6.5 - resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.6.5" - checksum: 4d011d07c2d63f36bea81d935eb29a41815ddc2570e60c6b62668a96442b00e03285ed7fea2afd40554ef3f4a2f45b8123d8623f05862ecc6d9a4c7c606cdff4 - languageName: node - linkType: hard - "@nomicfoundation/edr-linux-x64-gnu@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.5.2" @@ -1647,13 +1619,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr-linux-x64-gnu@npm:0.6.5": - version: 0.6.5 - resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.6.5" - checksum: d20616245f643cc930c9b10e2969a550f39a506c5e77d69dca2ecfd23b23bfbae4fe63a7d8add355e2c79b3624c130270cbd24cba0ae42583b087019e7d2e3fa - languageName: node - linkType: hard - "@nomicfoundation/edr-linux-x64-musl@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.5.2" @@ -1661,13 +1626,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr-linux-x64-musl@npm:0.6.5": - version: 0.6.5 - resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.6.5" - checksum: 4e47f0e5b5176cc500c4a5beff526688a26be69d9ac2d6176c432a7ca51da4270f3b3f6738771a13c68149c66c94dcf4b719c33cf97edf96a15ddabbbc22ba1c - languageName: node - linkType: hard - "@nomicfoundation/edr-win32-x64-msvc@npm:0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.5.2" @@ -1675,13 +1633,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr-win32-x64-msvc@npm:0.6.5": - version: 0.6.5 - resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.6.5" - checksum: ae953433f5e45e96f0448219716b7e204fc18e8b0b7f840e4158daf26e75163de528cb74940ded25b24a1f23af82993ff312ddcde120d94acecaaaf7e87f7eb7 - languageName: node - linkType: hard - "@nomicfoundation/edr@npm:^0.5.2": version: 0.5.2 resolution: "@nomicfoundation/edr@npm:0.5.2" @@ -1697,21 +1648,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr@npm:^0.6.5": - version: 0.6.5 - resolution: "@nomicfoundation/edr@npm:0.6.5" - dependencies: - "@nomicfoundation/edr-darwin-arm64": 0.6.5 - "@nomicfoundation/edr-darwin-x64": 0.6.5 - "@nomicfoundation/edr-linux-arm64-gnu": 0.6.5 - "@nomicfoundation/edr-linux-arm64-musl": 0.6.5 - "@nomicfoundation/edr-linux-x64-gnu": 0.6.5 - "@nomicfoundation/edr-linux-x64-musl": 0.6.5 - "@nomicfoundation/edr-win32-x64-msvc": 0.6.5 - checksum: 5390da27b59836b64a4f5975e02dc803a70c5ba82dd29795366a79b62b53927f69d43aaf533ec0e5f56a613c29c5edea4b188059d80caf51db9cd7bd9da9fb0a - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-common@npm:4.0.4": version: 4.0.4 resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.4" @@ -1803,17 +1739,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/hardhat-network-helpers@npm:^1.0.12": - version: 1.0.12 - resolution: "@nomicfoundation/hardhat-network-helpers@npm:1.0.12" - dependencies: - ethereumjs-util: ^7.1.4 - peerDependencies: - hardhat: ^2.9.5 - checksum: 7e1b91789dd4e73464b4eec919b1e67c6d482dd7534f4f7cae73fb5bdddd69f2a47143754b34385b098a1df0f4875cd4d2e1109fc3d847db76f4b0a9a44bd959 - languageName: node - linkType: hard - "@nomicfoundation/hardhat-verify@npm:^2.0.10": version: 2.0.10 resolution: "@nomicfoundation/hardhat-verify@npm:2.0.10" @@ -5047,15 +4972,6 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^4.0.0": - version: 4.0.1 - resolution: "chokidar@npm:4.0.1" - dependencies: - readdirp: ^4.0.1 - checksum: 193da9786b0422a895d59c7552195d15c6c636e6a2293ae43d09e34e243e24ccd02d693f007c767846a65abbeae5fea6bfacb8fc2ddec4ea4d397620d552010d - languageName: node - linkType: hard - "chownr@npm:^1.1.4": version: 1.1.4 resolution: "chownr@npm:1.1.4" @@ -7222,18 +7138,6 @@ __metadata: languageName: node linkType: hard -"fdir@npm:^6.4.2": - version: 6.4.2 - resolution: "fdir@npm:6.4.2" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 517ad31c495f1c0778238eef574a7818788efaaf2ce1969ffa18c70793e2951a9763dfa2e6720b8fcef615e602a3cbb47f9b8aea9da0b02147579ab36043f22f - languageName: node - linkType: hard - "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -8102,68 +8006,6 @@ __metadata: languageName: node linkType: hard -"hardhat@npm:^2.22.17": - version: 2.22.17 - resolution: "hardhat@npm:2.22.17" - dependencies: - "@ethersproject/abi": ^5.1.2 - "@metamask/eth-sig-util": ^4.0.0 - "@nomicfoundation/edr": ^0.6.5 - "@nomicfoundation/ethereumjs-common": 4.0.4 - "@nomicfoundation/ethereumjs-tx": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - "@nomicfoundation/solidity-analyzer": ^0.1.0 - "@sentry/node": ^5.18.1 - "@types/bn.js": ^5.1.0 - "@types/lru-cache": ^5.1.0 - adm-zip: ^0.4.16 - aggregate-error: ^3.0.0 - ansi-escapes: ^4.3.0 - boxen: ^5.1.2 - chokidar: ^4.0.0 - ci-info: ^2.0.0 - debug: ^4.1.1 - enquirer: ^2.3.0 - env-paths: ^2.2.0 - ethereum-cryptography: ^1.0.3 - ethereumjs-abi: ^0.6.8 - find-up: ^5.0.0 - fp-ts: 1.19.3 - fs-extra: ^7.0.1 - immutable: ^4.0.0-rc.12 - io-ts: 1.10.4 - json-stream-stringify: ^3.1.4 - keccak: ^3.0.2 - lodash: ^4.17.11 - mnemonist: ^0.38.0 - mocha: ^10.0.0 - p-map: ^4.0.0 - picocolors: ^1.1.0 - raw-body: ^2.4.1 - resolve: 1.17.0 - semver: ^6.3.0 - solc: 0.8.26 - source-map-support: ^0.5.13 - stacktrace-parser: ^0.1.10 - tinyglobby: ^0.2.6 - tsort: 0.0.1 - undici: ^5.14.0 - uuid: ^8.3.2 - ws: ^7.4.6 - peerDependencies: - ts-node: "*" - typescript: "*" - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true - bin: - hardhat: internal/cli/bootstrap.js - checksum: 52fe0b846c6e5808adf85c7704dfb13bfd22368f54b9ade3ba7719e60ea725a6558715f79e4eb92071ef71d1e66bdd02ff0138f71aedf3fea77784ed5ae11809 - languageName: node - linkType: hard - "has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": version: 1.0.2 resolution: "has-bigints@npm:1.0.2" @@ -9148,13 +8990,6 @@ __metadata: languageName: node linkType: hard -"json-stream-stringify@npm:^3.1.4": - version: 3.1.6 - resolution: "json-stream-stringify@npm:3.1.6" - checksum: ce873e09fe18461960b7536f63e2f913a2cb242819513856ed1af58989d41846976e7177cb1fe3c835220023aa01e534d56b6d5c3290a5b23793a6f4cb93785e - languageName: node - linkType: hard - "json5@npm:^1.0.2": version: 1.0.2 resolution: "json5@npm:1.0.2" @@ -11009,13 +10844,6 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.1.0": - version: 1.1.1 - resolution: "picocolors@npm:1.1.1" - checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 - languageName: node - linkType: hard - "picomatch@npm:^2.0.4, picomatch@npm:^2.0.7, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" @@ -11023,13 +10851,6 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.2": - version: 4.0.2 - resolution: "picomatch@npm:4.0.2" - checksum: a7a5188c954f82c6585720e9143297ccd0e35ad8072231608086ca950bee672d51b0ef676254af0788205e59bd4e4deb4e7708769226bed725bf13370a7d1464 - languageName: node - linkType: hard - "pidtree@npm:~0.6.0": version: 0.6.0 resolution: "pidtree@npm:0.6.0" @@ -11722,13 +11543,6 @@ __metadata: languageName: node linkType: hard -"readdirp@npm:^4.0.1": - version: 4.0.2 - resolution: "readdirp@npm:4.0.2" - checksum: 309376e717f94fb7eb61bec21e2603243a9e2420cd2e9bf94ddf026aefea0d7377ed1a62f016d33265682e44908049a55c3cfc2307450a1421654ea008489b39 - languageName: node - linkType: hard - "readdirp@npm:~3.3.0": version: 3.3.0 resolution: "readdirp@npm:3.3.0" @@ -12127,8 +11941,6 @@ __metadata: version: 0.0.0-use.local resolution: "se-2@workspace:." dependencies: - "@nomicfoundation/hardhat-network-helpers": ^1.0.12 - hardhat: ^2.22.17 husky: ^9.1.6 lint-staged: ^15.2.10 react-icons: ^5.3.0 @@ -13058,16 +12870,6 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.6": - version: 0.2.10 - resolution: "tinyglobby@npm:0.2.10" - dependencies: - fdir: ^6.4.2 - picomatch: ^4.0.2 - checksum: 7e2ffe262ebc149036bdef37c56b32d02d52cf09efa7d43dbdab2ea3c12844a4da881058835ce4c74d1891190e5ad5ec5133560a11ec8314849b68ad0d99d3f4 - languageName: node - linkType: hard - "tmp@npm:0.0.33": version: 0.0.33 resolution: "tmp@npm:0.0.33" From 0fad4a1819bfc4763458747d152653dff8deea58 Mon Sep 17 00:00:00 2001 From: phipsae Date: Tue, 17 Dec 2024 11:09:22 +0100 Subject: [PATCH 13/13] add PixelCanvas contract abi to externalContracts --- .../nextjs/contracts/externalContracts.ts | 736 ++++++++++++++++++ 1 file changed, 736 insertions(+) diff --git a/packages/nextjs/contracts/externalContracts.ts b/packages/nextjs/contracts/externalContracts.ts index 1af01ae..edf87fd 100644 --- a/packages/nextjs/contracts/externalContracts.ts +++ b/packages/nextjs/contracts/externalContracts.ts @@ -347,6 +347,742 @@ const externalContracts = { transferOwnership: "@openzeppelin/contracts/access/Ownable.sol", }, }, + BatchGraduationNFT: { + address: "0x72A22AE8dDabA9D316Ffed3d5C0A46F7Ea8Aa809", + abi: [ + { + inputs: [ + { + internalType: "address", + name: "_batchRegistry", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "NoMetadataSet", + type: "error", + }, + { + inputs: [], + name: "UnauthorizedCaller", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "approved", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: false, + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "builder", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "metadataContract", + type: "address", + }, + ], + name: "MetadataSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "approve", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "batchRegistry", + outputs: [ + { + internalType: "contract IBatchRegistry", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "getApproved", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "operator", + type: "address", + }, + ], + name: "isApprovedForAll", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "builder", + type: "address", + }, + ], + name: "mint", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "ownerOf", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + { + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "metadataContract", + type: "address", + }, + ], + name: "setMetadataContract", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceId", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + name: "tokenToMetadataContract", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "tokenURI", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "yourGraduationContractAddress", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + ], + }, + PixelCanvas: { + address: "0x54c92BB9f6c3d3416c22070bcD5678cfF57784B4", + abi: [ + { + inputs: [], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "OwnableInvalidOwner", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "OwnableUnauthorizedAccount", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "author", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "x", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "y", + type: "uint256", + }, + { + indexed: false, + internalType: "enum PixelCanvas.Color", + name: "color", + type: "uint8", + }, + ], + name: "PixelPlaced", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Withdrawal", + type: "event", + }, + { + stateMutability: "payable", + type: "fallback", + }, + { + inputs: [], + name: "CANVAS_HEIGHT", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CANVAS_WIDTH", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + name: "canvas", + outputs: [ + { + internalType: "address", + name: "author", + type: "address", + }, + { + internalType: "enum PixelCanvas.Color", + name: "color", + type: "uint8", + }, + { + internalType: "uint256", + name: "timestamp", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "x", + type: "uint256", + }, + { + internalType: "uint256", + name: "y", + type: "uint256", + }, + ], + name: "getPixel", + outputs: [ + { + components: [ + { + internalType: "address", + name: "author", + type: "address", + }, + { + internalType: "enum PixelCanvas.Color", + name: "color", + type: "uint8", + }, + { + internalType: "uint256", + name: "timestamp", + type: "uint256", + }, + ], + internalType: "struct PixelCanvas.Pixel", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "x", + type: "uint256", + }, + { + internalType: "uint256", + name: "y", + type: "uint256", + }, + { + internalType: "enum PixelCanvas.Color", + name: "color", + type: "uint8", + }, + ], + name: "placePixel", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + stateMutability: "payable", + type: "receive", + }, + ], + inheritedFunctions: { + owner: "@openzeppelin/contracts/access/Ownable.sol", + renounceOwnership: "@openzeppelin/contracts/access/Ownable.sol", + transferOwnership: "@openzeppelin/contracts/access/Ownable.sol", + }, + }, }, } as const;