當函式呼叫不同的合約時,如何使用合約的 msg.value 和 msg.sender 的值
我正在研究 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));