Solidity
當孩子擁有時如何使用工廠模式?
我試圖推斷工廠如何呼叫 EOA 擁有的子契約。
這個項目的目標是製作一個 StoreFactory 合約,允許任何人部署他們自己的 Store 合約。部署商店的商家應該是所有者,並且應該是唯一可以從購買中提取 ETH 的人。以下是我試圖修復以啟用此流程的一些虛擬碼。
經過一番研究,我相信我需要使用delegatecall,但我不確定。
商店工廠:
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "./Store.sol"; contract StoreFactory { uint256 id; mapping(uint256 => Store) storeMapping; function createStore() public { Store store = new Store(); store.transferOwnership(msg.sender()); storeMapping[id] = child; id++; } function depositEth(uint256 _id) public { storeMapping[_id].depositEth(); } function withdrawEth(uint256 _id) public { storeMapping[_id].withdrawEth(); } }
儲存(子)契約:
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "openzeppelin-contracts/contracts/access/Ownable.sol"; contract Store is Ownable { function depositEth() public payable {} function withdrawEth() public onlyOwner { uint amount = address(this).balance; (bool success, ) = msg.sender.call{value: amount}(""); require(success, "Failed to send Ether"); } }
如果工廠正在打電話,那麼創建商店的原始 EOA 帳戶如何提取資金?這就是我想要完成的。
為什麼要 msg.sender 成為子合約的所有者?還有,誰 msg.sender 應該在這裡?是您(如協議的設計者)還是使用者?如果是你,我建議你不要那樣做,讓工廠擁有孩子。如果它是使用者,那麼您仍然可以這樣做,但希望他們也成為契約所有者是有意義的。
在這種情況下,您可以執行以下操作:
工廠 :
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "./Child.sol"; contract ChildFactory { uint256 id; mapping(uint256 => Child) childMapping; function createChild() public { Child child = new Child(address(this)); child.transferOwnership(msg.sender); childMapping[id] = child; id++; } function depositEth(uint256 _id) public { childMapping[_id].depositEth(); } function withdrawEth(uint256 _id) public { require(msg.sender == childMapping[_id].owner()); childMapping[_id].factoryWithdrawEth(msg.sender); } }
孩子 :
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "openzeppelin-contracts/contracts/access/Ownable.sol"; contract Child is Ownable { address factory; constructor(address _factory) { factory = _factory; } function depositEth() public payable {} function ownerWithdraw() public onlyOwner { _withdrawEth(msg.sender); } function factoryWithdrawEth(address to) public { require(msg.sender == factory); _withdrawEth(to); } function _withdrawEth(address account) internal { uint amount = address(this).balance; (bool success, ) = payable(account).call{value: amount}(""); require(success, "Failed to send Ether"); } }