Adding unique address to each item

https://medium.com/upstate-interactive/creating-a-contract-with-a-smart-contract-bdb67c5c8595

We want each item that was created to have its own unique address, to which customers can make payment.

I initially thought:

    struct Item {
        string id;
        uint price;
        itemState state;
        address _payto;
    }

However, this is would not work. How do we define/pre-allocate an address automatically to each item on creation? We do not control address creation and allocation on the EVM.

Solution

To get a unique address per item -> each item has its own smart contract. Therefore, the create() should result in deployment on a new item AND its smart contract.

We will split the code up, keeping the item smart contract as a separate child contract.

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
import "./ItemManager.sol";

contract Item {
    uint public priceInWei;
    uint public paidWei;
    uint public index;
    
    //variable of type ItemManager -> contract object.
    ItemManager parentContract;     
    
    // creation requires inputs: price & index.
    constructor(ItemManager _parentContract, uint _priceInWei, uint _index) public {
        priceInWei = _priceInWei;
        index = _index;
        parentContract = _parentContract;
    }
    receive() external payable {
        require(msg.value == priceInWei, "We don't support partial payments");
        require(paidWei == 0, "Item is already paid!");
        paidWei += msg.value;
        (bool success, ) = address(parentContract).call{value:msg.value}(abi.encodeWithSignature("triggerPayment(uint256)", index));
        require(success, "Delivery did not work");
    }

    fallback () external {
    }
}

How do these 2 contracts interact?

createItem

When createItem() is called Item item = new Item(this, _price, item_index), creates a new instance of the Item contract based on the price provided and index counter.

this : the current contract, explicitly convertible to address.

this is passed into the child contract's constructor (Item{}), for the field ItemManager _parentContract, where it eventually assigned to variable parentContract

parentContract = _parentContract; 
// evaluates to:
parentContract = this;

This is to store the parent contract association.

struc Item {}

struc Item now has Item _item; which is a contract object. It is assigned value under the createItem(), after the new item contract object has been created.

item_list[item_index]._item = item;

Thoughts

This approach allows us to create an item using the parent contract, assign values to both parent and child

Last updated