diff --git a/l2-contracts/src/ZkCappedMinterV2.sol b/l2-contracts/src/ZkCappedMinterV2.sol index aa22c43..0340d27 100644 --- a/l2-contracts/src/ZkCappedMinterV2.sol +++ b/l2-contracts/src/ZkCappedMinterV2.sol @@ -31,6 +31,12 @@ contract ZkCappedMinterV2 is AccessControl, Pausable { /// @notice The timestamp after which minting is no longer allowed (inclusive). uint48 public immutable EXPIRATION_TIME; + /// @notice The metadata URI for this minter. + bytes32 public metadataURI; + + /// @notice Emitted when the metadata URI is set. + event MetadataURISet(bytes32 uri); + /// @notice Error for when the cap is exceeded. error ZkCappedMinterV2__CapExceeded(address minter, uint256 amount); @@ -122,4 +128,13 @@ contract ZkCappedMinterV2 is AccessControl, Pausable { _checkRole(DEFAULT_ADMIN_ROLE, msg.sender); closed = true; } + + /// @notice Sets the metadata URI for this contract + /// @param _uri The new metadata URI + /// @dev Only callable by addresses with the DEFAULT_ADMIN_ROLE + function setMetadataURI(bytes32 _uri) external { + _checkRole(DEFAULT_ADMIN_ROLE, msg.sender); + metadataURI = _uri; + emit MetadataURISet(_uri); + } } diff --git a/l2-contracts/test/ZkCappedMinterV2.t.sol b/l2-contracts/test/ZkCappedMinterV2.t.sol index d943636..72ae1a5 100644 --- a/l2-contracts/test/ZkCappedMinterV2.t.sol +++ b/l2-contracts/test/ZkCappedMinterV2.t.sol @@ -126,9 +126,7 @@ contract Mint is ZkCappedMinterV2Test { address _receiver1, address _receiver2, uint256 _amount1, - uint256 _amount2, - uint256 _startTime, - uint256 _expirationTime + uint256 _amount2 ) public { _amount1 = bound(_amount1, 1, DEFAULT_CAP / 2); _amount2 = bound(_amount2, 1, DEFAULT_CAP / 2); @@ -337,3 +335,36 @@ contract Close is ZkCappedMinterV2Test { cappedMinter.close(); } } + +contract SetMetadataURI is ZkCappedMinterV2Test { + function testFuzz_InitialMetadataURIIsEmpty(address _admin, uint256 _cap, uint48 _startTime, uint48 _expirationTime) + public + { + (_startTime, _expirationTime) = _boundToValidTimeControls(_startTime, _expirationTime); + + ZkCappedMinterV2 cappedMinter = _createCappedMinter(_admin, _cap, _startTime, _expirationTime); + assertEq(cappedMinter.metadataURI(), bytes32(0)); + } + + function testFuzz_AdminCanSetMetadataURI(bytes32 _uri) public { + vm.prank(cappedMinterAdmin); + cappedMinter.setMetadataURI(_uri); + + assertEq(cappedMinter.metadataURI(), _uri); + } + + function testFuzz_EmitsMetadataURISetEvent(bytes32 _uri) public { + vm.prank(cappedMinterAdmin); + vm.expectEmit(); + emit ZkCappedMinterV2.MetadataURISet(_uri); + cappedMinter.setMetadataURI(_uri); + } + + function testFuzz_RevertIf_NonAdminSetsMetadataURI(address _nonAdmin, bytes32 _uri) public { + vm.assume(cappedMinterAdmin != _nonAdmin); + + vm.prank(_nonAdmin); + vm.expectRevert(_formatAccessControlError(_nonAdmin, DEFAULT_ADMIN_ROLE)); + cappedMinter.setMetadataURI(_uri); + } +}