# Marital Obligations Smart Contract Review ## Background Superrare: https://superrare.com/artwork/eth/0x82a870e295b8dcb8de2095529bff1b0697aa361b/let-me-check-with-the-wife--1 Etherscan: https://etherscan.io/address/0x82a870e295b8dcb8de2095529bff1b0697aa361b Secondary Token: https://opensea.io/collection/marital-obligations Etherscan https://etherscan.io/address/0x0169b5e4059b18d3bc5002c56b72d512bf67fe37 - Basically we minted an artwork (let me check with the wife) on SuperRare - then created a 2nd contract called Marital Obligations - (which is a dynamic SVG nft we can update with prompts to the collector). - It uses the Owner(Of) function so that it is forever tied to LMCWTW SuperRare minted piece. - Questions I have are: - 1) will the owner of function work as expected - 2) are there any security issues with the updating the marital obligations contract (we have to connect our wallet to the contract in etherscan to create updates on the SVG ). - We’ve already updated the message before, but now just getting nervous bc if we can’t update the SVG then the artwork doesn’t make sense. ## Comments 1. Dynamic SVG - This seems to work as intended. It gets the message for the current year. However if the message for the current year does not exist it errors. The current year message is empty but this can be fixed by using `writeMessage` - You can edit any message with `editMessage` so if you mess up it can be fixed - I don't see any security isues with updating the message. Besides the normal ones of make sure you verify exactly what you're signing and confirm the contract address in the wallet. 2. Owner Of - This works as intended as well. I simulated a transfer of the primary artwork and the ownerOf for the second contract moved as well - HOWEVER just like with HU Act II it will probably not visually update ownership of the secondary contract in wallets and marketplaces because no event is emitted. This cannot be changed without rewriting/ redeploying the contract with some modifications and still then it wouldn't be guaranteed to work ## Superrare Token Overview Collection Address: 0x82a870e295b8dcb8de2095529bff1b0697aa361b Contract Owner: 0x8ba7E0BE0460035699BAddD1fD1aCCb178702348 Total supply: 1 Token Owner: 0x8ba7E0BE0460035699BAddD1fD1aCCb178702348 ## Secondary Token Overview Collection Address 0x0169b5e4059b18d3bc5002c56b72d512bf67fe37 Contract Owner: 0x8ba7E0BE0460035699BAddD1fD1aCCb178702348 Token Owner: 0x8ba7E0BE0460035699BAddD1fD1aCCb178702348 MD (metadata contract?): 0x420f67F0239fff147a1C5ccDdeEb55b3d0292e58 (unverified) ### Read Functions #### `tokenURI(uint256)` Returns token URI. Currently returning an error ![Screenshot 2024-06-07 at 12.56.00](https://hackmd.io/_uploads/H1ApineHR.png) Simulation error: https://www.tdly.co/shared/simulation/3633b1bc-c691-4609-99fa-9a608db6bcef Works if we go back in time: https://www.tdly.co/shared/simulation/3c54c539-f280-42da-8038-46eace59d142 ``` string[3] memory parts = [ '<svg...>', phrases[selector()], // This line appears to be the problem '</div>...' ]; ``` #### `selector()` Returns a new selector for the current year. If this is not set it causes tokenURI to error. Current selector is `2` ```solidity function selector() public view returns(uint) { return (block.timestamp - anniv) / 52 weeks; } ``` ![Screenshot 2024-06-07 at 13.12.00](https://hackmd.io/_uploads/HyBY1agrR.png) ![Screenshot 2024-06-07 at 13.11.55](https://hackmd.io/_uploads/HkBFy6lBC.png) #### `ownerOf(uint256)` Override of `ownerOf` ```solidity function ownerOf(uint256 _tokenId) public view override returns(address){ if(linkageId != 0){ return linkage.ownerOf(linkageId); } else { return linkage.ownerOf(_tokenId); } } ``` LinkageID appears to translate tokenId to external linked Token in case tokenId is different If not it returnes ownerOf via the tokenId Confirmed ownerOf works when SR token is transferred https://dashboard.tenderly.co/explorer/fork/2f10d3a6-c93f-474b-bb54-27fea6e28d85/simulation/92c103bd-f6fa-4be1-8fd3-2299184b700a #### `balanceOf(address)` Override of `balanceOf` ```solidity function balanceOf(address owner) public view virtual override returns (uint256) { if(owner == ownerOf(1)){ return 1; } else { return 0; } } ``` Returns 1 only if owner is the owner of the only token ### Internal Functions `_beforeTokenTransfer` Prevents token from being transferred. Allows for token to be minted ```solidity function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override { require(from == address(0),"Token cannot be transfered"); } ``` Confirmed this works, token cannot be transferred ### Write Functions #### Messages `alertMessage(string)` Writes message to current selector (based on year). Might need write message first to avoid array out of bounds error (confirmed, see simulation https://www.tdly.co/shared/simulation/ddef9dca-1e7e-4daf-8cfb-6bf2547fa299) `writeMessage(string)` Adds new message which gets used in SVG render. Can write as many as you want which would set future year messages `editMessage(string,uint256)` Edits any selector message #### Linkage `setLinkage(address,uint256)` Allows owner to set the linked contract address and token ID Can be updated if not finalized `finalizeLinkage()` Locks linkage so it cannot be updated again #### Standard ERC721 `approve(address,uint256)` Works `setApprovalForAll(address,bool)` Works `safeTransferFrom(address,address,uint256)` Disabled `safeTransferFrom(address,address,uint256,bytes)` Disabled `transferFrom(address,address,uint256)` Disabled #### Ownable `transferOwnership(address)` `renounceOwnership()`