-
Notifications
You must be signed in to change notification settings - Fork 58
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
feat(erc1155): add custom ERC1155 contract for airdrop #262
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome @dohaki and the scripts + tests look great. My main recommendation is to remove the AccessControlEnumerable
and just replace it with a simple Ownable
. We can have the owner
have minting, pausing, and setting URI ability. This will keep the contract simpler.
My other suggestion is to add NatSpec comments to all Solidity files. This will importantly render the function comments and descriptions on Etherscan! GitHub CoPilo is great for this ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few comments. Looks amazing so far, @dohaki
function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner { | ||
_tokenURIs[tokenId] = tokenURI; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want it to be possible to reset a token URI after it's already been set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm I guess not actually, it would give holders more confidence. So maybe require existing tokenURI is empty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a require here 898de67
* @param tokenId Token type to airdrop. | ||
* @param amount Amount of token types to airdrop. | ||
* | ||
* NOTE: Call might run out of gas if `recipients` arg too long. Might need to chunk up the list. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would just make this a @dev
call instead of NOTE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 898de67
constructor() ERC1155("") {} | ||
|
||
/** | ||
* @dev Creates `amount` new tokens for `recipients` of token type `tokenId`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, explanation of function should be @notice
not @dev
. Use @dev
for caller warnings like the out of gas limit
* @param tokenURI URI of token metadata. | ||
*/ | ||
function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner { | ||
_tokenURIs[tokenId] = tokenURI; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: emit an Event after changing state. Something like SetTokenURI(uint256 tokenId, string newUri)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes good point. Actually in the spec we should emit URI(uri, tokenId)
. See https://eips.ethereum.org/EIPS/eip-1155#specification
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect!
* `setTokenURI` to allow IPFS URIs for all token types. | ||
* @param tokenId Token type to retrieve metadata URI for. | ||
*/ | ||
function uri(uint256 tokenId) public view virtual override returns (string memory) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: no need to make this virtual
anymore
} | ||
|
||
/** | ||
* @dev Instead of returning the same URI for *all* token types, we return the uri set by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Add a @notice explaining this function. Can use @inheritdoc ERC1155
for example
} | ||
|
||
/** | ||
* @dev Sets the URI for token of type `tokenId` to `tokenURI`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: make @notice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! I left some nits
- emit URI event - require token uri not set - doc improvements
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; | ||
|
||
contract MintableERC1155 is ERC1155, Ownable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add a @title, @notice
comment above the Contract. Something like:
@title MintableERC1155
@notice Ownable contract enabling owner to airdrop many recipients the same token ID at once
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; | ||
|
||
contract MintableERC1155 is ERC1155, Ownable { | ||
mapping(uint256 => string) public _tokenURIs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should add comment above all state vars including _tokenURIs
event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount); | ||
|
||
// solhint-disable-next-line | ||
constructor() ERC1155("") {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might add a comment why you're passing in "" (because we opt to use the _tokenURIs mapping instead)
airdropTx.hash | ||
); | ||
await airdropTx.wait(); | ||
console.log(`Successfully minted token to:`, recipientsChunk); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would make sense to set the token URI here too or we'll submit a manual tx for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to create a separate script in a separate PR that does this. Basically
- Parse and validate metadata
- Upload to IPFS
- Set token URI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Part of ACX-950
I also deployed to Mumbai Testnet here https://mumbai.polygonscan.com/address/0x17496824ba574a4e9de80110a91207c4c63e552a and tested the integration with OpenSea here https://testnets.opensea.io/assets/mumbai/0x17496824ba574a4e9de80110a91207c4c63e552a/0.
But I wasn't able to verify the contract via Polyscan though 🤔 When I run
with the env var
POLYGON_ETHERSCAN_API_KEY
being set, I get