diff --git a/contracts/examples/SampleTokenTimelock.sol b/contracts/examples/SampleTokenTimelock.sol new file mode 100644 index 000000000..ee54da6ca --- /dev/null +++ b/contracts/examples/SampleTokenTimelock.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.24; + +import "../token/ERC20/ERC20Mintable.sol"; +import "../token/ERC20/ERC20Detailed.sol"; +import "../token/ERC20/TokenTimelock.sol"; + +/** + * @title SampleTimelockToken + * @dev Very simple ERC20 Token that can be minted. + * It is meant to be used in a tokentimelock contract. + */ +contract SampleTimelockToken is ERC20Mintable, ERC20Detailed { + constructor() public ERC20Detailed("Sample Timelock Token", "STT", 18) {} +} + + +/** + * @title SampleTokenTimelock + * @dev This is an example of a token lock for certain time. + */ + +contract SampleTokenTimelock is TokenTimelock{ + + constructor( + ERC20Mintable token, + address beneficiary, + uint256 releaseTime + ) + public + TokenTimelock(token, beneficiary, releaseTime){} + +} diff --git a/contracts/examples/SampleTokenVesting.sol b/contracts/examples/SampleTokenVesting.sol new file mode 100644 index 000000000..8b86f9c7e --- /dev/null +++ b/contracts/examples/SampleTokenVesting.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.24; + +import "../drafts/TokenVesting.sol"; + +/** + * @title SampleTokenVesting + * @dev This is an example of a token vesting for defined time period. + * Tokens to be vested will be sent directly to this contract. + */ + +contract SampleTokenVesting is TokenVesting{ + + constructor( + address beneficiary, + uint256 start, + uint256 cliffDuration, + uint256 duration, + bool revocable + ) + public + TokenVesting(beneficiary, start, cliffDuration, duration, revocable){} + +} \ No newline at end of file diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index 0dd602ffe..d8fa2d5f6 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -3,47 +3,28 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/SafeERC20.sol"; -contract ERC20FailingMock is IERC20 { - uint256 private _allowance; - function totalSupply() public view returns (uint256) { - return 0; - } +contract ERC20FailingMock { + uint256 private _allowance; - function transfer(address, uint256) public returns (bool) { - return false; - } + function transfer(address, uint256) public returns (bool) { + return false; + } - function transferFrom(address, address, uint256) public returns (bool) { - return false; - } + function transferFrom(address, address, uint256) public returns (bool) { + return false; + } - function approve(address, uint256) public returns (bool) { - return false; - } + function approve(address, uint256) public returns (bool) { + return false; + } - function increaseAllowance(address, uint256) public returns (bool){ - return false; - } - - function decreaseAllowance(address, uint256) public returns (bool){ - return false; - } - - function balanceOf(address) public view returns (uint256) { - return 0; - } - - function allowance(address, address) public view returns (uint256) { - return 0; - } + function allowance(address, address) public view returns (uint256) { + return 0; + } } -contract ERC20SucceedingMock is IERC20 { - uint256 private _allowance; - - function totalSupply() public view returns (uint256) { - return 0; - } +contract ERC20SucceedingMock { + uint256 private _allowance; function transfer(address, uint256) public returns (bool) { return true; @@ -57,33 +38,20 @@ contract ERC20SucceedingMock is IERC20 { return true; } - function increaseAllowance(address, uint256) public returns (bool){ - return true; - } + function setAllowance(uint256 allowance_) public { + _allowance = allowance_; + } - function decreaseAllowance(address, uint256) public returns (bool){ - return true; - } - - function balanceOf(address) public view returns (uint256) { - return 0; - } - - function allowance(address, address) public view returns (uint256) { - return _allowance; - } - - function setAllowance(uint256 value) public { - _allowance = value; - } + function allowance(address, address) public view returns (uint256) { + return _allowance; + } } contract SafeERC20Helper { + using SafeERC20 for IERC20; - using SafeERC20 for IERC20; - - IERC20 private _failing; - IERC20 private _succeeding; + IERC20 private _failing; + IERC20 private _succeeding; constructor () public { _failing = IERC20(new ERC20FailingMock()); @@ -130,23 +98,15 @@ contract SafeERC20Helper { _succeeding.safeIncreaseAllowance(address(0), amount); } - function doFailingIncreaseAllowance() public { - _failing.safeIncreaseAllowance(address(0), 0); - } - - function doFailingDecreaseAllowance() public { - _failing.safeDecreaseAllowance(address(0), 0); - } - - function doSucceedingTransfer() public { - _succeeding.safeTransfer(address(0), 0); - } + function doSucceedingDecreaseAllowance(uint256 amount) public { + _succeeding.safeDecreaseAllowance(address(0), amount); + } function setAllowance(uint256 allowance_) public { ERC20SucceedingMock(_succeeding).setAllowance(allowance_); } - function doSucceedingApprove() public { - _succeeding.safeApprove(address(0), 0); - } -} + function allowance() public view returns (uint256) { + return _succeeding.allowance(address(0), address(0)); + } +} \ No newline at end of file diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index 0c846d0a0..a8fac52a4 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; -import "./ERC20.sol"; import "./IERC20.sol"; +import "../../math/SafeMath.sol"; /** * @title SafeERC20 @@ -10,58 +10,31 @@ import "./IERC20.sol"; * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) - internal - { - require(token.transfer(to, value)); - } + using SafeMath for uint256; - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) - internal - { - require(token.transferFrom(from, to, value)); - } + function safeTransfer(IERC20 token, address to, uint256 value) internal { + require(token.transfer(to, value)); + } - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) - internal - { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require((value == 0) || (token.allowance(msg.sender, spender) == 0)); - require(token.approve(spender, value)); - } + function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { + require(token.transferFrom(from, to, value)); + } - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 addedValue - ) - internal - { - require(token.increaseAllowance(spender, addedValue)); - } + function safeApprove(IERC20 token, address spender, uint256 value) internal { + // safeApprove should only be called when setting an initial allowance, + // or when resetting it to zero. To increase and decrease it, use + // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' + require((value == 0) || (token.allowance(msg.sender, spender) == 0)); + require(token.approve(spender, value)); + } - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 subtractedValue - ) - internal - { - require(token.decreaseAllowance(spender, subtractedValue)); - } -} + function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender).add(value); + require(token.approve(spender, newAllowance)); + } + + function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender).sub(value); + require(token.approve(spender, newAllowance)); + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b5ce5da27..591247689 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4007,14 +4007,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4029,20 +4027,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -4159,8 +4154,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -4172,7 +4166,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4187,7 +4180,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4195,14 +4187,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -4221,7 +4211,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -4302,8 +4291,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -4315,7 +4303,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -4437,7 +4424,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/test/helpers/hashMessage.js b/test/helpers/hashMessage.js deleted file mode 100644 index 6e8a1f74e..000000000 --- a/test/helpers/hashMessage.js +++ /dev/null @@ -1,8 +0,0 @@ -import utils from 'ethereumjs-util'; - -// Hash and add same prefix to the hash that testrpc use. -module.exports = function (message) { - const messageHex = Buffer.from(utils.sha3(message).toString('hex'), 'hex'); - const prefix = utils.toBuffer('\u0019Ethereum Signed Message:\n' + messageHex.length.toString()); - return utils.bufferToHex(utils.sha3(Buffer.concat([prefix, messageHex]))); -}; diff --git a/test/token/ERC20/SafeERC20.test.js b/test/token/ERC20/SafeERC20.test.js index b3149658f..a7888fb68 100644 --- a/test/token/ERC20/SafeERC20.test.js +++ b/test/token/ERC20/SafeERC20.test.js @@ -22,17 +22,17 @@ contract('SafeERC20', function () { await shouldFail.reverting(this.helper.doFailingApprove()); }); - it('should throw on failed increaseAllowance', async function () { - await shouldFail.reverting(this.helper.doFailingIncreaseAllowance()); - }); + it('should throw on failed increaseAllowance', async function () { + await shouldFail.reverting(this.helper.doFailingIncreaseAllowance()); + }); - it('should throw on failed decreaseAllowance', async function () { - await shouldFail.reverting(this.helper.doFailingDecreaseAllowance()); - }); + it('should throw on failed decreaseAllowance', async function () { + await shouldFail.reverting(this.helper.doFailingDecreaseAllowance()); + }); - it('should not throw on succeeding transfer', async function () { - await this.helper.doSucceedingTransfer(); - }); + it('should not throw on succeeding transfer', async function () { + await this.helper.doSucceedingTransfer(); + }); it('reverts on decreaseAllowance', async function () { await shouldFail.reverting(this.helper.doFailingDecreaseAllowance());