Browse Source

Remove Claimable, DelayedClaimable, Heritable (#1274)

* remove Claimable, DelayedClaimable, Heritable

* remove SimpleSavingsWallet example which used Heritable
Francisco Giordano 7 years ago
parent
commit
0dc711732a

+ 0 - 40
contracts/examples/SimpleSavingsWallet.sol

@@ -1,40 +0,0 @@
-pragma solidity ^0.4.24;
-
-import "../ownership/Heritable.sol";
-
-
-/**
- * @title SimpleSavingsWallet
- * @dev Simplest form of savings wallet whose ownership can be claimed by a heir
- * if owner dies.
- * In this example, we take a very simple savings wallet providing two operations
- * (to send and receive funds) and extend its capabilities by making it Heritable.
- * The account that creates the contract is set as owner, who has the authority to
- * choose an heir account. Heir account can reclaim the contract ownership in the
- * case that the owner dies.
- */
-contract SimpleSavingsWallet is Heritable {
-
-  event Sent(address indexed payee, uint256 amount, uint256 balance);
-  event Received(address indexed payer, uint256 amount, uint256 balance);
-
-
-  constructor(uint256 _heartbeatTimeout) Heritable(_heartbeatTimeout) public {}
-
-  /**
-   * @dev wallet can receive funds.
-   */
-  function () external payable {
-    emit Received(msg.sender, msg.value, address(this).balance);
-  }
-
-  /**
-   * @dev wallet can send funds
-   */
-  function sendTo(address _payee, uint256 _amount) public onlyOwner {
-    require(_payee != address(0) && _payee != address(this));
-    require(_amount > 0);
-    _payee.transfer(_amount);
-    emit Sent(_payee, _amount, address(this).balance);
-  }
-}

+ 0 - 39
contracts/ownership/Claimable.sol

@@ -1,39 +0,0 @@
-pragma solidity ^0.4.24;
-
-
-import "./Ownable.sol";
-
-
-/**
- * @title Claimable
- * @dev Extension for the Ownable contract, where the ownership needs to be claimed.
- * This allows the new owner to accept the transfer.
- */
-contract Claimable is Ownable {
-  address public pendingOwner;
-
-  /**
-   * @dev Modifier throws if called by any account other than the pendingOwner.
-   */
-  modifier onlyPendingOwner() {
-    require(msg.sender == pendingOwner);
-    _;
-  }
-
-  /**
-   * @dev Allows the current owner to set the pendingOwner address.
-   * @param newOwner The address to transfer ownership to.
-   */
-  function transferOwnership(address newOwner) public onlyOwner {
-    pendingOwner = newOwner;
-  }
-
-  /**
-   * @dev Allows the pendingOwner address to finalize the transfer.
-   */
-  function claimOwnership() public onlyPendingOwner {
-    emit OwnershipTransferred(owner, pendingOwner);
-    owner = pendingOwner;
-    pendingOwner = address(0);
-  }
-}

+ 0 - 40
contracts/ownership/DelayedClaimable.sol

@@ -1,40 +0,0 @@
-pragma solidity ^0.4.24;
-
-import "./Claimable.sol";
-
-
-/**
- * @title DelayedClaimable
- * @dev Extension for the Claimable contract, where the ownership needs to be claimed before/after
- * a certain block number.
- */
-contract DelayedClaimable is Claimable {
-
-  uint256 public end;
-  uint256 public start;
-
-  /**
-   * @dev Used to specify the time period during which a pending
-   * owner can claim ownership.
-   * @param _start The earliest time ownership can be claimed.
-   * @param _end The latest time ownership can be claimed.
-   */
-  function setLimits(uint256 _start, uint256 _end) public onlyOwner {
-    require(_start <= _end);
-    end = _end;
-    start = _start;
-  }
-
-  /**
-   * @dev Allows the pendingOwner address to finalize the transfer, as long as it is called within
-   * the specified start and end time.
-   */
-  function claimOwnership() public onlyPendingOwner {
-    require((block.number <= end) && (block.number >= start));
-    emit OwnershipTransferred(owner, pendingOwner);
-    owner = pendingOwner;
-    pendingOwner = address(0);
-    end = 0;
-  }
-
-}

+ 0 - 119
contracts/ownership/Heritable.sol

@@ -1,119 +0,0 @@
-pragma solidity ^0.4.24;
-
-
-import "./Ownable.sol";
-
-
-/**
- * @title Heritable
- * @dev The Heritable contract provides ownership transfer capabilities, in the
- * case that the current owner stops "heartbeating". Only the heir can pronounce the
- * owner's death.
- */
-contract Heritable is Ownable {
-  address private heir_;
-
-  // Time window the owner has to notify they are alive.
-  uint256 private heartbeatTimeout_;
-
-  // Timestamp of the owner's death, as pronounced by the heir.
-  uint256 private timeOfDeath_;
-
-  event HeirChanged(address indexed owner, address indexed newHeir);
-  event OwnerHeartbeated(address indexed owner);
-  event OwnerProclaimedDead(
-    address indexed owner,
-    address indexed heir,
-    uint256 timeOfDeath
-  );
-  event HeirOwnershipClaimed(
-    address indexed previousOwner,
-    address indexed newOwner
-  );
-
-
-  /**
-   * @dev Throw an exception if called by any account other than the heir's.
-   */
-  modifier onlyHeir() {
-    require(msg.sender == heir_);
-    _;
-  }
-
-
-  /**
-   * @notice Create a new Heritable Contract with heir address 0x0.
-   * @param _heartbeatTimeout time available for the owner to notify they are alive,
-   * before the heir can take ownership.
-   */
-  constructor(uint256 _heartbeatTimeout) public {
-    heartbeatTimeout_ = _heartbeatTimeout;
-  }
-
-  function setHeir(address _newHeir) public onlyOwner {
-    require(_newHeir != owner);
-    heartbeat();
-    emit HeirChanged(owner, _newHeir);
-    heir_ = _newHeir;
-  }
-
-  /**
-   * @dev Use these getter functions to access the internal variables in
-   * an inherited contract.
-   */
-  function heir() public view returns(address) {
-    return heir_;
-  }
-
-  function heartbeatTimeout() public view returns(uint256) {
-    return heartbeatTimeout_;
-  }
-
-  function timeOfDeath() public view returns(uint256) {
-    return timeOfDeath_;
-  }
-
-  /**
-   * @dev set heir = 0x0
-   */
-  function removeHeir() public onlyOwner {
-    heartbeat();
-    heir_ = address(0);
-  }
-
-  /**
-   * @dev Heir can pronounce the owners death. To claim the ownership, they will
-   * have to wait for `heartbeatTimeout` seconds.
-   */
-  function proclaimDeath() public onlyHeir {
-    require(_ownerLives());
-    emit OwnerProclaimedDead(owner, heir_, timeOfDeath_);
-    // solium-disable-next-line security/no-block-members
-    timeOfDeath_ = block.timestamp;
-  }
-
-  /**
-   * @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
-   */
-  function heartbeat() public onlyOwner {
-    emit OwnerHeartbeated(owner);
-    timeOfDeath_ = 0;
-  }
-
-  /**
-   * @dev Allows heir to transfer ownership only if heartbeat has timed out.
-   */
-  function claimHeirOwnership() public onlyHeir {
-    require(!_ownerLives());
-    // solium-disable-next-line security/no-block-members
-    require(block.timestamp >= timeOfDeath_ + heartbeatTimeout_);
-    emit OwnershipTransferred(owner, heir_);
-    emit HeirOwnershipClaimed(owner, heir_);
-    owner = heir_;
-    timeOfDeath_ = 0;
-  }
-
-  function _ownerLives() internal view returns (bool) {
-    return timeOfDeath_ == 0;
-  }
-}

+ 0 - 120
test/Heritable.test.js

@@ -1,120 +0,0 @@
-const { increaseTime } = require('./helpers/increaseTime');
-const { expectThrow } = require('./helpers/expectThrow');
-const { assertRevert } = require('./helpers/assertRevert');
-
-const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
-
-const Heritable = artifacts.require('Heritable');
-
-const BigNumber = web3.BigNumber;
-
-require('chai')
-  .use(require('chai-bignumber')(BigNumber))
-  .should();
-
-contract('Heritable', function ([_, owner, heir, anyone]) {
-  const heartbeatTimeout = 4141;
-  let heritable;
-
-  beforeEach(async function () {
-    heritable = await Heritable.new(heartbeatTimeout, { from: owner });
-  });
-
-  it('should start off with an owner, but without heir', async function () {
-    const heir = await heritable.heir();
-
-    owner.should.be.a('string').that.is.not.equal(NULL_ADDRESS);
-    heir.should.be.a('string').that.is.equal(NULL_ADDRESS);
-  });
-
-  it('only owner should set heir', async function () {
-    await heritable.setHeir(heir, { from: owner });
-    await expectThrow(heritable.setHeir(heir, { from: anyone }));
-  });
-
-  it('owner can\'t be heir', async function () {
-    await assertRevert(heritable.setHeir(owner, { from: owner }));
-  });
-
-  it('owner can remove heir', async function () {
-    await heritable.setHeir(heir, { from: owner });
-    (await heritable.heir()).should.equal(heir);
-
-    await heritable.removeHeir({ from: owner });
-    (await heritable.heir()).should.equal(NULL_ADDRESS);
-  });
-
-  it('heir can claim ownership only if owner is dead and timeout was reached', async function () {
-    await heritable.setHeir(heir, { from: owner });
-    await expectThrow(heritable.claimHeirOwnership({ from: heir }));
-
-    await heritable.proclaimDeath({ from: heir });
-    await increaseTime(1);
-    await expectThrow(heritable.claimHeirOwnership({ from: heir }));
-
-    await increaseTime(heartbeatTimeout);
-    await heritable.claimHeirOwnership({ from: heir });
-    (await heritable.heir()).should.equal(heir);
-  });
-
-  it('only heir can proclaim death', async function () {
-    await assertRevert(heritable.proclaimDeath({ from: owner }));
-    await assertRevert(heritable.proclaimDeath({ from: anyone }));
-  });
-
-  it('heir can\'t proclaim death if owner is death', async function () {
-    await heritable.setHeir(heir, { from: owner });
-    await heritable.proclaimDeath({ from: heir });
-    await assertRevert(heritable.proclaimDeath({ from: heir }));
-  });
-
-  it('heir can\'t claim ownership if owner heartbeats', async function () {
-    await heritable.setHeir(heir, { from: owner });
-
-    await heritable.proclaimDeath({ from: heir });
-    await heritable.heartbeat({ from: owner });
-    await expectThrow(heritable.claimHeirOwnership({ from: heir }));
-
-    await heritable.proclaimDeath({ from: heir });
-    await increaseTime(heartbeatTimeout);
-    await heritable.heartbeat({ from: owner });
-    await expectThrow(heritable.claimHeirOwnership({ from: heir }));
-  });
-
-  it('should log events appropriately', async function () {
-    const setHeirLogs = (await heritable.setHeir(heir, { from: owner })).logs;
-    const setHeirEvent = setHeirLogs.find(e => e.event === 'HeirChanged');
-
-    setHeirEvent.args.owner.should.equal(owner);
-    setHeirEvent.args.newHeir.should.equal(heir);
-
-    const heartbeatLogs = (await heritable.heartbeat({ from: owner })).logs;
-    const heartbeatEvent = heartbeatLogs.find(e => e.event === 'OwnerHeartbeated');
-
-    heartbeatEvent.args.owner.should.equal(owner);
-
-    const proclaimDeathLogs = (await heritable.proclaimDeath({ from: heir })).logs;
-    const ownerDeadEvent = proclaimDeathLogs.find(e => e.event === 'OwnerProclaimedDead');
-
-    ownerDeadEvent.args.owner.should.equal(owner);
-    ownerDeadEvent.args.heir.should.equal(heir);
-
-    await increaseTime(heartbeatTimeout);
-    const claimHeirOwnershipLogs = (await heritable.claimHeirOwnership({ from: heir })).logs;
-    const ownershipTransferredEvent = claimHeirOwnershipLogs.find(e => e.event === 'OwnershipTransferred');
-    const heirOwnershipClaimedEvent = claimHeirOwnershipLogs.find(e => e.event === 'HeirOwnershipClaimed');
-
-    ownershipTransferredEvent.args.previousOwner.should.equal(owner);
-    ownershipTransferredEvent.args.newOwner.should.equal(heir);
-    heirOwnershipClaimedEvent.args.previousOwner.should.equal(owner);
-    heirOwnershipClaimedEvent.args.newOwner.should.equal(heir);
-  });
-
-  it('timeOfDeath can be queried', async function () {
-    (await heritable.timeOfDeath()).should.be.bignumber.equal(0);
-  });
-
-  it('heartbeatTimeout can be queried', async function () {
-    (await heritable.heartbeatTimeout()).should.be.bignumber.equal(heartbeatTimeout);
-  });
-});

+ 0 - 40
test/SimpleSavingsWallet.test.js

@@ -1,40 +0,0 @@
-const { expectThrow } = require('./helpers/expectThrow');
-const { ethGetBalance, ethSendTransaction } = require('./helpers/web3');
-
-const SimpleSavingsWallet = artifacts.require('SimpleSavingsWallet');
-
-const BigNumber = web3.BigNumber;
-
-require('chai')
-  .use(require('chai-bignumber')(BigNumber))
-  .should();
-
-contract('SimpleSavingsWallet', function ([_, owner, anyone]) {
-  let savingsWallet;
-
-  const paymentAmount = 4242;
-
-  beforeEach(async function () {
-    savingsWallet = await SimpleSavingsWallet.new(4141, { from: owner });
-  });
-
-  it('should receive funds', async function () {
-    await ethSendTransaction({ from: owner, to: savingsWallet.address, value: paymentAmount });
-    const balance = await ethGetBalance(savingsWallet.address);
-    balance.should.be.bignumber.equal(paymentAmount);
-  });
-
-  it('owner can send funds', async function () {
-    // Receive payment so we have some money to spend.
-    await ethSendTransaction({ from: anyone, to: savingsWallet.address, value: 1000000 });
-
-    await expectThrow(savingsWallet.sendTo(0, paymentAmount, { from: owner }));
-    await expectThrow(savingsWallet.sendTo(savingsWallet.address, paymentAmount, { from: owner }));
-    await expectThrow(savingsWallet.sendTo(anyone, 0, { from: owner }));
-
-    const balance = await ethGetBalance(anyone);
-    await savingsWallet.sendTo(anyone, paymentAmount, { from: owner });
-    const updatedBalance = await ethGetBalance(anyone);
-    balance.plus(paymentAmount).should.be.bignumber.equal(updatedBalance);
-  });
-});

+ 0 - 46
test/ownership/Claimable.test.js

@@ -1,46 +0,0 @@
-const { assertRevert } = require('../helpers/assertRevert');
-
-const Claimable = artifacts.require('Claimable');
-
-const BigNumber = web3.BigNumber;
-
-require('chai')
-  .use(require('chai-bignumber')(BigNumber))
-  .should();
-
-contract('Claimable', function ([_, owner, newOwner, anyone]) {
-  let claimable;
-
-  beforeEach(async function () {
-    claimable = await Claimable.new({ from: owner });
-  });
-
-  it('should have an owner', async function () {
-    (await claimable.owner()).should.not.equal(0);
-  });
-
-  it('changes pendingOwner after transfer', async function () {
-    await claimable.transferOwnership(newOwner, { from: owner });
-    (await claimable.pendingOwner()).should.equal(newOwner);
-  });
-
-  it('should prevent to claimOwnership from anyone', async function () {
-    await assertRevert(claimable.claimOwnership({ from: anyone }));
-  });
-
-  it('should prevent non-owners from transfering', async function () {
-    await assertRevert(claimable.transferOwnership(anyone, { from: anyone }));
-  });
-
-  describe('after initiating a transfer', function () {
-    beforeEach(async function () {
-      await claimable.transferOwnership(newOwner, { from: owner });
-    });
-
-    it('changes allow pending owner to claim ownership', async function () {
-      await claimable.claimOwnership({ from: newOwner });
-
-      (await claimable.owner()).should.equal(newOwner);
-    });
-  });
-});

+ 0 - 55
test/ownership/DelayedClaimable.test.js

@@ -1,55 +0,0 @@
-const { assertRevert } = require('../helpers/assertRevert');
-
-const BigNumber = web3.BigNumber;
-
-require('chai')
-  .use(require('chai-bignumber')(BigNumber))
-  .should();
-
-const DelayedClaimable = artifacts.require('DelayedClaimable');
-
-contract('DelayedClaimable', function ([_, owner, newOwner]) {
-  beforeEach(async function () {
-    this.delayedClaimable = await DelayedClaimable.new({ from: owner });
-  });
-
-  it('can set claim blocks', async function () {
-    await this.delayedClaimable.transferOwnership(newOwner, { from: owner });
-    await this.delayedClaimable.setLimits(0, 1000, { from: owner });
-
-    (await this.delayedClaimable.end()).should.be.bignumber.equal(1000);
-
-    (await this.delayedClaimable.start()).should.be.bignumber.equal(0);
-  });
-
-  it('changes pendingOwner after transfer successful', async function () {
-    await this.delayedClaimable.transferOwnership(newOwner, { from: owner });
-    await this.delayedClaimable.setLimits(0, 1000, { from: owner });
-
-    (await this.delayedClaimable.end()).should.be.bignumber.equal(1000);
-
-    (await this.delayedClaimable.start()).should.be.bignumber.equal(0);
-
-    (await this.delayedClaimable.pendingOwner()).should.equal(newOwner);
-    await this.delayedClaimable.claimOwnership({ from: newOwner });
-    (await this.delayedClaimable.owner()).should.equal(newOwner);
-  });
-
-  it('changes pendingOwner after transfer fails', async function () {
-    await this.delayedClaimable.transferOwnership(newOwner, { from: owner });
-    await this.delayedClaimable.setLimits(100, 110, { from: owner });
-
-    (await this.delayedClaimable.end()).should.be.bignumber.equal(110);
-
-    (await this.delayedClaimable.start()).should.be.bignumber.equal(100);
-
-    (await this.delayedClaimable.pendingOwner()).should.equal(newOwner);
-    await assertRevert(this.delayedClaimable.claimOwnership({ from: newOwner }));
-    (await this.delayedClaimable.owner()).should.not.equal(newOwner);
-  });
-
-  it('set end and start invalid values fail', async function () {
-    await this.delayedClaimable.transferOwnership(newOwner, { from: owner });
-    await assertRevert(this.delayedClaimable.setLimits(1001, 1000, { from: owner }));
-  });
-});