0

I have a hard time distinguishing between:

  • a smart-contract, as the set of guidelines dictating what should happen during a transaction
  • a transaction as the act of transferring funds from one address to another
  • a record of a transaction as an immutable record of data in regards to a transaction that took place
  • using a transaction as a way to also transfer ownership of data

In the below smart contract, what I want to achieve is the following:

  1. An msg.sender can create an Apple with some default properties and become its owner
  2. An owner can change the price of an Apple they own
  3. An owner can own several Apples
  4. An owner can sell an Apple to a buyer

Bear in mind that this is my first attempt at creating a smart contract. I haven't even tested it, so I'm assuming its full of errors.

pragma solidity ^0.8.7;

contract MyContract{
    struct Apple{
        string id
        address payable owner;
        string propertyX; // ~100Kb
        uint price;
    }

    mapping(string => Apple) Apples;

    function createApple(string calldata appleId, string calldata propertyX, uint calldata price) public {
      require(msg.sender != address(0), 'Apple creator address not found');
      Apples[appleId] = Apple(appleId, msg.sender, propertyX, price);
    }

    function changeApplePrice(string calldata appleId, uint calldata price) public {
      require(Apples[appleId], 'Apple not found');
      require(msg.sender == Apples[appleId].owner, 'Only the owner of this apple can change its price');
      Apples[appleId].price = price;
    }

    function getApple(string calldata appleId) public returns (string, address, string, uint) {
      require(Apples[appleId], 'Apple not found');
      require(msg.sender == Apples[appleId].owner, 'Only the owner can see the contents of this Apple'); 
      return (appleId, Apples[appleId].owner, Apples[appleId].propertyX, Apples[appleId].price)
    }

    function buyApple(string calldata appleId) public {
        require(Apples[appleId], 'Apple not found');
        require(msg.sender != address(0), 'Buyer address not found');
        require(msg.value >= uint(Apples[appleId].price, 'Not enough money to buy this Apple')
       
        // Buyer pays current owner for the Apple with id {appleId}
        Apples[appleId].owner.transfer(Apples[appleId].price);

        // set the new apple owner
        Apples[appleId].owner = msg.sender;
    }
}

When I call the public method buyApple(...) using the web3.eth.Contract API what should happen is more or less obvious to me: I expect some funds to be transferred from msg.sender to Apples[appleId].owner and then an immutable record of that transaction to be stored on the Ethereum blockchain, containing the 2 addresses involved and the value of the funds transferred.

Question 1: When the transaction takes place I assume that I (the developer calling the method) will also have access to the transaction hash. I would like to store that transaction hash in a traditional DB and then later be able to retrieve some information about that transaction. But the information retrieve will only contain the addresses and funds involved I'm assuming, but what about, the Apple (appleId) it was referring to. How can I get that information from the record of the transaction?

Question 2: What happens when I call the public method createApple(...) using the web3.eth.Contract API is less obvious to me. What this method is supposed to do is "create an apple" but "where" in the blockchain will that information reside ? Is it just another block that gets added to the blockchain that will store all the properties for that Apple? But I need this block to be mutable since I want to be able to update whenever changeApplePrice() or buyApple() are called. And yet a blockchain is a collection of immutable data so how will this work ?

Question 3: As more Apples are created, more space will be taken up. Who pays for that extra space used every time ? Is the cost paid by msg.sender during createApple(...) ? Does every call to a public smart contract method come with some cost that the msg.sender will be charged with ?

I know this was long but I couldn't find clear answers to any of the above. Thank you in advance for your help.

1 Answer 1

1

Question 1

How can I get that information from the record of the transaction?

Answer:

You can emit an event in the function "buyApple" and use getPastEvents ir order to get the data you need

Question 2

but "where" in the blockchain will that information reside?

Answer:

in the account storage trie

from ethereum site

Storage trie is where all contract data lives. There is a separate storage trie for each account. To retrieve values at specific storage positions at a given address the storage address, integer position of the stored data in the storage, and the block ID are required. These can then be pased as arguments to the eth_getStorageAt defined in the JSON-RPC API, e.g. to retrieve the data in storage slot 0 for address

take a look at the following diagram from here:

enter image description here

Question 3

Does every call to a public smart contract method come with some cost that the msg.sender will be charged with?

Answer: yes

Ethereum Gas is a unit that measures the amount of computational effort that it will take to execute certain operations.

Every single operation that takes part in Ethereum, be it a transaction or smart contract execution requires some amount of gas.

Miners get paid an amount in Ether which depends on to the total amount of gas it took them to execute a complete operation.

take a look at this video and this article

1
  • Thank you, your answer to Q1 was most enlightening (!) Commented Jun 6, 2022 at 21:58

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.