Heritable.sol 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. pragma solidity ^0.4.21;
  2. import "./Ownable.sol";
  3. /**
  4. * @title Heritable
  5. * @dev The Heritable contract provides ownership transfer capabilities, in the
  6. * case that the current owner stops "heartbeating". Only the heir can pronounce the
  7. * owner's death.
  8. */
  9. contract Heritable is Ownable {
  10. address private heir_;
  11. // Time window the owner has to notify they are alive.
  12. uint256 private heartbeatTimeout_;
  13. // Timestamp of the owner's death, as pronounced by the heir.
  14. uint256 private timeOfDeath_;
  15. event HeirChanged(address indexed owner, address indexed newHeir);
  16. event OwnerHeartbeated(address indexed owner);
  17. event OwnerProclaimedDead(address indexed owner, address indexed heir, uint256 timeOfDeath);
  18. event HeirOwnershipClaimed(address indexed previousOwner, address indexed newOwner);
  19. /**
  20. * @dev Throw an exception if called by any account other than the heir's.
  21. */
  22. modifier onlyHeir() {
  23. require(msg.sender == heir_);
  24. _;
  25. }
  26. /**
  27. * @notice Create a new Heritable Contract with heir address 0x0.
  28. * @param _heartbeatTimeout time available for the owner to notify they are alive,
  29. * before the heir can take ownership.
  30. */
  31. function Heritable(uint256 _heartbeatTimeout) public {
  32. setHeartbeatTimeout(_heartbeatTimeout);
  33. }
  34. function setHeir(address newHeir) public onlyOwner {
  35. require(newHeir != owner);
  36. heartbeat();
  37. emit HeirChanged(owner, newHeir);
  38. heir_ = newHeir;
  39. }
  40. /**
  41. * @dev Use these getter functions to access the internal variables in
  42. * an inherited contract.
  43. */
  44. function heir() public view returns(address) {
  45. return heir_;
  46. }
  47. function heartbeatTimeout() public view returns(uint256) {
  48. return heartbeatTimeout_;
  49. }
  50. function timeOfDeath() public view returns(uint256) {
  51. return timeOfDeath_;
  52. }
  53. /**
  54. * @dev set heir = 0x0
  55. */
  56. function removeHeir() public onlyOwner {
  57. heartbeat();
  58. heir_ = 0;
  59. }
  60. /**
  61. * @dev Heir can pronounce the owners death. To claim the ownership, they will
  62. * have to wait for `heartbeatTimeout` seconds.
  63. */
  64. function proclaimDeath() public onlyHeir {
  65. require(ownerLives());
  66. emit OwnerProclaimedDead(owner, heir_, timeOfDeath_);
  67. timeOfDeath_ = block.timestamp;
  68. }
  69. /**
  70. * @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
  71. */
  72. function heartbeat() public onlyOwner {
  73. emit OwnerHeartbeated(owner);
  74. timeOfDeath_ = 0;
  75. }
  76. /**
  77. * @dev Allows heir to transfer ownership only if heartbeat has timed out.
  78. */
  79. function claimHeirOwnership() public onlyHeir {
  80. require(!ownerLives());
  81. require(block.timestamp >= timeOfDeath_ + heartbeatTimeout_);
  82. emit OwnershipTransferred(owner, heir_);
  83. emit HeirOwnershipClaimed(owner, heir_);
  84. owner = heir_;
  85. timeOfDeath_ = 0;
  86. }
  87. function setHeartbeatTimeout(uint256 newHeartbeatTimeout) internal onlyOwner {
  88. require(ownerLives());
  89. heartbeatTimeout_ = newHeartbeatTimeout;
  90. }
  91. function ownerLives() internal view returns (bool) {
  92. return timeOfDeath_ == 0;
  93. }
  94. }