MultisigWallet.sol 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. pragma solidity ^0.4.4;
  2. import "./Multisig.sol";
  3. import "./Shareable.sol";
  4. import "./DayLimit.sol";
  5. /*
  6. * MultisigWallet
  7. * usage:
  8. * bytes32 h = Wallet(w).from(oneOwner).execute(to, value, data);
  9. * Wallet(w).from(anotherOwner).confirm(h);
  10. */
  11. contract MultisigWallet is Multisig, Shareable, DayLimit {
  12. // TYPES
  13. // Transaction structure to remember details of transaction lest it need be saved for a later call.
  14. struct Transaction {
  15. address to;
  16. uint value;
  17. bytes data;
  18. }
  19. // CONSTRUCTOR
  20. // just pass on the owner array to the multiowned and
  21. // the limit to daylimit
  22. function MultisigWallet(address[] _owners, uint _required, uint _daylimit)
  23. Shareable(_owners, _required)
  24. DayLimit(_daylimit) { }
  25. // METHODS
  26. // kills the contract sending everything to `_to`.
  27. function kill(address _to) onlymanyowners(sha3(msg.data)) external {
  28. suicide(_to);
  29. }
  30. // gets called when no other function matches
  31. function() payable {
  32. // just being sent some cash?
  33. if (msg.value > 0)
  34. Deposit(msg.sender, msg.value);
  35. }
  36. // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit.
  37. // If not, goes into multisig process. We provide a hash on return to allow the sender to provide
  38. // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
  39. // and _data arguments). They still get the option of using them if they want, anyways.
  40. function execute(address _to, uint _value, bytes _data) external onlyOwner returns (bytes32 _r) {
  41. // first, take the opportunity to check that we're under the daily limit.
  42. if (underLimit(_value)) {
  43. SingleTransact(msg.sender, _value, _to, _data);
  44. // yes - just execute the call.
  45. if (!_to.call.value(_value)(_data)) {
  46. throw;
  47. }
  48. return 0;
  49. }
  50. // determine our operation hash.
  51. _r = sha3(msg.data, block.number);
  52. if (!confirm(_r) && txs[_r].to == 0) {
  53. txs[_r].to = _to;
  54. txs[_r].value = _value;
  55. txs[_r].data = _data;
  56. ConfirmationNeeded(_r, msg.sender, _value, _to, _data);
  57. }
  58. }
  59. // confirm a transaction through just the hash. we use the previous transactions map, txs, in order
  60. // to determine the body of the transaction from the hash provided.
  61. function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) {
  62. if (txs[_h].to != 0) {
  63. if (!txs[_h].to.call.value(txs[_h].value)(txs[_h].data)) {
  64. throw;
  65. }
  66. MultiTransact(msg.sender, _h, txs[_h].value, txs[_h].to, txs[_h].data);
  67. delete txs[_h];
  68. return true;
  69. }
  70. }
  71. function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external {
  72. this.setDailyLimit(_newLimit);
  73. }
  74. function resetSpentToday() onlymanyowners(sha3(msg.data)) external {
  75. this.resetSpentToday();
  76. }
  77. // INTERNAL METHODS
  78. function clearPending() internal {
  79. uint length = pendingsIndex.length;
  80. for (uint i = 0; i < length; ++i) {
  81. delete txs[pendingsIndex[i]];
  82. }
  83. super.clearPending();
  84. }
  85. // FIELDS
  86. // pending transactions we have at present.
  87. mapping (bytes32 => Transaction) txs;
  88. }