DEV Community

Cover image for Solidity Contracts Within Contracts: A Dive into Solidity Mapping (Series - Part 3)
Scofield Idehen
Scofield Idehen

Posted on • Originally published at blog.learnhub.africa

Solidity Contracts Within Contracts: A Dive into Solidity Mapping (Series - Part 3)

On Day 4 of my learning path of "Learn Blockchain, Solidity and Full Stack Web Development with JavaScript, I learnt about contracts inside contracts.

In the world of blockchain development, smart contracts play a crucial role in facilitating decentralized applications.

These self-executing contracts, with the terms of the agreement written directly into code, allow for trustless interactions between parties on the blockchain.

One powerful feature of smart contract development is using contracts within contracts.

In this article, we will explore the concept of using contracts within contracts and take a deeper look at how it can be implemented in the programming language Solidity.

A contract within a contract, also known as a nested contract, is a contract that is defined and deployed within another contract.

This allows for creating a more modular and reusable codebase and encapsulating a contract's functionality.

The outer contract, also known as the parent contract, can interact with the inner contract, the child contract, and access its functions and variables.

//SPDX-License-Identifier: MIT
//Parent contract
pragma solidity ^0.8.8;
contract scofieldNew{
    uint newuser;
    mapping(uint256 => string) public newMappingForUser;
    struct addUser{
        string name;
        uint favoriteNumber;
    }
    addUser[] public TestUser; 
    function UserReturn()public view returns(uint){
        return newuser;
    }

    function FirstUser(string memory _name, uint _favouriteNumbner)public{
        TestUser.push(addUser(_name, _favouriteNumbner));
        newMappingForUser[_favouriteNumbner] = _name;

    }
}
Enter fullscreen mode Exit fullscreen mode
//SPDX-License-Identifier: MIT
//child contract
pragma solidity ^0.8.0;
import './ss.sol';
contract addNewContract{
    scofieldNew public newUserBase;
    function addnewfile()public{
        newUserBase = new scofieldNew();
    }
}
Enter fullscreen mode Exit fullscreen mode

The code example shows that the contract addNewContract has a variable newUserBase of type scofieldNew, which is publicly accessible.

The addNewContract contract also has a function called addnewfile, which creates an instance of the scofieldNew contract and assigns it to the newUserBase variable.

This allows the addNewContract contract to interact with the functions and variables of the scofieldNew contract.

The scofieldNew contract, the child contract in this example, has several functions and variables that the parent contract can access.

It has a variable newuser of type uint, a mapping newMappingForUser that maps a uint256 to a string, and an array of structs called TestUser.

The scofieldNew contract also has two functions, UserReturn and FirstUser, which the parent contract can call.

The UserReturn function returns the value of the newuser variable, and the FirstUser function allows for adding a new user to the TestUser array and updating the newMappingForUser mapping with the user's name and their favorite number.

One of the key benefits of using contracts within contracts is the ability to encapsulate functionality.

Separating a contract's functionality into smaller contracts makes it easier to understand, maintain, and test the code.

For example, if the scofieldNew contract were too complex, it could be broken down into multiple child contracts, each with specific functionality.

This allows for a more modular and reusable codebase and the ability to test each contract individually.

Another benefit of using contracts within contracts is creating a more secure environment for your application.

By separating the functionality of a contract into smaller contracts, it becomes more difficult for an attacker to compromise the entire system.

If a vulnerability is found in one of the child contracts, only that contract needs to be updated rather than the entire application.

It's also worth noting that creating a contract within a contract incurs additional gas costs. Each contract deployment is a separate transaction with its gas costs.

This needs to be considered when designing your contract architecture and deciding whether to use contracts within contracts.

Also, I learnt about mapping.
Mapping is a data structure that allows you to store and retrieve key-value pairs.

The keys are usually integers or fixed-size byte arrays, while the values can be of any data type.

Mappings are stored in the contract's storage and do not have a fixed size, meaning they can grow or shrink as you add or delete key-value pairs.

Mappings are defined using the mapping keyword, followed by the data type of the key and value.

For example, the following code defines a mapping that stores an address as the key and an uint as the value:

mapping (address => uint) public balances;

One of the main use cases for mappings is to store information about individual users or entities in a contract.

For example, in the code provided, the scofieldNew contract has a mapping called newMappingForUser that maps a uint256 to a string. This allows the contract to store information about a user based on their unique ID, and then retrieve it later by using their ID as the key.

Mappings are also helpful for checking if a certain value exists in the mapping. You can use the exists keyword to check if a key exists in the mapping. For example:

It's also worth noting that when you access a mapping, you are not modifying the value stored in the mapping; you're only reading it, so you don't have to worry about the state change and gas cost.

In terms of performance, the time complexity of reading and writing to a mapping is O(1), meaning it takes constant time to access a value regardless of the mapping size.

However, it's essential to remember that mappings can take up a lot of storage space and may be costly when storing large amounts of data.

In conclusion, using contracts within contracts is a powerful feature of smart contract development that allows for a more modular and reusable codebase and the ability to encapsulate functionality within a contract.

Mappings are also powerful data structure in Solidity that allows you to store and retrieve key-value pairs.

It can also lead to a more secure environment for your application.

However, Weighing the benefits and costs of using contracts within contracts is essential and deciding whether it's the best approach for your specific use case.

To follow my series, please find them here.

Top comments (0)