diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index 0d08f73dd..69280409e 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -10,6 +10,7 @@ contract Ownable { address public owner; + event OwnershipRenounced(address indexed previousOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); @@ -39,4 +40,11 @@ contract Ownable { owner = newOwner; } + /** + * @dev Allows the current owner to relinquish control of the contract. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipRenounced(owner); + owner = address(0); + } } diff --git a/test/ownership/Ownable.test.js b/test/ownership/Ownable.test.js index 209a209b1..460836e7f 100644 --- a/test/ownership/Ownable.test.js +++ b/test/ownership/Ownable.test.js @@ -2,6 +2,7 @@ import assertRevert from '../helpers/assertRevert'; var Ownable = artifacts.require('Ownable'); +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; contract('Ownable', function (accounts) { let ownable; @@ -34,4 +35,18 @@ contract('Ownable', function (accounts) { let originalOwner = await ownable.owner(); await assertRevert(ownable.transferOwnership(null, { from: originalOwner })); }); + + it('loses owner after renouncement', async function () { + await ownable.renounceOwnership(); + let owner = await ownable.owner(); + + assert.isTrue(owner === ZERO_ADDRESS); + }); + + it('should prevent non-owners from renouncement', async function () { + const other = accounts[2]; + const owner = await ownable.owner.call(); + assert.isTrue(owner !== other); + await assertRevert(ownable.renounceOwnership({ from: other })); + }); });