Contract-Invocation

當函式呼叫不同的合約時,如何使用合約的 msg.value 和 msg.sender 的值

  • March 16, 2022

我正在研究 Solidity 並試圖了解它是如何工作的。

從“Solidity 部分範例”中的安全遠端購買開始,我嘗試使用文件( https://docs.soliditylang.org/en/v0.8.12/solidity-by-example.html#safe-remote-purchase )程式碼就像物件導向的語言一樣。我想了解編寫以下程式碼的最佳方法是什麼。

特別是,我創建了兩個不同的合約:singlePuchase 和 Puchase。

這是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 想要管理更多的“singlePuchase 元素”並包含一個singlePuchase 實例數組。這裡的程式碼::

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
}

當我呼叫該函式時propostaVendita,該行prodotti.push(new singlePuchase(prod,i))返回一個錯誤,因為合約 Puchase 呼叫了具有不同值的 msg.value 和 msg.sender 的 singlePuchase 建構子。

我試圖解決這個問題delegatecall,Puchase 中的 singlePuchase 建構子返回:(true, 0x0)

我該如何解決這個問題?如何從原始合約 (Puchase) 使用 msg.value 和 msg.sender 到被呼叫合約 (singlePuchase)?

如果您在合約 A 中創建新合約 B,則 msg.sender(在 B 的建構子呼叫中)將是第一個合約 A 而不是原始呼叫者。

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

在這種情況下,您可以簡單地使用tx.origin它,它始終指向發起交易的帳戶。但是通常不鼓勵使用 tx.origin ,因為它會導致混淆(儘管在這種情況下非常好)。

更合適的方法是將所有者地址作為參數傳遞給 B 的建構子。然後合約 a 將呼叫new singlePuchase(msg.sender, prod,i)

編輯:這裡是在建構子中添加 msg.sender 和 msg.value 的變化。

   constructor(address venditore_, string memory prod, uint i) payable{
       ...
       venditore = payable(venditore_);
   }
prodotti.push(new singlePuchase{value: msg.value}(msg.sender, "", 0));

引用自:https://ethereum.stackexchange.com/questions/123880