Smart-Contract-Wallets

DelegateCall 後狀態變數未更新

  • January 19, 2022

我部署了兩個合約“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.

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