DelegateCall 後狀態變數未更新
我部署了兩個合約“WalletLibrary”和“Wallet”:Wallet delegateCall() 中的大部分函式是 WalletLibrary 中的函式。我想重新創建一個攻擊,我通過觸發 Wallet 的回退函式從 WalletLibrary 呼叫 initWallet() 函式。但是,當我這樣做時,錢包中的所有者會更新為我的地址,但 WalletLibrary 中的所有者不是。此外,WalletLibrary 的所有者在部署時是 00000000000000000(我可能在部署時做錯了什麼嗎?),我希望所有者應該是我部署它的地址。
據我了解,當我在 Wallet 中更新某個變數時,它也應該在 WalletLibrary 中更新,因為 delegateCall() 保留了上下文,對吧?我的問題是,為什麼它不起作用。請告訴我,如果我有什麼問題。希望任何人都可以提供幫助。
下面,兩個合約的程式碼……
WalletLibrary.sol:
pragma solidity ^0.5.4; contract WalletLibrary { address walletLibrary; address payable owner; address payable student; event LogValue(uint256 exitcode,uint256 amount); function initWallet(address payable _owner) public payable { owner = _owner; } function getOwner() public view returns (address payable) { return owner; } function changeOwner(address payable new_owner) public returns (bool success) { if (msg.sender == owner) { owner = new_owner; return true; } else { return false; } } function withdraw(uint256 amount) public returns (bool success) { if (msg.sender == owner) { return owner.send(amount); } else { return false; } } function () external payable { emit LogValue(200,msg.value); } }
錢包.sol:
pragma solidity ^0.5.4; contract Wallet { address walletLibrary; address payable owner; address payable student; event LogValue(uint256 exitcode,uint256 amount); // constructor, called once when this contract is created constructor(address payable _student, address lib) public payable { student = _student; walletLibrary = lib; // hardcode lib address at deploy time // init the owner with the respective lib contract walletLibrary.delegatecall(abi.encodeWithSignature("initWallet(address)", msg.sender)); } function getOwner() public view returns (address payable) { return owner; } function getWalletLibrary() public view returns (address) { return walletLibrary; } function withdraw(uint256 amount) public returns (bool) { (bool success, bytes memory data) = walletLibrary.delegatecall(abi.encodeWithSignature("withdraw(uint256)", amount)); if ( success ) { emit LogValue(200,amount); } else { emit LogValue(401,amount); } return success; } function changeOwner(address payable new_owner) public returns (bool) { (bool success, bytes memory data) = walletLibrary.delegatecall(abi.encodeWithSignature("changeOwner(address)", new_owner)); return success; } function getStudent() public view returns (address) { return student; } // fallback function gets called if no other function matches call function () external payable { emit LogValue(301,msg.value); require( tx.origin == student ); walletLibrary.delegatecall(msg.data); } }
當您使用委託呼叫時,它將在呼叫者的上下文中執行目標的****程式碼。這意味著當您的合約對您使用委託呼叫時,它將使用庫中的程式碼,但使用.
Wallet``WalletLibrary``owner``student``Wallet
因此,要更改狀態,
WalletLibrary
您必須直接與該合約進行互動。可以在此處找到委託呼叫的詳細介紹:https ://medium.com/coinmonks/delegatecall-calling-another-contract-function-in-solidity-b579f804178c
owner
你的是WalletLibrary
因為0x0000...0000
你沒有任何建構子,因此所有者沒有被初始化。在Wallet
你呼叫initWallet
函式來執行此操作,因此Wallet
所有者設置為msg.sender
.