Creating a Set Contract
December 3, 2024
This guide walks through creating a simple dice contract that demonstrates basic set functionality.
Initialize the Project
First, create a new Forge project and install dependencies:
forge init dice
cd dice
forge install everythingfun/v1-periphery
Write the Contract
Create a new file src/Dice.sol
with the following code:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {SetBase} from "v1-periphery/sets/SetBase.sol";
import {ObjectMeta} from "v1-periphery/interfaces/core/types/ObjectMeta.sol";
contract Dice is SetBase {
error ObjectIdOverflow();
error InvalidFaceValue();
uint64 private _nextId;
constructor(uint64 kind) SetBase(kind) {
_nextId = 1;
}
function mint() external returns (uint64) {
uint256 randomFace = _random();
return _mint(randomFace);
}
function mint(uint256 faceValue) external returns (uint64) {
return _mint(faceValue);
}
function roll(uint64 id) external returns (uint256) {
uint256 newFaceValue = _random();
bytes32[] memory elems = new bytes32[](1);
elems[0] = bytes32(newFaceValue);
ObjectMeta memory meta = _update(id, elems);
emit Updated(id, meta, elems);
emit URI(uri(id), id);
return newFaceValue;
}
function _mint(uint256 faceValue) internal returns (uint64) {
if (faceValue < 1 || faceValue > 6) revert InvalidFaceValue();
uint64 id = _nextId++;
if (id >= type(uint64).max) revert ObjectIdOverflow();
bytes32[] memory elems = new bytes32[](1);
elems[0] = bytes32(faceValue);
ObjectMeta memory meta = _create(id, elems);
emit Created(id, meta, elems, msg.sender);
emit TransferSingle(msg.sender, address(0), msg.sender, id, 1);
return id;
}
function _random() private view returns (uint256) {
return uint256(blockhash(block.number - 1)) % 6 + 1;
}
}
Deploy and Register
- Build the contract:
forge build
- Deploy the contract (you'll need to add your specific deployment parameters):
forge create src/Dice.sol:Dice --constructor-args <KIND>
- Register your contract with the registry:
cast send sreg.0xpre.eth "register()(uint64)" --private-key <YOUR_KEY>
Interacting with the Contract
Minting Dice
To mint a new die with a random value:
cast send <CONTRACT_ADDRESS> "mint()" --private-key <YOUR_KEY>
Or mint with a specific face value (1-6):
cast send <CONTRACT_ADDRESS> "mint(uint256)" 3 --private-key <YOUR_KEY>
Rolling Dice
To roll an existing die:
cast send <CONTRACT_ADDRESS> "roll(uint64)" <TOKEN_ID> --private-key <YOUR_KEY>
Advanced Operations
For more complex operations like upgrading or transferring dice, use these commands:
# Transfer a die to another address
cast send <CONTRACT_ADDRESS> "transfer(uint64,address)" <TOKEN_ID> <RECIPIENT>
# Upgrade a die
cast send <CONTRACT_ADDRESS> "upgrade(uint64,uint32,uint32)" <TOKEN_ID> <NEW_LEVEL> <NEW_XP>
Remember to replace placeholder values (enclosed in <>
) with actual parameters when using these commands.