From d9a963e90b4ce95cc24d029de33048408d70e338 Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Tue, 19 May 2020 19:08:45 +0300 Subject: [PATCH 1/2] dxdaoTimeLock --- contracts/misc/TimeLocking.sol | 26 ++++++++++++++++++++ contracts/test/Wallet.sol | 8 ++++++ test/dxdaotimelock.js | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 contracts/misc/TimeLocking.sol create mode 100644 test/dxdaotimelock.js diff --git a/contracts/misc/TimeLocking.sol b/contracts/misc/TimeLocking.sol new file mode 100644 index 00000000..8ff11de0 --- /dev/null +++ b/contracts/misc/TimeLocking.sol @@ -0,0 +1,26 @@ +pragma solidity ^0.5.17; + + +contract DxDAOTimeLock { + + address public owner; + uint256 public releaseTime; + + constructor(address _owner, uint256 _releaseTime) public { + owner = _owner; + releaseTime = _releaseTime; + } + + function () external payable { + } + + function withdraw() external { + require(msg.sender == owner, "only owner can withdraw"); + // solhint-disable-next-line not-rely-on-time + require(releaseTime < now, "cannot withdraw before releaseTime"); + // solhint-disable-next-line avoid-call-value + (bool success, ) = owner.call.value(address(this).balance)(""); + require(success, "sendEther failed."); + } + +} diff --git a/contracts/test/Wallet.sol b/contracts/test/Wallet.sol index 4d509f82..31d94a36 100644 --- a/contracts/test/Wallet.sol +++ b/contracts/test/Wallet.sol @@ -27,4 +27,12 @@ contract Wallet is Ownable { emit Pay(_beneficiary, amount); } + function genericCall(address _contract, bytes memory _encodedABI) + public + returns(bool success, bytes memory returnValue) { + // solhint-disable-next-line avoid-low-level-calls + (success, returnValue) = _contract.call(_encodedABI); + require(success, "call fail"); + } + } diff --git a/test/dxdaotimelock.js b/test/dxdaotimelock.js new file mode 100644 index 00000000..0f0096db --- /dev/null +++ b/test/dxdaotimelock.js @@ -0,0 +1,45 @@ +const helpers = require('./helpers'); + +const Wallet = artifacts.require("./Wallet.sol"); +const DxDAOTimeLock = artifacts.require("./DxDAOTimeLock.sol"); +contract('DxDAOTimeLock', accounts => { + + it("sendEther", async () => { + var wallet = await Wallet.new(); + await wallet.initialize(accounts[0]); + var owner = wallet.address; + var block = await web3.eth.getBlock("latest"); + var releaseTime = block.timestamp + (30*60*60*24); + var dxDAOTimeLock = await DxDAOTimeLock.new(owner,releaseTime); + assert.equal(await dxDAOTimeLock.owner(), owner); + assert.equal(await dxDAOTimeLock.releaseTime(), releaseTime); + + //send funds to wallet + await web3.eth.sendTransaction({from:accounts[0],to:owner, value: web3.utils.toWei('10', "ether")}); + assert.equal(await web3.eth.getBalance(owner), web3.utils.toWei('10', "ether")); + await wallet.pay(dxDAOTimeLock.address); + await wallet.pay(dxDAOTimeLock.address); + assert.equal(await web3.eth.getBalance(dxDAOTimeLock.address), web3.utils.toWei('10', "ether")); + + var encodedABI = await new web3.eth.Contract(dxDAOTimeLock.abi) + .methods + .withdraw() + .encodeABI(); + + try { + await wallet.genericCall(dxDAOTimeLock.address, encodedABI); + throw 'cannot withdraw before time'; + } catch (error) { + helpers.assertVMException(error); + } + await helpers.increaseTime((30*60*60*24)+1); + try { + await dxDAOTimeLock.withdraw(); + throw 'only Owner can withdraw'; + } catch (error) { + helpers.assertVMException(error); + } + await wallet.genericCall(dxDAOTimeLock.address, encodedABI); + assert.equal(await web3.eth.getBalance(owner), web3.utils.toWei('10', "ether")); + }); +}); From f932d2aaf903d08070049335b6ce1022bf0ac0ea Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Wed, 20 May 2020 17:53:43 +0300 Subject: [PATCH 2/2] naming --- .../misc/{TimeLocking.sol => TimeLock.sol} | 2 +- test/{dxdaotimelock.js => timelock.js} | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) rename contracts/misc/{TimeLocking.sol => TimeLock.sol} (96%) rename test/{dxdaotimelock.js => timelock.js} (60%) diff --git a/contracts/misc/TimeLocking.sol b/contracts/misc/TimeLock.sol similarity index 96% rename from contracts/misc/TimeLocking.sol rename to contracts/misc/TimeLock.sol index 8ff11de0..133164b2 100644 --- a/contracts/misc/TimeLocking.sol +++ b/contracts/misc/TimeLock.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.17; -contract DxDAOTimeLock { +contract TimeLock { address public owner; uint256 public releaseTime; diff --git a/test/dxdaotimelock.js b/test/timelock.js similarity index 60% rename from test/dxdaotimelock.js rename to test/timelock.js index 0f0096db..878eee86 100644 --- a/test/dxdaotimelock.js +++ b/test/timelock.js @@ -1,8 +1,8 @@ const helpers = require('./helpers'); const Wallet = artifacts.require("./Wallet.sol"); -const DxDAOTimeLock = artifacts.require("./DxDAOTimeLock.sol"); -contract('DxDAOTimeLock', accounts => { +const TimeLock = artifacts.require("./TimeLock.sol"); +contract('TimeLock', accounts => { it("sendEther", async () => { var wallet = await Wallet.new(); @@ -10,36 +10,36 @@ contract('DxDAOTimeLock', accounts => { var owner = wallet.address; var block = await web3.eth.getBlock("latest"); var releaseTime = block.timestamp + (30*60*60*24); - var dxDAOTimeLock = await DxDAOTimeLock.new(owner,releaseTime); - assert.equal(await dxDAOTimeLock.owner(), owner); - assert.equal(await dxDAOTimeLock.releaseTime(), releaseTime); + var timeLock = await TimeLock.new(owner,releaseTime); + assert.equal(await timeLock.owner(), owner); + assert.equal(await timeLock.releaseTime(), releaseTime); //send funds to wallet await web3.eth.sendTransaction({from:accounts[0],to:owner, value: web3.utils.toWei('10', "ether")}); assert.equal(await web3.eth.getBalance(owner), web3.utils.toWei('10', "ether")); - await wallet.pay(dxDAOTimeLock.address); - await wallet.pay(dxDAOTimeLock.address); - assert.equal(await web3.eth.getBalance(dxDAOTimeLock.address), web3.utils.toWei('10', "ether")); + await wallet.pay(timeLock.address); + await wallet.pay(timeLock.address); + assert.equal(await web3.eth.getBalance(timeLock.address), web3.utils.toWei('10', "ether")); - var encodedABI = await new web3.eth.Contract(dxDAOTimeLock.abi) + var encodedABI = await new web3.eth.Contract(timeLock.abi) .methods .withdraw() .encodeABI(); try { - await wallet.genericCall(dxDAOTimeLock.address, encodedABI); + await wallet.genericCall(timeLock.address, encodedABI); throw 'cannot withdraw before time'; } catch (error) { helpers.assertVMException(error); } await helpers.increaseTime((30*60*60*24)+1); try { - await dxDAOTimeLock.withdraw(); + await timeLock.withdraw(); throw 'only Owner can withdraw'; } catch (error) { helpers.assertVMException(error); } - await wallet.genericCall(dxDAOTimeLock.address, encodedABI); + await wallet.genericCall(timeLock.address, encodedABI); assert.equal(await web3.eth.getBalance(owner), web3.utils.toWei('10', "ether")); }); });