25952 - [SC - Insight] The smart contract could be inoperable due to w...
Previous25935 - [SC - Insight] Permissive Fallback FunctionNext26012 - [SC - Insight] getTransactionIds will break at some point runn...
Last updated
Was this helpful?
Was this helpful?
function confirmTransaction(uint transactionId)
public
ownerExists(msg.sender)
transactionExists(transactionId)
notConfirmed(transactionId, msg.sender)
{
confirmations[transactionId][msg.sender] = true;
Confirmation(msg.sender, transactionId);
executeTransaction(transactionId);
} function executeTransaction(uint transactionId)
public
notExecuted(transactionId)
{
if (isConfirmed(transactionId)) {
Transaction tx = transactions[transactionId];
tx.executed = true;
if (tx.destination.call.value(tx.value)(tx.data))
Execution(transactionId);
else {
ExecutionFailure(transactionId);
tx.executed = false;
}
}
}
function isConfirmed(uint transactionId)
public
constant
returns (bool)
{
uint count = 0;
for (uint i=0; i<owners.length; i++) {
if (confirmations[transactionId][owners[i]])
count += 1;
if (count == required)
return true;
}
} function replaceOwner(address owner, address newOwner)
public
onlyWallet
ownerExists(owner)
ownerDoesNotExist(newOwner)
+ notNull(newOwner)
{
for (uint i=0; i<owners.length; i++)
if (owners[i] == owner) {
owners[i] = newOwner;
break;
}
isOwner[owner] = false;
isOwner[newOwner] = true;
OwnerRemoval(owner);
OwnerAddition(newOwner);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
interface IMultiSigWallet {
function submitTransaction(address destination, uint value, bytes memory data) external returns (uint transactionId);
function confirmTransaction(uint transactionId) external;
function revokeConfirmation(uint transactionId) external;
function executeTransaction(uint transactionId) external;
function getOwners() external returns (address[] memory);
function required() external returns (uint);
function isOwner(address owner) external returns (bool);
}
contract MultiSigWalletTest is Test {
IMultiSigWallet wallet;
function setUp() public {
wallet = IMultiSigWallet(0x2028834B2c0A36A918c10937EeA71BE4f932da52);
}
function testUpdateOwner() public {
address[] memory owners = wallet.getOwners();
assertEq(owners.length, 6);
assertEq(wallet.required(),4);
address destination = address(wallet);
uint value = 0;
bytes memory removeOwnerData1 = abi.encodeWithSignature("removeOwner(address)", owners[4]);
bytes memory removeOwnerData2 = abi.encodeWithSignature("removeOwner(address)", owners[5]);
//remove 2 owners
vm.startPrank(owners[0]);
uint transactionId1 = wallet.submitTransaction(destination, value, removeOwnerData1);
uint transactionId2 = wallet.submitTransaction(destination, value, removeOwnerData2);
vm.stopPrank();
for (uint i=1; i<4; i++) {
vm.startPrank(owners[i]);
wallet.confirmTransaction(transactionId1);
wallet.confirmTransaction(transactionId2);
vm.stopPrank();
}
owners = wallet.getOwners();
//the total number of owners is 4, equals to the threshold `required`
assertEq(owners.length, 4);
assertEq(wallet.required(),4);
//replace the last owner to address(0)
bytes memory replaceOwnerData = abi.encodeWithSignature("replaceOwner(address,address)",owners[3], address(0));
vm.prank(owners[0]);
uint transactionId = wallet.submitTransaction(destination, value, replaceOwnerData);
for (uint i=1; i<4; i++) {
vm.prank(owners[i]);
wallet.confirmTransaction(transactionId);
}
//the last owner became address(0), threshold i still 4 and only 3 available owners left.afterwards the threshold can never be met
owners = wallet.getOwners();
assertEq(owners.length, 4);
assertEq(wallet.required(),4);
assertEq(owners[3], address(0));
assertEq(wallet.isOwner(address(0)), true);
}
}