@@ -144,13 +144,77 @@ contract TokenizerWrappedTest is Test {
144144 IIPToken tokenContract = tokenizer.attachIpt (1 , agreementCid, "" , erc20);
145145
146146 // Wrapped tokens should not be able to issue or cap
147- vm.expectRevert ("WrappedIPToken: cannot issue " );
147+ vm.expectRevert ("WrappedIPToken: read-only wrapper - use underlying token for minting " );
148148 tokenContract.issue (alice, 1000 );
149149
150- vm.expectRevert ("WrappedIPToken: cannot cap " );
150+ vm.expectRevert ("WrappedIPToken: read-only wrapper - use underlying token for cappping " );
151151 tokenContract.cap ();
152152 }
153153
154+ function testWrappedTokenStateChangingOperationsRevert () public {
155+ vm.startPrank (originalOwner);
156+ erc20 = new FakeERC20 ("TestToken " , "TEST " );
157+ erc20.mint (originalOwner, 1_000_000 ether);
158+
159+ IIPToken tokenContract = tokenizer.attachIpt (1 , agreementCid, "" , erc20);
160+
161+ // Test that IIPToken state-changing operations revert with proper messages
162+ vm.expectRevert ("WrappedIPToken: read-only wrapper - use underlying token for minting " );
163+ tokenContract.issue (alice, 1000 );
164+
165+ vm.expectRevert ("WrappedIPToken: read-only wrapper - use underlying token for cappping " );
166+ tokenContract.cap ();
167+ }
168+
169+ function testWrappedTokenReadOnlyOperationsWork () public {
170+ vm.startPrank (originalOwner);
171+ erc20 = new FakeERC20 ("TestToken " , "TEST " );
172+ erc20.mint (originalOwner, 1_000_000 ether);
173+
174+ IIPToken tokenContract = tokenizer.attachIpt (1 , agreementCid, "" , erc20);
175+ WrappedIPToken wrappedToken = WrappedIPToken (address (tokenContract));
176+
177+ // Test that read-only operations still work
178+ assertEq (wrappedToken.balanceOf (originalOwner), 1_000_000 ether);
179+ assertEq (wrappedToken.totalSupply (), 1_000_000 ether);
180+ assertEq (wrappedToken.name (), "TestToken " );
181+ assertEq (wrappedToken.symbol (), "TEST " );
182+ assertEq (wrappedToken.decimals (), 18 );
183+ assertEq (wrappedToken.totalIssued (), 1_000_000 ether);
184+
185+ // Test IP metadata functions work
186+ assertEq (wrappedToken.metadata ().ipnftId, 1 );
187+ assertEq (wrappedToken.metadata ().originalOwner, originalOwner);
188+ assertEq (wrappedToken.metadata ().agreementCid, agreementCid);
189+
190+ // Test URI function works
191+ string memory uri = wrappedToken.uri ();
192+ assertTrue (bytes (uri).length > 0 );
193+ }
194+
195+ function testUnderlyingTokenOperationsStillWork () public {
196+ vm.startPrank (originalOwner);
197+ erc20 = new FakeERC20 ("TestToken " , "TEST " );
198+ erc20.mint (originalOwner, 1_000_000 ether);
199+
200+ IIPToken tokenContract = tokenizer.attachIpt (1 , agreementCid, "" , erc20);
201+
202+ // Users can still use the underlying token directly for transfers
203+ assertTrue (erc20.transfer (alice, 100_000 ether));
204+ assertEq (erc20.balanceOf (alice), 100_000 ether);
205+ assertEq (erc20.balanceOf (originalOwner), 900_000 ether);
206+
207+ // Approvals work on the underlying token
208+ assertTrue (erc20.approve (alice, 50_000 ether));
209+ assertEq (erc20.allowance (originalOwner, alice), 50_000 ether);
210+
211+ // Transfer from works on the underlying token
212+ vm.startPrank (alice);
213+ assertTrue (erc20.transferFrom (originalOwner, alice, 25_000 ether));
214+ assertEq (erc20.balanceOf (alice), 125_000 ether);
215+ assertEq (erc20.balanceOf (originalOwner), 875_000 ether);
216+ }
217+
154218 // Helper function to check if a string contains a substring
155219 function contains (string memory source , string memory search ) internal pure returns (bool ) {
156220 bytes memory sourceBytes = bytes (source);
0 commit comments