Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SoundNft -> SoundEdition #6

Merged
merged 4 commits into from
Jul 21, 2022
Merged
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Sound Protocol 2.0

See [spec](./spec.md) for current spec.
37 changes: 20 additions & 17 deletions contracts/SoundCreator/SoundCreatorV1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,39 @@ pragma solidity ^0.8.15;
▓██████████████████████████████████████████████████████████
*/

import "../SoundNft/ISoundNftV1.sol";
import "../SoundEdition/ISoundEditionV1.sol";
import "chiru-labs/ERC721A-Upgradeable/ERC721AUpgradeable.sol";
import "openzeppelin/proxy/Clones.sol";

contract SoundCreatorV1 {
/***********************************
/***********************************
STORAGE
***********************************/

address public nftImplementation;
address public soundRegistry;
address public nftImplementation;
address public soundRegistry;

/***********************************
/***********************************
PUBLIC FUNCTIONS
***********************************/

constructor(address _nftImplementation, address _soundRegistry) {
nftImplementation = _nftImplementation;
soundRegistry = _soundRegistry;
}
constructor(address _nftImplementation, address _soundRegistry) {
nftImplementation = _nftImplementation;
soundRegistry = _soundRegistry;
}

function createSoundNft(string memory _name, string memory _symbol) external returns (address soundNft) {
// todo: if signature provided, pass it to SoundRegistry.register();
// todo: implement extension configurations
function createSound(string memory _name, string memory _symbol)
external
returns (address soundNft)
{
// todo: if signature provided, pass it to SoundRegistry.register();
// todo: implement extension configurations

// todo: research if we can get any gas savings by using a more minimal version of Clones lib
soundNft = Clones.clone(nftImplementation);
// todo: research if we can get any gas savings by using a more minimal version of Clones lib
soundNft = Clones.clone(nftImplementation);

ISoundNftV1(soundNft).initialize(_name, _symbol);
ISoundEditionV1(soundNft).initialize(msg.sender, _name, _symbol);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to pass in msg.sender to ensure it is set as the owner of the NFT. If we used msg.sender within SoundNftV1.sol, it would set SoundCreatorV1.sol as the owner. And if we used tx.origin, contracts wouldn't be able to create/own NFTs.


// todo: emit event
}
// todo: emit event
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

pragma solidity ^0.8.15;

import "chiru-labs/ERC721A-Upgradeable/ERC721AUpgradeable.sol";
import "openzeppelin-upgradeable/access/OwnableUpgradeable.sol";
import "chiru-labs/ERC721A-Upgradeable/interfaces/IERC721AUpgradeable.sol";

/*
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
Expand Down Expand Up @@ -31,8 +30,12 @@ import "openzeppelin-upgradeable/access/OwnableUpgradeable.sol";
▓██████████████████████████████████████████████████████████
*/

/// @title ISoundNftV1
/// @title ISoundEditionV1
/// @author Sound.xyz
interface ISoundNftV1 {
function initialize(string memory _name, string memory _symbol) external;
interface ISoundEditionV1 is IERC721AUpgradeable {
function initialize(
address _owner,
string memory _name,
string memory _symbol
) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
pragma solidity ^0.8.15;

import "chiru-labs/ERC721A-Upgradeable/ERC721AUpgradeable.sol";
import "openzeppelin-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "openzeppelin-upgradeable/access/OwnableUpgradeable.sol";
import "openzeppelin-upgradeable/interfaces/IERC2981Upgradeable.sol";

/*
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
Expand Down Expand Up @@ -31,11 +33,50 @@ import "openzeppelin-upgradeable/access/OwnableUpgradeable.sol";
▓██████████████████████████████████████████████████████████
*/

/// @title SoundNftV1
/// @title SoundEditionV1
/// @author Sound.xyz
contract SoundNftV1 is ERC721AUpgradeable, OwnableUpgradeable {
function initialize(string memory _name, string memory _symbol) public initializerERC721A initializer {
__ERC721A_init(_name, _symbol);
__Ownable_init();
}
contract SoundEditionV1 is
ERC721AUpgradeable,
IERC2981Upgradeable,
OwnableUpgradeable
{
/// @notice Initializes the contract
/// @param _owner Owner of contract (artist)
/// @param _name Name of the token
/// @param _symbol Symbol of the token
function initialize(
address _owner,
string memory _name,
string memory _symbol
) public initializerERC721A initializer {
__ERC721A_init(_name, _symbol);
__Ownable_init();

// Set ownership to owner
transferOwnership(_owner);
}

/// @notice Informs other contracts which interfaces this contract supports
/// @param _interfaceId The interface id to check
/// @dev https://eips.ethereum.org/EIPS/eip-165
function supportsInterface(bytes4 _interfaceId)
public
view
override(ERC721AUpgradeable, IERC165Upgradeable)
returns (bool)
{
// todo
}

/// @notice Get royalty information for token
/// @param _tokenId token id
/// @param _salePrice Sale price for the token
function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
external
view
override
returns (address fundingRecipient, uint256 royaltyAmount)
{
// todo
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added these functions because IERC2981Upgradeable inherits from IERC165Upgradeable, which I thought I might need for the registry, which wasn't the case.

However, both will be needed eventually so I figured it doesn't hurt to keep them.

}
}
14 changes: 12 additions & 2 deletions spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,20 @@ Sound Protocol 2.0 enables creators to permissinonlessly deploy gas-efficient NF

- `SoundCreatorV1.sol`
- Upgradeable via [UUPSUpgradeable](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable)
- Deploys [minimal proxies (clones)](https://eips.ethereum.org/EIPS/eip-1167) of `Sound721aV1.sol` & initializes them with customizable configurations.
- `Sound721aV1.sol`
- Deploys [minimal proxies (clones)](https://eips.ethereum.org/EIPS/eip-1167) of `SoundEditionV1.sol` & initializes them with customizable configurations.

- `SoundEditionV1.sol`
- Logic contract for the proxies deployed from SoundCreatorV1
- Extended version of the [721a implementation](https://www.azuki.com/erc721a)
- Implements EIP-2981 (`royaltyInfo`)
- Implements `contractURI` (https://docs.opensea.io/docs/contract-level-metadata)
- Implements EIP-165 (`supportsInterface)
- Implements extension contracts for:
- metadata - `tokenURI`
- payments - royalties & withdrawals
- minting
- registry management

- `SoundXyzRegistryV1.sol`
- Upgradeable via [UUPSUpgradeable](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable)
- Stores registry of NFTs by sound.xyz artists
Expand Down
10 changes: 5 additions & 5 deletions tests/SoundCreator.t.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
pragma solidity ^0.8.15;

import "./TestConfig.sol";
import "../contracts/SoundNft/SoundNftV1.sol";
import "../contracts/SoundEdition/SoundEditionV1.sol";
import "../contracts/SoundCreator/SoundCreatorV1.sol";

contract SoundCreatorTests is TestConfig {
// Tests that the factory deploys
function test_deploysSoundCreator() public {
SoundNftV1 soundNftImplementation = new SoundNftV1();
SoundEditionV1 soundNftImplementation = new SoundEditionV1();
address soundRegistry = address(123);
SoundCreatorV1 _soundCreator = new SoundCreatorV1(
address(soundNftImplementation),
Expand All @@ -24,9 +24,9 @@ contract SoundCreatorTests is TestConfig {
}

// Tests that the factory creates a new sound NFT
function test_createSoundNft() public {
SoundNftV1 soundNft = SoundNftV1(
soundCreator.createSoundNft(SONG_NAME, SONG_SYMBOL)
function test_createSound() public {
SoundEditionV1 soundNft = SoundEditionV1(
soundCreator.createSound(SONG_NAME, SONG_SYMBOL)
);

assert(address(soundNft) != address(0));
Expand Down
6 changes: 3 additions & 3 deletions tests/TestConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.5;
import "forge-std/Test.sol";

import "../contracts/SoundCreator/SoundCreatorV1.sol";
import "../contracts/SoundNft/SoundNftV1.sol";
import "../contracts/SoundEdition/SoundEditionV1.sol";

contract TestConfig is Test {
// Artist contract creation vars
Expand All @@ -15,8 +15,8 @@ contract TestConfig is Test {

// Set up called before each test
function setUp() public {
// Deploy SoundNft implementation
SoundNftV1 soundNftImplementation = new SoundNftV1();
// Deploy SoundEdition implementation
SoundEditionV1 soundNftImplementation = new SoundEditionV1();

// todo: deploy registry here
address soundRegistry = address(123);
Expand Down