Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: pauser role #47

Merged
merged 4 commits into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions contracts/ToucanRegenBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.4;

import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

import "./interfaces/IContractRegistry.sol";
import "./interfaces/ITCO2.sol";
Expand All @@ -14,7 +15,22 @@ import "./interfaces/INCTPool.sol";
*
* See README file for more information about the functionality
*/
contract ToucanRegenBridge is Ownable, Pausable {
contract ToucanRegenBridge is Ownable, Pausable, AccessControl {
// ----------------------------------------
// Roles
// ----------------------------------------

bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

modifier onlyPauser() {
require(hasRole(PAUSER_ROLE, msg.sender), "caller does not have pauser role");
_;
}

// ----------------------------------------
// State
// ----------------------------------------

/// @notice total amount of tokens burned and signalled for transfer
uint256 public totalTransferred;

Expand Down Expand Up @@ -62,7 +78,9 @@ contract ToucanRegenBridge is Ownable, Pausable {
constructor(address tokenIssuer_, INCTPool nctPool_) Ownable() {
tokenIssuer = tokenIssuer_;
nctPool = nctPool_;
_grantRole(PAUSER_ROLE, msg.sender);
if (tokenIssuer_ != address(0)) {
_grantRole(PAUSER_ROLE, tokenIssuer_);
emit TokenIssuerUpdated(address(0), tokenIssuer_);
}
}
Expand All @@ -71,11 +89,11 @@ contract ToucanRegenBridge is Ownable, Pausable {
// Functions
// ----------------------------------------

function pause() external onlyOwner {
function pause() external onlyPauser {
_pause();
}

function unpause() external onlyOwner {
function unpause() external onlyPauser {
_unpause();
}

Expand All @@ -92,6 +110,14 @@ contract ToucanRegenBridge is Ownable, Pausable {
emit TokenIssuerUpdated(oldIssuer, newIssuer);
}

function grantPauserRole(address newPauser) external onlyOwner {
_grantRole(PAUSER_ROLE, newPauser);
}

function revokePauserRole(address pauser) external onlyOwner {
_revokeRole(PAUSER_ROLE, pauser);
}

/**
* @dev bridge tokens to Regen Network.
* Burns Toucan TCO2 compatible tokens and signals a bridge event.
Expand Down
15 changes: 14 additions & 1 deletion test/ToucanRegenBridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,23 @@ describe("Bridge contract", function () {
await bridge.connect(admin).unpause();
expect(await bridge.paused()).equal(false);

await expect(bridge.connect(broker).pause()).to.be.revertedWith("Ownable: caller is not the owner");
await expect(bridge.connect(broker).pause()).to.be.revertedWith("caller does not have pauser role");
expect(await bridge.paused()).equal(false);
});

it("should pause only with pauser role", async function () {
await bridge.connect(admin).grantPauserRole(broker.address);

await bridge.connect(broker).pause();
expect(await bridge.paused()).equal(true);

await bridge.connect(broker).unpause();
expect(await bridge.paused()).equal(false);

await bridge.connect(admin).revokePauserRole(broker.address);
await expect(bridge.connect(broker).pause()).to.be.revertedWith("caller does not have pauser role");
});

describe("Polygon to Regen", function () {
it("should fail with non positive amount", async function () {
await expect(bridge.connect(broker).bridge(regenUser, tco2.address, 0)).to.be.revertedWith(
Expand Down