Skip to content

Commit

Permalink
CanvasOnChain: Show the canvas with all the pixel placements #29
Browse files Browse the repository at this point in the history
  • Loading branch information
melanke committed Dec 15, 2024
1 parent 3ad0f57 commit acf7055
Show file tree
Hide file tree
Showing 5 changed files with 1,194 additions and 137 deletions.
333 changes: 211 additions & 122 deletions packages/hardhat/contracts/PixelCanvas.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,126 +4,215 @@ 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;
}

// 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){

// 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 {
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: msg.sender,
color: Color.GREEN,
timestamp: block.timestamp
});
}
}

// Add some distinctive pixels to represent Buidlguidl spirit
canvas[32][25] = Pixel({
author: msg.sender,
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 {
require(x < CANVAS_WIDTH, "X coordinate out of bounds");
require(y < CANVAS_HEIGHT, "Y coordinate out of bounds");

canvas[x][y] = Pixel({
author: msg.sender,
color: color,
timestamp: block.timestamp
});

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];
}



function withdraw() external onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, "No funds to withdraw");


(bool success, ) = payable(owner()).call{value: balance}("");
require(success, "Transfer failed");


emit Withdrawal(owner(), balance);
}

// Fallback and receive functions to accept Ether
fallback() external payable {}

receive() external payable {}
// 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;
}

// 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) {
// 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 {
uint256 startx = 28;
uint256 starty = 28;

canvas[startx][starty + 1] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty + 1] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty + 2] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty + 3] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty + 4] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx][starty + 4] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});
canvas[startx + 2][starty + 4] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

startx = 32;

canvas[startx][starty + 1] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty + 1] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty + 2] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty + 3] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx + 1][starty + 4] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});

canvas[startx][starty + 4] = Pixel({
author: msg.sender,
color: Color.BLACK,
timestamp: block.timestamp
});
canvas[startx + 2][starty + 4] = Pixel({
author: msg.sender,
color: Color.BLACK,
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 {
require(x < CANVAS_WIDTH, "X coordinate out of bounds");
require(y < CANVAS_HEIGHT, "Y coordinate out of bounds");

canvas[x][y] = Pixel({
author: msg.sender,
color: color,
timestamp: block.timestamp
});

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 Get the entire canvas as a 2D array of pixels
* @return Array of arrays containing all pixels
*/
function getFullCanvas() external view returns (Pixel[][] memory) {
Pixel[][] memory fullCanvas = new Pixel[][](CANVAS_WIDTH);

for (uint256 x = 0; x < CANVAS_WIDTH; x++) {
fullCanvas[x] = new Pixel[](CANVAS_HEIGHT);
for (uint256 y = 0; y < CANVAS_HEIGHT; y++) {
fullCanvas[x][y] = canvas[x][y];
}
}

return fullCanvas;
}

function withdraw() external onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, "No funds to withdraw");

(bool success, ) = payable(owner()).call{ value: balance }("");
require(success, "Transfer failed");

emit Withdrawal(owner(), balance);
}

// Fallback and receive functions to accept Ether
fallback() external payable {}

receive() external payable {}
}
34 changes: 20 additions & 14 deletions packages/hardhat/deploy/00_deploy_your_contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -25,31 +25,37 @@ 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("PixelCanvas", {
await deploy("BatchRegistry", {
from: deployer,
args: [],
// Contract constructor arguments
args: [deployer, BATCH_NUMBER],
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.
autoMine: true,
});

// Get the deployed contract to interact with it after deploying.
// const batchRegistry = await hre.ethers.getContract<Contract>("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<Contract>("BatchRegistry", deployer);
console.log("\nBatchRegistry deployed to:", await batchRegistry.getAddress());
console.log("Remember to update the allow list!\n");

// The GraduationNFT contract is deployed on the BatchRegistry constructor.
const batchGraduationNFTAddress = await batchRegistry.batchGraduationNFT();
console.log("BatchGraduation NFT deployed to:", batchGraduationNFTAddress, "\n");

await deploy("PixelCanvas", {
from: deployer,
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.
autoMine: true,
});

const pixelCanvas = await hre.ethers.getContract<Contract>("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");

// Verify initial canvas state
const canvasWidth = await pixelCanvas.CANVAS_WIDTH();
const canvasHeight = await pixelCanvas.CANVAS_HEIGHT();
Expand Down
Loading

0 comments on commit acf7055

Please sign in to comment.