1

I'm studing Solidity and tring to understand how it works.

Starting from Safe Remote Purchase in the "Solidity section by example" the doc (https://docs.soliditylang.org/en/v0.8.12/solidity-by-example.html#safe-remote-purchase) I tried to use the code as in an object-oriented language. I would like to understand what is the best way to write the following code.

In particular, I create two different contract: singlePuchase and Puchase.

This is singlePuchase:

contract singlePuchase{
    string nome;
    uint importo;
    Stages stage;
    address payable venditore;
   
    enum Stages{
        MessaVendita,
        AccettaCliente,
        ProdottoInviato,
        VenditaConclusa
    }
    
    // si impostano le variabili base quali: nome del prodotto, importo, lo stato iniziale (MessaVendita), chi è il venditore
    constructor(string memory prod, uint i) payable{
        require(i*2000000000000000000==msg.value, string(abi.encodePacked("importo non valido: ", Strings.toString(msg.value)," e ", Strings.toString(i*2000000000000000000))));
        nome = prod;
        importo = i*1000000000000000000;
        stage = Stages.MessaVendita;
        venditore = payable(msg.sender);
    }

    \\ other function

}

Puchase wants to manage more "singlePuchase elements" and contains an array of singlePuchase instance. Here the code: :

contract Puchase{
    singlePuchase[] prodotti;
    mapping(string => uint) mapPosizione;

    address creatore;

    //definiamo del creatore e garante
    constructor(){
        creatore = msg.sender;
        prodotti.push(new singlePuchase(string(""),0));
    }

    function propostaVendita(string memory prod, uint i) public payable{
        if(mapPosizione[prod] == 0){
            require(msg.sender!=creatore);
            prodotti.push(new singlePuchase(prod,i));
        } else {
            prodotti[mapPosizione[prod]].modificaVendita(i);
        }
    }
    
    // other function
}

When I call the function propostaVendita the line prodotti.push(new singlePuchase(prod,i)) return an error because the contract Puchase call the singlePuchase constractor with different value of msg.value and msg.sender.

I tried to resolve the problem with delegatecall, the singlePuchase constructor in Puchase return: (true, 0x0).

How can I resolve the ploblem? How is possible use msg.value and msg.sender from the original contract (Puchase) to the called contract (singlePuchase)?

1 Answer 1

0

If you create a new contract B inside a contract A, the msg.sender (in the constructor call of B) will be the first contract A and not the original caller.

    constructor(string memory prod, uint i) payable{
        ...
        venditore = payable(tx.origin);
    }

You could simply use tx.origin in this case, which always points to the account initiating the transaction. However generally, the use of tx.origin is discouraged, because it can lead to confusion (although in this case perfectly fine).

A more proper way would be to pass the owner address as a parameter to the constructor of B. Contract a would then call new singlePuchase(msg.sender, prod,i)

Edit: Here the changes with adding msg.sender and msg.value in the constructor.

    constructor(address venditore_, string memory prod, uint i) payable{
        ...
        venditore = payable(venditore_);
    }
prodotti.push(new singlePuchase{value: msg.value}(msg.sender, "", 0));
2
  • thank you! Can I find such a solution for msg.value or do I have to pass msg.value as a function paramiter?
    – juole
    Commented Mar 16, 2022 at 16:50
  • updated the answer.
    – phaze
    Commented Mar 16, 2022 at 18:34

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.