Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
url = https://github.com/transmissions11/solmate
[submodule "icy-btc/lib/solady"]
path = icy-btc/lib/solady
url = https://github.com/vectorized/solady
url = https://github.com/vectorized/solady
19 changes: 19 additions & 0 deletions memo-nft/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# EditorConfig http://EditorConfig.org

# top-most EditorConfig file
root = true

# All files
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.sol]
indent_size = 4

[*.tree]
indent_size = 1
4 changes: 4 additions & 0 deletions memo-nft/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ETHERSCAN_API_KEY=
BASE_SEPOLIA_RPC=
BASE_RPC=
WALLET_PRIVATE_KEY=
20 changes: 20 additions & 0 deletions memo-nft/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# directories
cache
coverage
node_modules
out

# files
*.env
*.log
.DS_Store
.pnp.*
lcov.info
package-lock.json
pnpm-lock.yaml
yarn.lock

# broadcasts
# !broadcast
# broadcast/*
# broadcast/*/31337/
17 changes: 17 additions & 0 deletions memo-nft/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# directories
broadcast
cache
coverage
node_modules
out

# files
*.env
*.log
.DS_Store
.pnp.*
bun.lockb
lcov.info
package-lock.json
pnpm-lock.yaml
yarn.lock
3 changes: 3 additions & 0 deletions memo-nft/.prettierrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
printWidth: 120
proseWrap: "always"
trailingComma: "all"
14 changes: 14 additions & 0 deletions memo-nft/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "solhint:recommended",
"rules": {
"code-complexity": ["error", 8],
"compiler-version": ["error", ">=0.8.28"],
"func-name-mixedcase": "off",
"func-visibility": ["error", { "ignoreConstructors": true }],
"max-line-length": ["error", 120],
"named-parameters-mapping": "warn",
"no-console": "off",
"not-rely-on-time": "off",
"one-contract-per-file": "off"
}
}
57 changes: 57 additions & 0 deletions memo-nft/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# This repo is an implementation of the Memo NFT contract.

## Contract

- [DwarvesMemo.sol](./src/DwarvesMemo.sol)

## Overview
We're developing an upgradable ERC1155 smart contract that integrates with Arweave for storing NFT metadata. This contract will allow the owner to create new NFT types mapped to Arweave transaction IDs, while enabling anyone to mint tokens of these established types.

### Features
- Upgradable
- ERC1155
- Integrates with Arweave
- ...

### Smart Contract Functionalities
1. `createTokenType (onlyOwner)` -> Maps a new NFT ID to an Arweave transaction ID
2. `updateTokenType (onlyOwner)` -> Updates the Arweave transaction ID for an existing NFT ID
3. `mintNFT (public)` -> Mints a new NFT token
4. `readNFT (public)` -> Returns the Arweave gateway URL for the token's metadata
5. `getUniqueMinterCount (public)` -> Returns the total number of unique addresses that have minted at least one NFT

## Usage
### Prerequisites
- Install `Bun` CLI (https://bun.sh/docs/installation)
- Install `Foundry` (https://getfoundry.sh/)
- Install dependencies: `bun install`
- Update `.env` file with your own values (see `.env.example`)

### Available commands
1. Build commands
- `bun run build` -> Build the contract (always run this before deploying)

2. Deploy commands
- `bun run deploy:testnet` -> Deploy to Base Sepolia
- `bun run deploy:mainnet` -> Deploy to Base Mainnet

3. Upgrade commands
- `bun run upgrade:testnet` -> Upgrade on Base Sepolia
- `bun run upgrade:mainnet` -> Upgrade on Base Mainnet

4. Other commands
- `bun run test` -> Run tests
- `bun run lint` -> Run lint
- `bun run format` -> Format code

## Latest Deployments
1. Testnet
- [Proxy](https://sepolia.basescan.org/address/0xb1e052156676750D193D800D7D91eA0C7cEeAdF0)

2. Mainnet
- ...

## Resources
- [Arweave Integration](https://academy.developerdao.com/tracks/arweave-101/2)
- [Foundry Book](https://book.getfoundry.sh/)
- [Foundry Template](https://github.com/PaulRBerg/foundry-template)
190 changes: 190 additions & 0 deletions memo-nft/broadcast/DeployScript.s.sol/8453/run-1742959126.json

Large diffs are not rendered by default.

190 changes: 190 additions & 0 deletions memo-nft/broadcast/DeployScript.s.sol/8453/run-latest.json

Large diffs are not rendered by default.

Binary file added memo-nft/bun.lockb
Binary file not shown.
37 changes: 37 additions & 0 deletions memo-nft/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Full reference https://github.com/foundry-rs/foundry/tree/master/crates/config

[profile.default]
auto_detect_solc = false
block_timestamp = 1_738_368_000 # Feb 1, 2025 at 00:00 GMT
bytecode_hash = "none"
fuzz = { runs = 1_000 }
gas_reports = ["*"]
optimizer = true
optimizer_runs = 10_000
out = "out"
script = "script"
solc = "0.8.29"
src = "src"
test = "tests"

[profile.ci]
fuzz = { runs = 10_000 }
verbosity = 4

[rpc_endpoints]
base = "${BASE_RPC}"
base_sepolia = "${BASE_SEPOLIA_RPC}"

[etherscan]
base = { key = "${BASESCAN_API_KEY}" }
base_sepolia = { key = "${BASESCAN_API_KEY}" }

[fmt]
bracket_spacing = true
int_types = "long"
line_length = 120
multiline_func_header = "all"
number_underscore = "thousands"
quote_style = "double"
tab_width = 4
wrap_comments = true
31 changes: 31 additions & 0 deletions memo-nft/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@df/memo-nft",
"description": "Memo NFT",
"version": "1.0.0",
"dependencies": {
"@openzeppelin/contracts": "^5.2.0",
"@openzeppelin/foundry-upgrades": "OpenZeppelin/openzeppelin-foundry-upgrades",
"openzeppelin-solidity": "OpenZeppelin/openzeppelin-contracts-upgradeable"
},
"devDependencies": {
"forge-std": "github:foundry-rs/forge-std#v1.8.1",
"prettier": "^3.0.0",
"solhint": "^3.6.2"
},
"private": true,
"scripts": {
"clean": "rm -rf cache out",
"build": "forge build",
"lint": "bun run lint:sol && bun run prettier:check",
"lint:sol": "forge fmt --check && bun solhint \"{script,src,tests}/**/*.sol\"",
"prettier:check": "prettier --check \"**/*.{json,md,yml}\" --ignore-path \".prettierignore\"",
"prettier:write": "prettier --write \"**/*.{json,md,yml}\" --ignore-path \".prettierignore\"",
"test": "forge test -vvv",
"test:coverage": "forge coverage",
"test:coverage:report": "forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage",
"deploy:testnet": "forge script script/DeployScript.s.sol:DeployScript --rpc-url base_sepolia --private-key $(grep WALLET_PRIVATE_KEY .env | cut -d '=' -f2) --broadcast --verify -vvvv",
"upgrade:testnet": "forge script script/UpgradeScript.s.sol:UpgradeScript --rpc-url base_sepolia --private-key $(grep WALLET_PRIVATE_KEY .env | cut -d '=' -f2) --broadcast --verify -vvvv",
"deploy:mainnet": "forge script script/DeployScript.s.sol:DeployScript --rpc-url base --private-key $(grep WALLET_PRIVATE_KEY .env | cut -d '=' -f2) --broadcast --verify -vvvv",
"upgrade:mainnet": "forge script script/UpgradeScript.s.sol:UpgradeScript --rpc-url base --private-key $(grep WALLET_PRIVATE_KEY .env | cut -d '=' -f2) --broadcast --verify -vvvv"
}
}
3 changes: 3 additions & 0 deletions memo-nft/remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/
forge-std/=node_modules/forge-std/
@openzeppelin/contracts-upgradeable/=node_modules/openzeppelin-solidity/contracts
27 changes: 27 additions & 0 deletions memo-nft/script/DeployScript.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;

import "forge-std/src/Script.sol";
import "../src/DwarvesMemo.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

// Notes:
// Replace `INITIAL_URI` with the initial URI for the NFT metadata
contract DeployScript is Script {
function run() external {
vm.startBroadcast();

string memory INITIAL_URI = "https://example.com/metadata/{id}.json";

// Deploy implementation contract
DwarvesMemo implementation = new DwarvesMemo();

// Deploy proxy contract
new ERC1967Proxy(
address(implementation),
abi.encodeWithSelector(DwarvesMemo.initialize.selector, INITIAL_URI)
);

vm.stopBroadcast();
}
}
29 changes: 29 additions & 0 deletions memo-nft/script/UpgradeScript.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;

import "forge-std/src/Script.sol";
import "../src/DwarvesMemo.sol";

// Notes:
// 1. Replace `PROXY_ADDRESS` with the address of the proxy contract you want to upgrade before running the script
// 2. Replace `INITIAL_URI` with the initial URI for the NFT metadata
contract UpgradeScript is Script {
function run() external {
vm.startBroadcast();

// TODO: Replace with the address of the latest proxy contract you want to upgrade
address PROXY_ADDRESS = 0x07f3ed54e0b2D07cC522c4FC12EbA80E6D3A8DeB;

// Deploy the new implementation contract
DwarvesMemo newImplementation = new DwarvesMemo();

DwarvesMemo proxy = DwarvesMemo(address(PROXY_ADDRESS));
bytes memory data = "";
proxy.upgradeToAndCall(
address(newImplementation),
data
);

vm.stopBroadcast();
}
}
Loading