@@ -15,6 +15,7 @@ interface IERC721 {
1515/// @author Rookmate (@0xRookmate)
1616contract MultiRootVesting is Ownable {
1717 address immutable vestingToken;
18+ bool public rootsLocked;
1819
1920 enum Collection {
2021 Cat, // NFT Collection
@@ -31,11 +32,6 @@ contract MultiRootVesting is Ownable {
3132 Liquidity
3233 }
3334
34- struct MerkleRootData {
35- bytes32 root;
36- bool locked;
37- }
38-
3935 struct Vesting {
4036 uint256 totalClaim;
4137 uint256 claimed;
@@ -47,8 +43,8 @@ contract MultiRootVesting is Ownable {
4743 Collection collection;
4844 }
4945
50- // Mapping from Collection to its merkle root data
51- mapping (Collection => MerkleRootData ) public collectionRoots;
46+ // Mapping from Collection to its merkle root
47+ mapping (Collection => bytes32 ) public collectionRoots;
5248 // Mapping from Collection to its NFT address
5349 mapping (Collection => address ) public nftCollections;
5450 // Mapping from vesting hash to vesting data
@@ -65,7 +61,7 @@ contract MultiRootVesting is Ownable {
6561 error CollectionNotConfigured ();
6662
6763 event MerkleRootUpdated (Collection indexed collection , bytes32 newRoot );
68- event CollectionRootLocked (Collection indexed collection );
64+ event RootsLocked ( );
6965 event VestingClaimed (bytes32 indexed vestingId , Collection indexed collection , address recipient , uint256 amount );
7066
7167 constructor (
@@ -89,24 +85,23 @@ contract MultiRootVesting is Ownable {
8985
9086 // Set up merkle roots
9187 for (uint256 i = 0 ; i < collections.length ; ++ i) {
92- collectionRoots[collections[i]].root = roots[i];
88+ collectionRoots[collections[i]] = roots[i];
9389 }
9490 }
9591
9692 /// @notice Update the merkle root for a specific collection (only if not locked)
9793 /// @param collection The collection to update
9894 /// @param newRoot The new merkle root
9995 function updateMerkleRoot (Collection collection , bytes32 newRoot ) external onlyOwner {
100- if (collectionRoots[collection].locked ) revert RootLocked ();
101- collectionRoots[collection].root = newRoot;
96+ if (rootsLocked ) revert RootLocked ();
97+ collectionRoots[collection] = newRoot;
10298 emit MerkleRootUpdated (collection, newRoot);
10399 }
104100
105- /// @notice Lock the merkle root for a specific collection permanently
106- /// @param collection The collection to lock
107- function lockRoot (Collection collection ) external onlyOwner {
108- collectionRoots[collection].locked = true ;
109- emit CollectionRootLocked (collection);
101+ /// @notice Lock all merkle roots permanently
102+ function lockRoots () external onlyOwner {
103+ rootsLocked = true ;
104+ emit RootsLocked ();
110105 }
111106
112107 /// @notice Claim vested tokens with merkle proof
@@ -133,7 +128,7 @@ contract MultiRootVesting is Ownable {
133128 bytes32 leaf = keccak256 (abi.encodePacked (collection, tokenId, recipient, totalClaim, start, end));
134129
135130 // Verify merkle proof against collection root
136- if (! MerkleProofLib.verifyCalldata (proof, collectionRoots[collection].root , leaf)) {
131+ if (! MerkleProofLib.verifyCalldata (proof, collectionRoots[collection], leaf)) {
137132 revert InvalidMerkleProof ();
138133 }
139134
@@ -184,7 +179,7 @@ contract MultiRootVesting is Ownable {
184179 uint256 start = vesting.start;
185180 uint256 current = block .timestamp ;
186181
187- // Early return if vesting hasn't started
182+ // Early return if vesting hasn't started or if it hasn't passed a day since last claim
188183 if (current < start || current < (vesting.lastClaim + 1 days)) {
189184 return (vesting, 0 );
190185 }
0 commit comments