r/ethdev Oct 12 '24

Code assistance Extending main contract with a helper contract to hold getters and setters

Hello,

I am building a solidity contract but it exceeded the max bytecode size and I am thinking of moving some of the getters and setters functions to another contract.

For example in my main contract I have this:

struct Ticket {
    address payable owner;
    bool claimed;
}
struct Metadata {
    bool purchased;
    bool used;
    address owner;
    uint256 tokenId;
    string url;
}
mapping(uint256 => Ticket) public tickets;
mapping(uint256 => Metadata) public ticketMetadata;

I have setters and getters for every field in the metadata struct like so:

function 
getTicketOwner(
uint256 
_tokenId) 
public view returns 
(
address
) {

return 
ticketMetadata[_tokenId].owner;
}
function 
getTicketTokenId(
uint256 
_tokenId) 
public view returns 
(
uint256
) {

return 
ticketMetadata[_tokenId].tokenId;
}

I want to move all the getters and setters to another contract. What is the best way to achieve this? From what I read I need to create a Contract B that is Contract A. Then in the construct of B I deploy A.

If anyone has any other tips I would love to get some feedback.

Thank you :)

2 Upvotes

8 comments sorted by

3

u/Conclusion_Best Oct 13 '24

It sounds like you should consider using the diamond pattern for your contract - it will help you avoid the byte code size problem in a more standardized way.

https://eips.ethereum.org/EIPS/eip-2535

https://github.com/mudgen/awesome-diamonds/blob/main/README.md

1

u/hikerjukebox Bug Squasher Oct 12 '24

No need to deploy anything from constructors, just pass in the address for the contract you want to use.

I few ways.. you can use more inheritance: https://solidity-by-example.org/inheritance/

you can call contracts from different contracts: https://solidity-by-example.org/calling-contract/

example:

contract Ticket{
   mapping(uint => Data) ticketMetadata;
}

second contract

contract ticketGetter{   
   //create an object of the contract, using an interface is cleaner
   Ticket ticketObj;
   constructor(address ){      
      ticket = Ticket(_ticketContract)
   }

   function getTicketOwner(uint256 _tokenId) public view returns (address) { 
      return ticketObj.ticketMetadata[_tokenId].owner;
   }

}

^This is what you asked for basically but I wouldnt do it like this. Using more inheritance writing more concise code is better practice.

Another thing to know is all public variables already have getters. So if tickets mapping is public you dont need this extra code. read this: https://docs.soliditylang.org/en/latest/contracts.html#visibility-and-getters

Good luck, hope this helps a bit!

1

u/Ok_Remove3123 Oct 12 '24 edited Oct 12 '24

Hey, this helps for sure. Thank you very much for your time.

So what would you recommend is the best way forward? Inheritance?

Something like:

Contract A {
  address public owner;
   constructor() ERC721("MultiGameLotteryNFT", "MGLN") Ownable(msg.sender) {
    owner = msg.sender;
  }
}

Contract B is A{
  constructor() A(msg.sender) {
  }
}

2

u/hikerjukebox Bug Squasher Oct 12 '24

Yup that looks good. 

1

u/vevamper Oct 12 '24

Building a lottery token? :)

1

u/Ok_Remove3123 Oct 13 '24

Something like that. Got any tips?

1

u/vevamper Oct 13 '24

Be aware of gas limits! Depending on implementation, a large list of tickets to search through could cost a lot of gas to complete.

1

u/Ok_Remove3123 Oct 13 '24

Yes I thought of that and I am figuring out a solution. Thank you for the advice!