Skip to content

Commit

Permalink
Set collection name, symbol, uri in dao (#568)
Browse files Browse the repository at this point in the history
* Set collection name, symbol, uri in dao

* Update deployment task, lint

* Use _baseURI

* Use setBaseURI in init

* Remove requireMinted check
  • Loading branch information
nickmzero authored Sep 27, 2022
1 parent bab837b commit a718a13
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 44 deletions.
57 changes: 46 additions & 11 deletions contracts/nft/TributeERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ contract TributeERC721 is

DaoRegistry public daoRegistry;

bytes32 constant TokenName = keccak256("dao-collection.TokenName");
bytes32 constant TokenSymbol = keccak256("dao-collection.TokenSymbol");
bytes32 constant TokenMediaPt1 = keccak256("dao-collection.TokenMediaPt1");
bytes32 constant TokenMediaPt2 = keccak256("dao-collection.TokenMediaPt2");
bytes32 constant Transferable = keccak256("dao-collection.Transferable");
bytes32 constant CollectionSize =
keccak256("dao-collection.CollectionSize");
Expand All @@ -48,17 +52,12 @@ contract TributeERC721 is
}

// https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable
function initialize(
string memory name,
string memory symbol,
address daoAddress,
string memory newBaseURI
) external initializer {
__ERC721_init(name, symbol);
function initialize(address daoAddress) external initializer {
__ERC721_init("", "");
__Ownable_init();
__UUPSUpgradeable_init();
daoRegistry = DaoRegistry(daoAddress);
setBaseURI(newBaseURI);
setBaseURI("ipfs://");
}

function _authorizeUpgrade(address newImplementation)
Expand Down Expand Up @@ -104,6 +103,16 @@ contract TributeERC721 is
_createNewAmountCheckpoint(to);
}

function name() public view virtual override returns (string memory) {
return
bytes32ToString(bytes32(daoRegistry.getConfiguration(TokenName)));
}

function symbol() public view virtual override returns (string memory) {
return
bytes32ToString(bytes32(daoRegistry.getConfiguration(TokenSymbol)));
}

function _baseURI() internal view override returns (string memory) {
return baseURI;
}
Expand All @@ -112,15 +121,25 @@ contract TributeERC721 is
baseURI = newBaseURI;
}

function tokenURI(uint256 tokenId)
function tokenURI(uint256)
public
view
virtual
override
returns (string memory)
{
_requireMinted(tokenId);
return _baseURI();
return
string(
abi.encodePacked(
_baseURI(),
bytes32ToString(
bytes32(daoRegistry.getConfiguration(TokenMediaPt1))
),
bytes32ToString(
bytes32(daoRegistry.getConfiguration(TokenMediaPt2))
)
)
);
}

/**
Expand Down Expand Up @@ -203,4 +222,20 @@ contract TributeERC721 is
numCheckpoints[member] = nCheckpoints + 1;
}
}

function bytes32ToString(bytes32 _bytes32)
public
pure
returns (string memory)
{
uint8 i = 0;
while (i < 32 && _bytes32[i] != 0) {
i++;
}
bytes memory bytesArray = new bytes(i);
for (i = 0; i < 32 && _bytes32[i] != 0; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
}
57 changes: 46 additions & 11 deletions contracts/test/TributeERC721V2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ contract TributeERC721V2 is

DaoRegistry public daoRegistry;

bytes32 constant TokenName = keccak256("dao-collection.TokenName");
bytes32 constant TokenSymbol = keccak256("dao-collection.TokenSymbol");
bytes32 constant TokenMediaPt1 = keccak256("dao-collection.TokenMediaPt1");
bytes32 constant TokenMediaPt2 = keccak256("dao-collection.TokenMediaPt2");
bytes32 constant Transferable = keccak256("dao-collection.Transferable");
bytes32 constant CollectionSize =
keccak256("dao-collection.CollectionSize");
Expand All @@ -49,17 +53,12 @@ contract TributeERC721V2 is
}

// https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable
function initialize(
string memory name,
string memory symbol,
address daoAddress,
string memory newBaseURI
) external initializer {
__ERC721_init(name, symbol);
function initialize(address daoAddress) external initializer {
__ERC721_init("", "");
__Ownable_init();
__UUPSUpgradeable_init();
daoRegistry = DaoRegistry(daoAddress);
setBaseURI(newBaseURI);
setBaseURI("ipfs://");
}

function _authorizeUpgrade(address newImplementation)
Expand Down Expand Up @@ -105,6 +104,16 @@ contract TributeERC721V2 is
_createNewAmountCheckpoint(to);
}

function name() public view virtual override returns (string memory) {
return
bytes32ToString(bytes32(daoRegistry.getConfiguration(TokenName)));
}

function symbol() public view virtual override returns (string memory) {
return
bytes32ToString(bytes32(daoRegistry.getConfiguration(TokenSymbol)));
}

function _baseURI() internal view override returns (string memory) {
return baseURI;
}
Expand All @@ -113,15 +122,25 @@ contract TributeERC721V2 is
baseURI = newBaseURI;
}

function tokenURI(uint256 tokenId)
function tokenURI(uint256)
public
view
virtual
override
returns (string memory)
{
_requireMinted(tokenId);
return _baseURI();
return
string(
abi.encodePacked(
_baseURI(),
bytes32ToString(
bytes32(daoRegistry.getConfiguration(TokenMediaPt1))
),
bytes32ToString(
bytes32(daoRegistry.getConfiguration(TokenMediaPt2))
)
)
);
}

/**
Expand Down Expand Up @@ -204,4 +223,20 @@ contract TributeERC721V2 is
numCheckpoints[member] = nCheckpoints + 1;
}
}

function bytes32ToString(bytes32 _bytes32)
public
pure
returns (string memory)
{
uint8 i = 0;
while (i < 32 && _bytes32[i] != 0) {
i++;
}
bytes memory bytesArray = new bytes(i);
for (i = 0; i < 32 && _bytes32[i] != 0; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
}
16 changes: 3 additions & 13 deletions tasks/tributeERC721Tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,20 @@ task(
"deployTributeERC721",
"Task that deploys a TributeERC721 proxy collection and implementation (will reuse existing implementation)"
)
.addPositionalParam("name")
.addPositionalParam("symbol")
.addPositionalParam("daoAddress")
.addPositionalParam("baseURI")
.setAction(async (taskArgs, hre) => {
const { name, symbol, daoAddress, baseURI } = taskArgs;
const { daoAddress } = taskArgs;
const { network } = hre.hardhatArguments;

log(`Deployment started at ${new Date().toISOString()}`);
log(`Deploying TributeERC721 ${name} to ${network} network`);
log(`Constructor args: `);
log(
`-- Name: ${name}, Symbol: ${symbol}, daoAddress: ${daoAddress}, baseURI: ${baseURI}\n`
`Deploying TributeERC721 for daoAddress ${daoAddress} to ${network} network`
);

const TributeERC721 = await ethers.getContractFactory("TributeERC721");

// Deploying the proxy and implementation. Implementation can be reused.
const proxy = await hre.upgrades.deployProxy(TributeERC721, [
name,
symbol,
daoAddress,
baseURI,
]);
const proxy = await hre.upgrades.deployProxy(TributeERC721, [daoAddress]);
await proxy.deployed();
log(`Proxy deployed: ${proxy.address}`);
const implementation = await upgrades.erc1967.getImplementationAddress(
Expand Down
94 changes: 85 additions & 9 deletions test/tribute-erc721/tribute-erc721.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@ const setNftConfigurations = async (
manager,
daoAddress,
transferable,
collectionSize
collectionSize,
tokenName,
tokenSymbol,
tokenMediaPt1,
tokenMediaPt2
) => {
const nonce = (await manager.nonces(daoAddress)).toNumber() + 1;
const proposal = {
Expand All @@ -88,6 +92,30 @@ const setNftConfigurations = async (
};

const configs = [
{
key: sha3("dao-collection.TokenName"),
numericValue: ethers.utils.formatBytes32String(tokenName),
addressValue: ZERO_ADDRESS,
configType: 0,
},
{
key: sha3("dao-collection.TokenSymbol"),
numericValue: ethers.utils.formatBytes32String(tokenSymbol),
addressValue: ZERO_ADDRESS,
configType: 0,
},
{
key: sha3("dao-collection.TokenMediaPt1"),
numericValue: ethers.utils.formatBytes32String(tokenMediaPt1),
addressValue: ZERO_ADDRESS,
configType: 0,
},
{
key: sha3("dao-collection.TokenMediaPt2"),
numericValue: ethers.utils.formatBytes32String(tokenMediaPt2),
addressValue: ZERO_ADDRESS,
configType: 0,
},
{
key: sha3("dao-collection.Transferable"),
numericValue: transferable,
Expand Down Expand Up @@ -126,7 +154,10 @@ const setNftConfigurations = async (
);
};

const BASE_URI = "https://www.fakenfturi123.com/";
const TOKEN_MEDIA = "QmdXQLJWkv27YFLxJ33piMBpxmL6236TdrsD1Lh8n33WXU";
const TOKEN_URI = `ipfs://${TOKEN_MEDIA}`;
const COLLECTION_NAME = "Test DAO NFT";
const COLLECTION_SYMBOL = "TDN";

const deployAndConfigureCollection = async (
manager,
Expand All @@ -135,14 +166,19 @@ const deployAndConfigureCollection = async (
collectionSize
) => {
const TributeERC721 = await hre.ethers.getContractFactory("TributeERC721");
const proxy = await upgrades.deployProxy(TributeERC721, [
"Test DAO NFT",
"TDN",
daoAddress,
BASE_URI,
]);
const proxy = await upgrades.deployProxy(TributeERC721, [daoAddress]);
await proxy.deployed();
await setNftConfigurations(manager, daoAddress, transferable, collectionSize);
await setNftConfigurations(
manager,
daoAddress,
transferable,
collectionSize,
COLLECTION_NAME,
COLLECTION_SYMBOL,
TOKEN_MEDIA.slice(0, 23),
TOKEN_MEDIA.slice(23)
);

return { proxy };
};

Expand All @@ -169,6 +205,21 @@ describe("nft test", () => {
this.snapshotId = await takeChainSnapshot();
});

it("Configured with name and symbol in DAO", async () => {
const { proxy } = await deployAndConfigureCollection(
this.adapters.manager,
daoAddress,
1,
100
);

const name = await proxy.name();
const symbol = await proxy.symbol();

expect(name).to.equal(COLLECTION_NAME);
expect(symbol).to.equal(COLLECTION_SYMBOL);
});

it("Can upgrade proxy", async () => {
const { proxy } = await deployAndConfigureCollection(
this.adapters.manager,
Expand Down Expand Up @@ -531,6 +582,31 @@ describe("nft test", () => {

expect(uri1).to.equal(uri2);
});

it("tokenURI correctly resolves tokenMedia parts to ipfs cid", async () => {
const { proxy } = await deployAndConfigureCollection(
this.adapters.manager,
daoAddress,
1,
100
);
const [collectionAddress, owner, nonce] = [proxy.address, accounts[0], 1];
await proxy.mint(
owner,
nonce,
generateNFTCouponSignature({
collectionAddress,
owner,
nonce,
chainId,
daoAddress,
})
);

const uri = await proxy.tokenURI(1);

expect(uri).to.equal(TOKEN_URI);
});
});

const generateManagerCouponSignature = ({
Expand Down

0 comments on commit a718a13

Please sign in to comment.