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:
- An
msg.sender
can create anApple
with some default properties and become itsowner
- An
owner
can change theprice
of anApple
they own - An
owner
can own severalApple
s - An
owner
can sell anApple
to abuyer
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 Apple
s 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.