As my smart contract is >24k, I read that I need to break it into multiple (smaller) smart contracts.

So, my current design is to have a Core contract that has all the data in arrays. This Core has CRUD (create, read, update, delete) functions.

Then I have another Create contract that has the detailed logic on verification, massaging, etc.

Users will execute a method on this Create contract (eg GenerateNewRecord() ) which processes/validates the inputs, then execute the Core.Add(newRecord).

In this case, inside the Core.Add() method, it needs to ensure that it is executed by the Create contract, and only the Create contract.

How can I do this check? noting that end-user initiated the Create.GenerateNewRecord() which the Create contract will call the Core.Add() method.

Any advice will be appreciated. Or am I doing this incorrectly? What is the best-practice way to break large contracts into smaller ones?

In my case, I have a central store, and many functions that need access to this core storage. I am unable to break the storage into different smart contracts.

Thank you!

  • 1
    You could use something like OpenZeppelin's AccessControl, create a role for the Create contract and grant that role as part of the deployment.
    – Ismael
    Commented Jun 26, 2022 at 18:45
  • Would openzeppelin AccessControl be tracking the USER's address which called the Create.GenerateNewRecord() instead of the Create contract's address?
    – jlee88my
    Commented Jun 27, 2022 at 2:56
  • The AccessControl api only provides the base functionality. It is up to you how it is used, for example you could require() the caller to have certain role, ensuring only an approved contract could interact with a function.
    – Ismael
    Commented Jun 27, 2022 at 19:29

1 Answer 1


Simplest way of doing it would be to create an address variable inside the Create contract, store the address of the Core contract in constructor and inside the Add function, add a check like require(createAddress == msg.sender).

But the best way of doing it would be using AccessControl contract from openzepplin as mentioned by Ismael. AccessControl allows you to add multiple roles, you can add a role for CreateContract and use it with modifier onlyRole.

You can read more about AccessControl on Openzepplin AccessControl Page

  • Update: I confirm that when User calls ContractA, which then calls ContractB; then in this case, _msgSender() in ContractB returns ContractA, and not User who initiated the call). Thanks.
    – jlee88my
    Commented Jul 10, 2022 at 9:22
  • 1
    @JosephLee this is the expected behavior. If you need user's address. You can pass it as a function parameter to the second contract. Commented Jul 14, 2022 at 10:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.