pragma solidity ^0.5.0;
contract MultiSignatureWallet {
uint constant public MAX_OWNER_COUNT = 2;
event Confirmation(address indexed sender, uint indexed transactionId);
event Revocation(address indexed sender, uint indexed transactionId);
event Submission(uint indexed transactionId);
event Execution(uint indexed transactionId);
event ExecutionFailure(uint indexed transactionId);
event Deposit(address indexed owner);
event RequirementChange(uint required);
mapping (uint => Transaction) public transactions;
mapping (uint => mapping(address => bool)) public confirmations;
mapping (address => bool) public isOwner;
address[] public owners;
uint public required;
uint public transactionCount;
struct Transaction {
address destination;
uint value;
bytes data;
bool executed;
}
modifier onlyWallet() {
if (msg.sender !=address(this))
revert();
_;
}
modifier ownerDoesNotExist(address owner) {
if (isOwner[owner])
revert();
_;
}
modifier confirmed(uint transactionId, address owner) {
if (!confirmations[transactionId] [owner])
revert();
_;
}
modifier notConfirmed(uint transactionId, address owner) {
if (confirmations[transactionId][owner])
revert();
_;
}
modifier notExecuted(uint transactionId) {
if (transactions[transactionId].executed)
revert();
_;
}
modifier notNull(address _address) {
if (_address == address(0))
revert();
_;
}
modifier validRequirement( uint ownerCount, uint _required) {
if ( _required > ownerCount
|| _required == 0
|| ownerCount == 0)
revert();
_;
}
/*
* Public functions
*/
/// @dev Contract constructor sets initial owners and required number of confirmations.
/// @param _owners List of initial owners.
/// @param _required Number of required confirmations.
function MultiSigWallet(address[] memory _owners, uint _required)
public
validRequirement(_owners.length, _required)
{
for (uint i=0; i<_owners.length; i++) {
if (isOwner[_owners[i]] || _owners[i] == address (0))
revert();
isOwner[_owners[i]] = true;
}
owners = _owners;
required = _required;
}
/// @dev Allows an owner to submit and confirm a transaction.
/// @param destination Transaction target address.
/// @param value Transaction ether value.
/// @param data Transaction data payload.
/// @return Returns transaction ID.
function submitTransaction(address destination, uint value, bytes
memory data)
public
returns (uint transactionId)
{
require(isOwner[msg.sender]);
transactionId = addTransaction(destination, value, data);
confirmTransaction(transactionId);
}
/// @dev Allows an owner to confirm a transaction.
/// @param transactionId Transaction ID.
function confirmTransaction(uint transactionId)
public
{
require(isOwner[msg.sender]);
require(transactions[transactionId].destination != address (0));
require(confirmations[transactionId][msg.sender] == false);
confirmations[transactionId][msg.sender] = true;
executeTransaction(transactionId);
}
/// @dev Allows an owner to revoke a confirmation for a transaction.
/// @param transactionId Transaction ID.
function revokeConfirmation(uint transactionId)
public
{
require(transactions[transactionId].executed == false);
}
/// @dev Allows anyone to execute a confirmed transaction.
/// @param transactionId Transaction ID.
function executeTransaction(uint transactionId)
public
{
require(transactions[transactionId].executed == false);
if (isConfirmed(transactionId)) {
Transaction storage t = transactions[transactionId];
t.executed = true;
(bool success, bytes memory data) =
t.destination.call.value(t.value)(t.data);
if (success)
emit Execution(transactionId);
else {
emit ExecutionFailure(transactionId);
t.executed = false;
}
}
}
/*
* (Possible) Helper Functions
*/
/// @dev Returns the confirmation status of a transaction.
/// @param transactionId Transaction ID.
/// @return Confirmation status.
function isConfirmed(uint transactionId)
public
view
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;
}
}
/// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet.
/// @param destination Transaction target address.
/// @param value Transaction ether value.
/// @param data Transaction data payload.
/// @return Returns transaction ID.
function addTransaction(address destination, uint value, bytes memory data)
internal
returns (uint transactionId)
{
transactionId = transactionCount;
transactions[transactionId] = Transaction({
destination: destination,
value: value,
data: data,
executed: false
});
transactionCount +=1;
emit Submission(transactionId);
}
}
-
The problem is before this snippet.– Rob HitchensCommented Jan 23, 2019 at 20:03
-
You probably missed a right curly brace above this.– user19510Commented Jan 23, 2019 at 21:06
-
Oh, I updated it and I'm seeing the same error.. Error: Returned error: VM Exception while processing transaction: revert– Casmir PattersonCommented Jan 23, 2019 at 22:45
-
I assume you've been investigating the issue. What have you tried so far, and where did you get stuck?– user19510Commented Jan 24, 2019 at 0:06
1 Answer
Your contract is called MultiSignatureWallet and you have a function that is supposed to be a constructor but it is called MultiSigWallet (old style constructors should have exactly same name as the contract).
As such, it does not behave as a constructor. So, you should rename MultiSigWallet to constructor.
If after deploying the contract you run the MultiSigWallet function (or constructor after you apply the fix and redeploy the contract) and then run submitTransaction function then it should work (it worked for me on remix).
If you don't run the constructor function, which then will not populate the owners array and number of owners required for the multi-signature wallet, then your submit fails.
I suggest that you review your code and fix these points.