pragma solidity ^0.4.15; /** * @title MultiSigStub * Contract that delegates calls to a library to build a full MultiSigWallet that is cheap to create. */ contract MultiSigStub { address[] public owners; address[] public tokens; mapping (uint => Transaction) public transactions; mapping (uint => mapping (address => bool)) public confirmations; uint public transactionCount; struct Transaction { address destination; uint value; bytes data; bool executed; } function MultiSigStub(address[] _owners, uint256 _required) { //bytes4 sig = bytes4(sha3("constructor(address[],uint256)")); bytes4 sig = 0x36756a23; uint argarraysize = (2 + _owners.length); uint argsize = (1 + argarraysize) * 32; uint size = 4 + argsize; bytes32 mData = _malloc(size); assembly { mstore(mData, sig) codecopy(add(mData, 0x4), sub(codesize, argsize), argsize) } _delegatecall(mData, size); } modifier delegated { uint size = msg.data.length; bytes32 mData = _malloc(size); assembly { calldatacopy(mData, 0x0, size) } bytes32 mResult = _delegatecall(mData, size); _; assembly { return(mResult, 0x20) } } function() payable delegated { } function submitTransaction(address destination, uint value, bytes data) public delegated returns (uint) { } function confirmTransaction(uint transactionId) public delegated { } function watch(address _tokenAddr) public delegated { } function setMyTokenList(address[] _tokenList) public delegated { } /// @dev Returns the confirmation status of a transaction. /// @param transactionId Transaction ID. /// @return Confirmation status. function isConfirmed(uint transactionId) public constant delegated returns (bool) { } /* * Web3 call functions */ function tokenBalances(address tokenAddress) public constant delegated returns (uint) { } /// @dev Returns number of confirmations of a transaction. /// @param transactionId Transaction ID. /// @return Number of confirmations. function getConfirmationCount(uint transactionId) public constant delegated returns (uint) { } /// @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 delegated returns (uint) { } /// @dev Returns list of owners. /// @return List of owner addresses. function getOwners() public constant returns (address[]) { return owners; } /// @dev Returns list of tokens. /// @return List of token addresses. function getTokenList() public constant returns (address[]) { return tokens; } /// @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]; } } function _malloc(uint size) private returns(bytes32 mData) { assembly { mData := mload(0x40) mstore(0x40, add(mData, size)) } } function _delegatecall(bytes32 mData, uint size) private returns(bytes32 mResult) { address target = 0xc0FFeEE61948d8993864a73a099c0E38D887d3F4; //Multinetwork mResult = _malloc(32); bool failed; assembly { failed := iszero(delegatecall(sub(gas, 10000), target, mData, size, mResult, 0x20)) } assert(!failed); } }