Adding new Superuser contract with test (#952)
* Adding new Superuser contract + tests
This commit is contained in:
committed by
Matt Condon
parent
e3f866c982
commit
a0c03ee61c
62
contracts/ownership/Superuser.sol
Normal file
62
contracts/ownership/Superuser.sol
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
|
|
||||||
|
import "./Ownable.sol";
|
||||||
|
import "./rbac/RBAC.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Superuser
|
||||||
|
* @dev The Superuser contract defines a single superuser who can transfer the ownership
|
||||||
|
* @dev of a contract to a new address, even if he is not the owner.
|
||||||
|
* @dev A superuser can transfer his role to a new address.
|
||||||
|
*/
|
||||||
|
contract Superuser is Ownable, RBAC {
|
||||||
|
string public constant ROLE_SUPERUSER = "superuser";
|
||||||
|
|
||||||
|
constructor () public {
|
||||||
|
addRole(msg.sender, ROLE_SUPERUSER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Throws if called by any account that's not a superuser.
|
||||||
|
*/
|
||||||
|
modifier onlySuperuser() {
|
||||||
|
checkRole(msg.sender, ROLE_SUPERUSER);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev getter to determine if address has superuser role
|
||||||
|
*/
|
||||||
|
function isSuperuser(address _addr)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return hasRole(_addr, ROLE_SUPERUSER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Allows the current superuser to transfer his role to a newSuperuser.
|
||||||
|
* @param _newSuperuser The address to transfer ownership to.
|
||||||
|
*/
|
||||||
|
function transferSuperuser(address _newSuperuser)
|
||||||
|
onlySuperuser
|
||||||
|
public
|
||||||
|
{
|
||||||
|
require(_newSuperuser != address(0));
|
||||||
|
removeRole(msg.sender, ROLE_SUPERUSER);
|
||||||
|
addRole(_newSuperuser, ROLE_SUPERUSER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Allows the current superuser to transfer control of the contract to a newOwner.
|
||||||
|
* @param _newOwner The address to transfer ownership to.
|
||||||
|
*/
|
||||||
|
function transferOwnership(address _newOwner) public onlySuperuser {
|
||||||
|
require(_newOwner != address(0));
|
||||||
|
owner = _newOwner;
|
||||||
|
emit OwnershipTransferred(owner, _newOwner);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
test/ownership/Superuser.test.js
Normal file
62
test/ownership/Superuser.test.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import expectThrow from '../helpers/expectThrow';
|
||||||
|
import expectEvent from '../helpers/expectEvent';
|
||||||
|
|
||||||
|
const Superuser = artifacts.require('Superuser');
|
||||||
|
|
||||||
|
require('chai')
|
||||||
|
.use(require('chai-as-promised'))
|
||||||
|
.should();
|
||||||
|
|
||||||
|
contract('Superuser', function (accounts) {
|
||||||
|
const [
|
||||||
|
firstOwner,
|
||||||
|
newSuperuser,
|
||||||
|
newOwner,
|
||||||
|
anyone,
|
||||||
|
] = accounts;
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.superuser = await Superuser.new();
|
||||||
|
});
|
||||||
|
|
||||||
|
context('in normal conditions', () => {
|
||||||
|
it('should set the owner as the default superuser', async function () {
|
||||||
|
const ownerIsSuperuser = await this.superuser.isSuperuser(firstOwner);
|
||||||
|
ownerIsSuperuser.should.be.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change superuser after transferring', async function () {
|
||||||
|
await this.superuser.transferSuperuser(newSuperuser, { from: firstOwner });
|
||||||
|
|
||||||
|
const ownerIsSuperuser = await this.superuser.isSuperuser(firstOwner);
|
||||||
|
ownerIsSuperuser.should.be.equal(false);
|
||||||
|
|
||||||
|
const address1IsSuperuser = await this.superuser.isSuperuser(newSuperuser);
|
||||||
|
address1IsSuperuser.should.be.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change owner after transferring', async function () {
|
||||||
|
await expectEvent.inTransaction(
|
||||||
|
this.superuser.transferOwnership(newOwner, { from: newSuperuser }),
|
||||||
|
'OwnershipTransferred'
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentOwner = await this.superuser.owner();
|
||||||
|
currentOwner.should.be.equal(newOwner);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('in adversarial conditions', () => {
|
||||||
|
it('should prevent non-superusers from transfering the superuser role', async function () {
|
||||||
|
await expectThrow(
|
||||||
|
this.superuser.transferSuperuser(newOwner, { from: anyone })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prevent non-superusers from setting a new owner', async function () {
|
||||||
|
await expectThrow(
|
||||||
|
this.superuser.transferOwnership(newOwner, { from: anyone })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user