Skip to content

Commit

Permalink
Add Pauser role (#17)
Browse files Browse the repository at this point in the history
* Add Pauser role

* Add tests

* Guard for pauserAddress == 0
  • Loading branch information
lucas-janon authored Jun 27, 2022
1 parent 04ab7c2 commit 9e4ae67
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 28 deletions.
36 changes: 30 additions & 6 deletions packages/protocol-contracts/contracts/ZetaConnector.base.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import "./interfaces/ZetaInterfaces.sol";
contract ZetaConnectorBase is ConnectorErrors, Pausable {
address public zetaToken;

address public pauserAddress;

/**
* @dev Collectively held by Zeta blockchain validators.
*/
Expand All @@ -20,8 +22,8 @@ contract ZetaConnectorBase is ConnectorErrors, Pausable {
event ZetaSent(
address sourceTxOriginAddress,
address indexed zetaTxSenderAddress,
uint256 destinationChainId,
bytes destinationAddress,
uint256 indexed destinationChainId,
bytes indexed destinationAddress,
uint256 zetaValueAndGas,
uint256 destinationGasLimit,
bytes message,
Expand Down Expand Up @@ -49,18 +51,32 @@ contract ZetaConnectorBase is ConnectorErrors, Pausable {

event TSSAddressUpdated(address zetaTxSenderAddress, address newTssAddress);

event PauserAddressUpdated(address updaterAddress, address newTssAddress);

constructor(
address zetaToken_,
address tssAddress_,
address tssAddressUpdater_
address tssAddressUpdater_,
address pauserAddress_
) {
if (zetaToken_ == address(0) || tssAddress_ == address(0) || tssAddressUpdater_ == address(0)) {
if (
zetaToken_ == address(0) ||
tssAddress_ == address(0) ||
tssAddressUpdater_ == address(0) ||
pauserAddress_ == address(0)
) {
revert InvalidAddress();
}

zetaToken = zetaToken_;
tssAddress = tssAddress_;
tssAddressUpdater = tssAddressUpdater_;
pauserAddress = pauserAddress_;
}

modifier onlyPauser() {
if (msg.sender != pauserAddress) revert CallerIsNotPauser(msg.sender);
_;
}

modifier onlyTssAddress() {
Expand All @@ -73,6 +89,14 @@ contract ZetaConnectorBase is ConnectorErrors, Pausable {
_;
}

function updatePauserAddress(address pauserAddress_) external onlyPauser {
if (pauserAddress_ == address(0)) revert InvalidAddress();

pauserAddress = pauserAddress_;

emit PauserAddressUpdated(msg.sender, pauserAddress_);
}

function updateTssAddress(address tssAddress_) external {
if (msg.sender != tssAddress && msg.sender != tssAddressUpdater) revert CallerIsNotTssOrUpdater(msg.sender);
if (tssAddress_ == address(0)) revert InvalidAddress();
Expand All @@ -91,11 +115,11 @@ contract ZetaConnectorBase is ConnectorErrors, Pausable {
tssAddressUpdater = tssAddress;
}

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

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

Expand Down
5 changes: 3 additions & 2 deletions packages/protocol-contracts/contracts/ZetaConnector.eth.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ contract ZetaConnectorEth is ZetaConnectorBase {
constructor(
address zetaToken_,
address tssAddress_,
address tssAddressUpdater_
) ZetaConnectorBase(zetaToken_, tssAddress_, tssAddressUpdater_) {}
address tssAddressUpdater_,
address pauserAddress_
) ZetaConnectorBase(zetaToken_, tssAddress_, tssAddressUpdater_, pauserAddress_) {}

function getLockedAmount() external view returns (uint256) {
return IERC20(zetaToken).balanceOf(address(this));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ contract ZetaConnectorNonEth is ZetaConnectorBase {
constructor(
address zetaTokenAddress_,
address tssAddress_,
address tssAddressUpdater_
) ZetaConnectorBase(zetaTokenAddress_, tssAddress_, tssAddressUpdater_) {}
address tssAddressUpdater_,
address pauserAddress_
) ZetaConnectorBase(zetaTokenAddress_, tssAddress_, tssAddressUpdater_, pauserAddress_) {}

function getLockedAmount() external view returns (uint256) {
return ZetaToken(zetaToken).balanceOf(address(this));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
pragma solidity 0.8.7;

interface ConnectorErrors {
error CallerIsNotPauser(address caller);

error CallerIsNotTss(address caller);

error CallerIsNotTssUpdater(address caller);
Expand Down
5 changes: 3 additions & 2 deletions packages/protocol-contracts/test/Zeta.non-eth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe("ZetaNonEth tests", () => {
let tssUpdater: SignerWithAddress;
let tssSigner: SignerWithAddress;
let randomSigner: SignerWithAddress;
let pauserSigner: SignerWithAddress;

const tssUpdaterApproveConnectorNonEth = async () => {
await (await zetaTokenNonEthContract.approve(zetaConnectorNonEthContract.address, parseEther("100000"))).wait();
Expand All @@ -36,15 +37,15 @@ describe("ZetaNonEth tests", () => {

beforeEach(async () => {
const accounts = await ethers.getSigners();
[tssUpdater, tssSigner, randomSigner] = accounts;
[tssUpdater, tssSigner, randomSigner, pauserSigner] = accounts;

zetaTokenNonEthContract = await deployZetaNonEth({
args: [tssSigner.address, tssUpdater.address],
});

zetaReceiverMockContract = await deployZetaReceiverMock();
zetaConnectorNonEthContract = await deployZetaConnectorNonEth({
args: [zetaTokenNonEthContract.address, tssSigner.address, tssUpdater.address],
args: [zetaTokenNonEthContract.address, tssSigner.address, tssUpdater.address, pauserSigner.address],
});

await zetaTokenNonEthContract.updateTssAndConnectorAddresses(
Expand Down
72 changes: 56 additions & 16 deletions packages/protocol-contracts/test/ZetaConnector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe("ZetaConnector tests", () => {
let tssUpdater: SignerWithAddress;
let tssSigner: SignerWithAddress;
let randomSigner: SignerWithAddress;
let pauserSigner: SignerWithAddress;

const tssUpdaterApproveConnectorEth = async () => {
await (await zetaTokenEthContract.approve(zetaConnectorEthContract.address, parseEther("100000"))).wait();
Expand Down Expand Up @@ -61,7 +62,7 @@ describe("ZetaConnector tests", () => {

beforeEach(async () => {
const accounts = await ethers.getSigners();
[tssUpdater, tssSigner, randomSigner] = accounts;
[tssUpdater, tssSigner, randomSigner, pauserSigner] = accounts;

zetaTokenEthContract = await deployZetaEth({
args: [100_000],
Expand All @@ -73,13 +74,13 @@ describe("ZetaConnector tests", () => {

zetaReceiverMockContract = await deployZetaReceiverMock();
zetaConnectorBaseContract = await deployZetaConnectorBase({
args: [zetaTokenEthContract.address, tssSigner.address, tssUpdater.address],
args: [zetaTokenEthContract.address, tssSigner.address, tssUpdater.address, pauserSigner.address],
});
zetaConnectorEthContract = await deployZetaConnectorEth({
args: [zetaTokenEthContract.address, tssSigner.address, tssUpdater.address],
args: [zetaTokenEthContract.address, tssSigner.address, tssUpdater.address, pauserSigner.address],
});
zetaConnectorNonEthContract = await deployZetaConnectorNonEth({
args: [zetaTokenNonEthContract.address, tssSigner.address, tssUpdater.address],
args: [zetaTokenNonEthContract.address, tssSigner.address, tssUpdater.address, pauserSigner.address],
});

await zetaTokenNonEthContract.updateTssAndConnectorAddresses(
Expand Down Expand Up @@ -121,23 +122,62 @@ describe("ZetaConnector tests", () => {
});
});

describe("updatePauserAddress", () => {
it("Should revert if the caller is not the Pauser", async () => {
await expect(
zetaConnectorBaseContract.connect(randomSigner).updatePauserAddress(randomSigner.address)
).to.revertedWith(`CallerIsNotPauser("${randomSigner.address}")`);
});

it("Should revert if the new Pauser address is invalid", async () => {
await expect(
zetaConnectorBaseContract
.connect(pauserSigner)
.updatePauserAddress("0x0000000000000000000000000000000000000000")
).to.revertedWith(`InvalidAddress()`);
});

it("Should change the Pauser address if called by Pauser", async () => {
await (await zetaConnectorBaseContract.connect(pauserSigner).updatePauserAddress(randomSigner.address)).wait();

const address = await zetaConnectorBaseContract.pauserAddress();

expect(address).to.equal(randomSigner.address);
});

it("Should emit `PauserAddressUpdated` on success", async () => {
const pauserAddressUpdatedFilter = zetaConnectorBaseContract.filters.PauserAddressUpdated();
const e1 = await zetaConnectorBaseContract.queryFilter(pauserAddressUpdatedFilter);
expect(e1.length).to.equal(0);

await (await zetaConnectorBaseContract.connect(pauserSigner).updatePauserAddress(randomSigner.address)).wait();

const address = await zetaConnectorBaseContract.pauserAddress();

expect(address).to.equal(randomSigner.address);

const e2 = await zetaConnectorBaseContract.queryFilter(pauserAddressUpdatedFilter);
expect(e2.length).to.equal(1);
});
});

describe("pause, unpause", () => {
it("Should revert if not called by the TSS updater", async () => {
it("Should revert if not called by the Pauser", async () => {
await expect(zetaConnectorBaseContract.connect(randomSigner).pause()).to.revertedWith(
`CallerIsNotTssUpdater("${randomSigner.address}")`
`CallerIsNotPauser("${randomSigner.address}")`
);

await expect(zetaConnectorBaseContract.connect(randomSigner).unpause()).to.revertedWith(
`CallerIsNotTssUpdater("${randomSigner.address}")`
`CallerIsNotPauser("${randomSigner.address}")`
);
});

it("Should pause if called by the TSS updater", async () => {
await (await zetaConnectorBaseContract.pause()).wait();
it("Should pause if called by the Pauser", async () => {
await (await zetaConnectorBaseContract.connect(pauserSigner).pause()).wait();
const paused1 = await zetaConnectorBaseContract.paused();
expect(paused1).to.equal(true);

await (await zetaConnectorBaseContract.unpause()).wait();
await (await zetaConnectorBaseContract.connect(pauserSigner).unpause()).wait();
const paused2 = await zetaConnectorBaseContract.paused();
expect(paused2).to.equal(false);
});
Expand All @@ -147,7 +187,7 @@ describe("ZetaConnector tests", () => {
describe("ZetaConnector.eth", () => {
describe("send", () => {
it("Should revert if the contract is paused", async () => {
await (await zetaConnectorEthContract.pause()).wait();
await (await zetaConnectorEthContract.connect(pauserSigner).pause()).wait();
const paused1 = await zetaConnectorEthContract.paused();
expect(paused1).to.equal(true);

Expand Down Expand Up @@ -259,7 +299,7 @@ describe("ZetaConnector tests", () => {

describe("onReceive", () => {
it("Should revert if the contract is paused", async () => {
await (await zetaConnectorEthContract.pause()).wait();
await (await zetaConnectorEthContract.connect(pauserSigner).pause()).wait();
const paused1 = await zetaConnectorEthContract.paused();
expect(paused1).to.equal(true);

Expand Down Expand Up @@ -358,7 +398,7 @@ describe("ZetaConnector tests", () => {

describe("onRevert", () => {
it("Should revert if the contract is paused", async () => {
await (await zetaConnectorEthContract.pause()).wait();
await (await zetaConnectorEthContract.connect(pauserSigner).pause()).wait();
const paused1 = await zetaConnectorEthContract.paused();
expect(paused1).to.equal(true);

Expand Down Expand Up @@ -448,7 +488,7 @@ describe("ZetaConnector tests", () => {
describe("ZetaConnector.non-eth", () => {
describe("send", () => {
it("Should revert if the contract is paused", async () => {
await (await zetaConnectorNonEthContract.pause()).wait();
await (await zetaConnectorNonEthContract.connect(pauserSigner).pause()).wait();
const paused1 = await zetaConnectorNonEthContract.paused();
expect(paused1).to.equal(true);

Expand Down Expand Up @@ -554,7 +594,7 @@ describe("ZetaConnector tests", () => {

describe("onReceive", () => {
it("Should revert if the contract is paused", async () => {
await (await zetaConnectorNonEthContract.pause()).wait();
await (await zetaConnectorNonEthContract.connect(pauserSigner).pause()).wait();
const paused1 = await zetaConnectorNonEthContract.paused();
expect(paused1).to.equal(true);

Expand Down Expand Up @@ -650,7 +690,7 @@ describe("ZetaConnector tests", () => {

describe("onRevert", () => {
it("Should revert if the contract is paused", async () => {
await (await zetaConnectorNonEthContract.pause()).wait();
await (await zetaConnectorNonEthContract.connect(pauserSigner).pause()).wait();
const paused1 = await zetaConnectorNonEthContract.paused();
expect(paused1).to.equal(true);

Expand Down

0 comments on commit 9e4ae67

Please sign in to comment.