我部署了两个契约“WalletLibrary”和“Wallet”:Wallet delegateCall()中的大多数函数--来自WalletLibrary的函数。我想重新创建一个攻击,通过触发Wallet的回退函数,从WalletLibrary调用WalletLibrary()函数。然而,当我这样做时,钱包的所有者会被更新到我的地址,但是WalletLibrary中的那个不会。此外,WalletLibrary的所有者在部署时是0000000000000000 (我可能在部署时做错了什么吗?),我希望所有者应该是我部署它的地址。
根据我的理解,当我在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);
}
}Wallet.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);
}
}发布于 2022-01-19 09:52:50
当您使用委托时,它将在调用者的上下文中执行目标的代码。这意味着当您的Wallet合同使用委托给您的WalletLibrary时,它将使用来自库的代码,而使用来自Wallet的状态(例如owner、student等)。
因此,要更改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
复制相似问题