Skip to content

Commit

Permalink
Merge pull request #18 from blocto/feature/spotlight-root-ip-collection
Browse files Browse the repository at this point in the history
Spotlight root ip collection
  • Loading branch information
scottphc authored Jan 24, 2025
2 parents 618e217 + 74f1854 commit b5781c2
Show file tree
Hide file tree
Showing 3 changed files with 248 additions and 0 deletions.
23 changes: 23 additions & 0 deletions script/DeployIPRootCollectionAndMint.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

import "../lib/forge-std/src/Script.sol";
import {SpotlightRootIPCollection} from "../src/spotlight-root-ip-collection/SpotlightRootIPCollection.sol";

/* Deploy and verify with the following command:
forge script script/DeployIPRootCollectionAndMint.s.sol:Deploy --broadcast \
--chain-id 1516 \
--rpc-url https://odyssey.storyrpc.io \
--verify \
--verifier blockscout \
--verifier-url 'https://odyssey.storyscan.xyz/api/'
*/

contract Deploy is Script {
function run() public {
vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
SpotlightRootIPCollection ipCollection = new SpotlightRootIPCollection();
ipCollection.mint();
vm.stopBroadcast();
}
}
68 changes: 68 additions & 0 deletions src/spotlight-root-ip-collection/SpotlightRootIPCollection.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

contract SpotlightRootIPCollection is ERC721, Ownable {
using Strings for uint256;

bool private _isTransferEnabled = false;

uint256 private _nextTokenId;
string private _tokenURI = "ipfs://bafkreidsyc4pkxkk7io56uf5hhnvkx2n6ukua4xjg42dsv5n7y2hbb3h3u";

modifier onlyTransferEnabled() {
_checkTransferEnabled();
_;
}

constructor() ERC721("Spotlight Root IP", "SPRIP") Ownable(msg.sender) {}

function totalSupply() external view returns (uint256) {
return _nextTokenId;
}

function tokenURI(uint256 tokenId) public view override returns (string memory) {
_requireOwned(tokenId);
return _tokenURI;
}

function setTokenURI(string memory tokenURI_) public onlyOwner {
_tokenURI = tokenURI_;
}

function mint() public onlyOwner returns (uint256) {
uint256 tokenId = _nextTokenId;
_mint(msg.sender, tokenId);
_nextTokenId = _nextTokenId + 1;
return tokenId;
}

function isTransferEnabled() public view returns (bool) {
return _isTransferEnabled;
}

function _checkTransferEnabled() private view {
if (isTransferEnabled() != true) {
revert("SpotlightRootIPCollection: transfer is disabled");
}
}

function setTransferEnabled(bool enabled) public onlyOwner {
_isTransferEnabled = enabled;
}

function transferFrom(address from, address to, uint256 tokenId) public override onlyTransferEnabled {
super.transferFrom(from, to, tokenId);
}

function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data)
public
override
onlyTransferEnabled
{
super.safeTransferFrom(from, to, tokenId, data);
}
}
157 changes: 157 additions & 0 deletions test/SpotlightRootIPCollectionTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

import "../lib/forge-std/src/Test.sol";
import {SpotlightRootIPCollection} from "../src/spotlight-root-ip-collection/SpotlightRootIPCollection.sol";

abstract contract OwnableError {
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
}

contract SpotlightRootIPCollectionTest is Test {
address private _ownerAddr;

SpotlightRootIPCollection private _spotlightRootIPCollection;
address private _spotlightRootIPCollectionAddr;

string private newTokenURI = "https://example.com/new-token/";

function setUp() public {
_ownerAddr = makeAddr("owner");
vm.startPrank(_ownerAddr);
_spotlightRootIPCollection = new SpotlightRootIPCollection();
_spotlightRootIPCollectionAddr = address(_spotlightRootIPCollection);
vm.stopPrank();
}

function test_constructor() public view {
assertEq(_spotlightRootIPCollection.owner(), _ownerAddr);
assertEq(_spotlightRootIPCollection.totalSupply(), 0);
assertEq(_spotlightRootIPCollection.isTransferEnabled(), false);
assertEq(_spotlightRootIPCollection.name(), "Spotlight Root IP");
assertEq(_spotlightRootIPCollection.symbol(), "SPRIP");
}

function test_notOownerMint() public {
address receiver = makeAddr("receiver");

vm.startPrank(receiver);
vm.expectRevert();
_spotlightRootIPCollection.mint();
vm.stopPrank();
}

function test_mint() public {
vm.startPrank(_ownerAddr);
uint256 tokenId = _spotlightRootIPCollection.mint();
vm.stopPrank();

assertEq(_spotlightRootIPCollection.totalSupply(), 1);
assertEq(_spotlightRootIPCollection.ownerOf(tokenId), _ownerAddr);
assertEq(
_spotlightRootIPCollection.tokenURI(tokenId),
"ipfs://bafkreidsyc4pkxkk7io56uf5hhnvkx2n6ukua4xjg42dsv5n7y2hbb3h3u"
);
}

function test_notOwnerSetTransferEnabled() public {
address notOwner = makeAddr("notOwner");
vm.startPrank(notOwner);
vm.expectRevert();
_spotlightRootIPCollection.setTransferEnabled(true);
vm.stopPrank();
}

function test_setTransferEnabled() public {
vm.startPrank(_ownerAddr);
_spotlightRootIPCollection.setTransferEnabled(true);
assert(_spotlightRootIPCollection.isTransferEnabled());
_spotlightRootIPCollection.setTransferEnabled(false);
assert(!_spotlightRootIPCollection.isTransferEnabled());
vm.stopPrank();
}

function test_notOwnerSetTokenURI() public {
address notOwner = makeAddr("notOwner");
vm.startPrank(notOwner);
vm.expectRevert();
_spotlightRootIPCollection.setTokenURI(newTokenURI);
vm.stopPrank();
}

function test_setTokenURI() public {
vm.startPrank(_ownerAddr);
uint256 tokenId = _spotlightRootIPCollection.mint();
_spotlightRootIPCollection.setTokenURI(newTokenURI);
vm.stopPrank();

assertEq(_spotlightRootIPCollection.tokenURI(tokenId), newTokenURI);
}

function test_transferFromBeforeEnabled() public {
address receiver = makeAddr("receiver");

vm.startPrank(_ownerAddr);
uint256 tokenId = _spotlightRootIPCollection.mint();
vm.expectRevert("SpotlightRootIPCollection: transfer is disabled");
_spotlightRootIPCollection.transferFrom(_ownerAddr, receiver, tokenId);
vm.stopPrank();
}

function test_safeTransferFromBeforeEnabled() public {
address receiver = makeAddr("receiver");

vm.startPrank(_ownerAddr);
uint256 tokenId = _spotlightRootIPCollection.mint();
vm.expectRevert("SpotlightRootIPCollection: transfer is disabled");
_spotlightRootIPCollection.safeTransferFrom(_ownerAddr, receiver, tokenId);
vm.stopPrank();
}

function test_safeTransferFromWithDataBeforeEnabled() public {
address receiver = makeAddr("receiver");

vm.startPrank(_ownerAddr);
uint256 tokenId = _spotlightRootIPCollection.mint();
vm.expectRevert("SpotlightRootIPCollection: transfer is disabled");
_spotlightRootIPCollection.safeTransferFrom(_ownerAddr, receiver, tokenId, "");
vm.stopPrank();
}

function test_transferFrom() public {
address receiver = makeAddr("receiver");

vm.startPrank(_ownerAddr);
uint256 tokenId = _spotlightRootIPCollection.mint();
_spotlightRootIPCollection.setTransferEnabled(true);
_spotlightRootIPCollection.transferFrom(_ownerAddr, receiver, tokenId);
vm.stopPrank();

assertEq(_spotlightRootIPCollection.ownerOf(tokenId), receiver);
}

function test_safeTransferFrom() public {
address receiver = makeAddr("receiver");

vm.startPrank(_ownerAddr);
uint256 tokenId = _spotlightRootIPCollection.mint();
_spotlightRootIPCollection.setTransferEnabled(true);
_spotlightRootIPCollection.safeTransferFrom(_ownerAddr, receiver, tokenId);
vm.stopPrank();

assertEq(_spotlightRootIPCollection.ownerOf(tokenId), receiver);
}

function test_safeTransferFromWithData() public {
address receiver = makeAddr("receiver");

vm.startPrank(_ownerAddr);
uint256 tokenId = _spotlightRootIPCollection.mint();
_spotlightRootIPCollection.setTransferEnabled(true);
_spotlightRootIPCollection.safeTransferFrom(_ownerAddr, receiver, tokenId, "");
vm.stopPrank();

assertEq(_spotlightRootIPCollection.ownerOf(tokenId), receiver);
}
}

0 comments on commit b5781c2

Please sign in to comment.