multisig separated files and better stub contract

This commit is contained in:
Ricardo Guilherme Schmidt 2017-08-08 04:21:17 -03:00
parent 902129d639
commit 9c2775d87f
3 changed files with 170 additions and 187 deletions

View File

@ -0,0 +1,13 @@
pragma solidity ^0.4.11;
import "./MultiSigStub.sol";
contract MultiSigFactory {
event Create(address indexed caller, address createdContract);
function create(address[] owners, uint required) returns (MultisigStub stub){
stub = new MultiSigStub(owners, required);
Create(msg.sender, stub);
}
}

134
contracts/MultiSigStub.sol Normal file
View File

@ -0,0 +1,134 @@
pragma solidity ^0.4.11;
/**
* @title MultiSigStub
* Contact that delegates calls to a library to build a full MultiSigWallet that is cheap to create.
*/
contract MultiSigStub {
mapping (uint => Transaction) public transactions;
mapping (uint => mapping (address => bool)) public confirmations;
address[] public owners;
struct Transaction {
address destination;
uint value;
bytes data;
bool executed;
}
function MultiSigStub(address[] _owners, uint _required) {
bytes4 sig = bytes4(sha3("Constructor(address[],uint256)"));
uint argarraysize = (2 + _owners.length);
uint argsize = (1 + argarraysize) * 32;
uint size = 4 + argsize;
bytes32 m_data = _malloc(size);
assembly {
mstore(m_data, sig)
codecopy(add(m_data, 0x4), sub(codesize, argsize), argsize)
}
_delegatecall(m_data, size);
}
function()
payable
{
uint size = msg.data.length;
bytes32 m_data = _malloc(size);
assembly {
calldatacopy(m_data, 0x0, size)
}
bytes32 m_result = _delegatecall(m_data, size);
assembly {
return(m_result, 0x20)
}
}
function _malloc(uint size)
private
returns(bytes32 m_data)
{
assembly {
m_data := mload(0x40)
mstore(0x40, add(m_data, size))
}
}
function _delegatecall(bytes32 m_data, uint size)
private
returns(bytes32 m_result)
{
address target = 0xcafecafecafecafecafecafecafecafecafecafe; //will be replaced by correct value
m_result = _malloc(32);
bool failed;
assembly {
failed := iszero(delegatecall(sub(gas, 10000), target, m_data, size, m_result, 0x20))
}
assert(!failed);
}
/// @dev Returns list of owners.
/// @return List of owner addresses.
function getOwners()
public
constant
returns (address[])
{
return owners;
}
/// @dev Returns array with owner addresses, which confirmed transaction.
/// @param transactionId Transaction ID.
/// @return Returns array of owner addresses.
function getConfirmations(uint transactionId)
public
constant
returns (address[] _confirmations)
{
address[] memory confirmationsTemp = new address[](owners.length);
uint count = 0;
uint i;
for (i=0; i<owners.length; i++)
if (confirmations[transactionId][owners[i]]) {
confirmationsTemp[count] = owners[i];
count += 1;
}
_confirmations = new address[](count);
for (i=0; i<count; i++)
_confirmations[i] = confirmationsTemp[i];
}
/// @dev Returns list of transaction IDs in defined range.
/// @param from Index start position of transaction array.
/// @param to Index end position of transaction array.
/// @param pending Include pending transactions.
/// @param executed Include executed transactions.
/// @return Returns array of transaction IDs.
function getTransactionIds(uint from, uint to, bool pending, bool executed)
public
constant
returns (uint[] _transactionIds)
{
uint[] memory transactionIdsTemp = new uint[](transactionCount);
uint count = 0;
uint i;
for (i=0; i<transactionCount; i++)
if ( pending && !transactions[i].executed
|| executed && transactions[i].executed)
{
transactionIdsTemp[count] = i;
count += 1;
}
_transactionIds = new uint[](to - from);
for (i=from; i<to; i++)
_transactionIds[i - from] = transactionIdsTemp[i];
}
}

View File

@ -13,7 +13,25 @@ contract ERC20 {
contract MultiSigTokenWallet {
address constant _walletLibrary = 0x0;
address[] public owners;
mapping (uint => Transaction) public transactions;
mapping (uint => mapping (address => bool)) public confirmations;
mapping (address => bool) public isOwner;
mapping (address => uint) public tokenBalances;
mapping (address => bool) public ignoredTokens;
address[] public tokens;
uint public required;
uint public transactionCount;
uint nonce;
struct Transaction {
address destination;
uint value;
bytes data;
bool executed;
}
uint constant public MAX_OWNER_COUNT = 50;
event Confirmation(address indexed _sender, uint indexed _transactionId);
@ -28,25 +46,6 @@ contract MultiSigTokenWallet {
event RequirementChange(uint _required);
event IgnoredToken(address indexed _owner, address _token, bool ignored);
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;
mapping (address => uint) public tokenBalances;
mapping (address => bool) public ignoredTokens;
address[] public tokens;
uint nonce;
struct Transaction {
address destination;
uint value;
bytes data;
bool executed;
}
modifier onlyWallet() {
require (msg.sender == address(this));
_;
@ -88,7 +87,7 @@ contract MultiSigTokenWallet {
}
modifier validRequirement(uint ownerCount, uint _required) {
require ( ownerCount <= MAX_OWNER_COUNT
require (ownerCount <= MAX_OWNER_COUNT
&& _required <= ownerCount
&& _required != 0
&& ownerCount != 0);
@ -109,10 +108,11 @@ contract MultiSigTokenWallet {
/// @dev Contract constructor sets initial owners and required number of confirmations.
/// @param _owners List of initial owners.
/// @param _required Number of required confirmations.
function MultiSigTokenWallet(address[] _owners, uint _required)
function Constructor(address[] _owners, uint _required)
public
validRequirement(_owners.length, _required)
{
require(owners.length == 0 && required == 0);
for (uint i=0; i<_owners.length; i++) {
require (!isOwner[_owners[i]] && _owners[i] != 0);
isOwner[_owners[i]] = true;
@ -535,168 +535,4 @@ contract MultiSigTokenWallet {
_transactionIds[i - from] = transactionIdsTemp[i];
}
}
contract EnhancedMultiSig {
address constant _walletLibrary = 0xf5f6853e0ebA27074A804358eEdF4E89eFaebc98;
uint constant public MAX_OWNER_COUNT = 50;
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 _sender, uint _value);
event TokenDeposit(address _token, address indexed _sender, uint _value);
event OwnerAddition(address indexed _owner);
event OwnerRemoval(address indexed _owner);
event RequirementChange(uint _required);
event IgnoredToken(address indexed _owner, address _token, bool ignored);
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;
mapping (address => uint) public tokenBalances;
mapping (address => bool) public ignoredTokens;
address[] public tokens;
uint nonce;
struct Transaction {
address destination;
uint value;
bytes data;
bool executed;
}
// WALLET CONSTRUCTOR
function EnhancedMultiSig(address[] _owners, uint _required) {
require(_required > 0);
uint len = _owners.length;
require(len <= MAX_OWNER_COUNT);
require(len >= _required);
for (uint i=0; i < len; i++) {
require (!isOwner[_owners[i]] && _owners[i] != 0);
isOwner[_owners[i]] = true;
}
owners = _owners;
required = _required;
}
/// @dev Fallback function allows to deposit ether or other functions in library.
function()
payable
{
_walletLibrary.delegatecall(msg.data);
}
/// @dev Returns the confirmation status of a transaction.
/// @param transactionId Transaction ID.
/// @return Confirmation status.
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;
}
}
/*
* Web3 call functions
*/
/// @dev Returns number of confirmations of a transaction.
/// @param transactionId Transaction ID.
/// @return Number of confirmations.
function getConfirmationCount(uint transactionId)
public
constant
returns (uint count)
{
for (uint i=0; i<owners.length; i++)
if (confirmations[transactionId][owners[i]])
count += 1;
}
/// @dev Returns total number of transactions after filters are applied.
/// @param pending Include pending transactions.
/// @param executed Include executed transactions.
/// @return Total number of transactions after filters are applied.
function getTransactionCount(bool pending, bool executed)
public
constant
returns (uint count)
{
for (uint i=0; i<transactionCount; i++)
if ( pending && !transactions[i].executed
|| executed && transactions[i].executed)
count += 1;
}
/// @dev Returns list of owners.
/// @return List of owner addresses.
function getOwners()
public
constant
returns (address[])
{
return owners;
}
/// @dev Returns array with owner addresses, which confirmed transaction.
/// @param transactionId Transaction ID.
/// @return Returns array of owner addresses.
function getConfirmations(uint transactionId)
public
constant
returns (address[] _confirmations)
{
address[] memory confirmationsTemp = new address[](owners.length);
uint count = 0;
uint i;
for (i=0; i<owners.length; i++)
if (confirmations[transactionId][owners[i]]) {
confirmationsTemp[count] = owners[i];
count += 1;
}
_confirmations = new address[](count);
for (i=0; i<count; i++)
_confirmations[i] = confirmationsTemp[i];
}
/// @dev Returns list of transaction IDs in defined range.
/// @param from Index start position of transaction array.
/// @param to Index end position of transaction array.
/// @param pending Include pending transactions.
/// @param executed Include executed transactions.
/// @return Returns array of transaction IDs.
function getTransactionIds(uint from, uint to, bool pending, bool executed)
public
constant
returns (uint[] _transactionIds)
{
uint[] memory transactionIdsTemp = new uint[](transactionCount);
uint count = 0;
uint i;
for (i=0; i<transactionCount; i++)
if ( pending && !transactions[i].executed
|| executed && transactions[i].executed)
{
transactionIdsTemp[count] = i;
count += 1;
}
_transactionIds = new uint[](to - from);
for (i=from; i<to; i++)
_transactionIds[i - from] = transactionIdsTemp[i];
}
}
}