From 0ec84a3c4a918988c3e6a17e53ce3a2b516aab1f Mon Sep 17 00:00:00 2001 From: poma Date: Fri, 15 Jan 2021 22:35:54 -0500 Subject: [PATCH] init --- README.md | 3 +- contracts/Echoer.sol | 11 ------ contracts/RelayerRegistry.sol | 32 ++++++++++++++++ migrations/1_deploy_echo.js | 10 ----- migrations/1_deploy_registry.js | 10 +++++ package.json | 3 +- test/echoer.test.js | 32 ---------------- test/relayerRegistry.js | 65 +++++++++++++++++++++++++++++++++ 8 files changed, 110 insertions(+), 56 deletions(-) delete mode 100644 contracts/Echoer.sol create mode 100644 contracts/RelayerRegistry.sol delete mode 100644 migrations/1_deploy_echo.js create mode 100644 migrations/1_deploy_registry.js delete mode 100644 test/echoer.test.js create mode 100644 test/relayerRegistry.js diff --git a/README.md b/README.md index fba548e..3984224 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Peppersec solidity template [![Build Status](https://github.com/peppersec/solidity-template/workflows/build/badge.svg)](https://github.com/peppersec/solidity-template/actions) +# Tornado Cash relayer registry contract [![Build Status](https://github.com/tornadocash/relayer-registry/workflows/build/badge.svg)](https://github.com/tornadocash/relayer-registry/actions) ## Dependencies @@ -9,7 +9,6 @@ ```bash $ yarn -$ cp .env.example .env $ yarn test ``` diff --git a/contracts/Echoer.sol b/contracts/Echoer.sol deleted file mode 100644 index 44d397b..0000000 --- a/contracts/Echoer.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; - -contract Echoer { - event Echo(address indexed who, bytes data); - - function echo(bytes calldata data) external { - emit Echo(msg.sender, data); - } -} diff --git a/contracts/RelayerRegistry.sol b/contracts/RelayerRegistry.sol new file mode 100644 index 0000000..4470ed5 --- /dev/null +++ b/contracts/RelayerRegistry.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; + +contract RelayerRegistry { + address public immutable governance; + mapping(bytes32 => bool) public isRelayer; + + event RelayerAdded(bytes32 indexed relayer); + event RelayerRemoved(bytes32 indexed relayer); + + modifier onlyGovernance() { + require(msg.sender == governance, "unauthorized"); + _; + } + + constructor(address _governance) public { + governance = _governance; + } + + function add(bytes32 _relayer) public onlyGovernance { + require(!isRelayer[_relayer], "The relayer already exists"); + isRelayer[_relayer] = true; + emit RelayerAdded(_relayer); + } + + function remove(bytes32 _relayer) public onlyGovernance { + require(isRelayer[_relayer], "The relayer does not exist"); + isRelayer[_relayer] = false; + emit RelayerRemoved(_relayer); + } +} diff --git a/migrations/1_deploy_echo.js b/migrations/1_deploy_echo.js deleted file mode 100644 index 498a5b3..0000000 --- a/migrations/1_deploy_echo.js +++ /dev/null @@ -1,10 +0,0 @@ -/* global artifacts */ -const Echoer = artifacts.require('Echoer') - -module.exports = function (deployer) { - return deployer.then(async () => { - const echoer = await deployer.deploy(Echoer) - - console.log('Echoer :', echoer.address) - }) -} diff --git a/migrations/1_deploy_registry.js b/migrations/1_deploy_registry.js new file mode 100644 index 0000000..eadea5c --- /dev/null +++ b/migrations/1_deploy_registry.js @@ -0,0 +1,10 @@ +/* global artifacts */ +const RelayerRegistry = artifacts.require('RelayerRegistry') + +module.exports = function (deployer, network, accounts) { + return deployer.then(async () => { + const registry = await deployer.deploy(RelayerRegistry, accounts[0]) + + console.log('Registry :', registry.address) + }) +} diff --git a/package.json b/package.json index f8735fa..24570d8 100644 --- a/package.json +++ b/package.json @@ -43,5 +43,6 @@ "truffle-hdwallet-provider": "^1.0.17", "truffle-plugin-verify": "^0.3.11", "web3": "^1.2.11" - } + }, + "dependencies": {} } diff --git a/test/echoer.test.js b/test/echoer.test.js deleted file mode 100644 index 4d61543..0000000 --- a/test/echoer.test.js +++ /dev/null @@ -1,32 +0,0 @@ -/* global artifacts, web3, contract */ -require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should() - -const { takeSnapshot, revertSnapshot } = require('../scripts/ganacheHelper') -const Echoer = artifacts.require('./Echoer.sol') - -contract('Echoer', (accounts) => { - let echoer - let snapshotId - - before(async () => { - echoer = await Echoer.deployed() - snapshotId = await takeSnapshot() - }) - - describe('#echo', () => { - it('should work', async () => { - const data = '0xbeef' - const { logs } = await echoer.echo(data) - - logs[0].event.should.be.equal('Echo') - logs[0].args.who.should.be.equal(accounts[0]) - logs[0].args.data.should.be.equal(data) - }) - }) - - afterEach(async () => { - await revertSnapshot(snapshotId.result) - // eslint-disable-next-line require-atomic-updates - snapshotId = await takeSnapshot() - }) -}) diff --git a/test/relayerRegistry.js b/test/relayerRegistry.js new file mode 100644 index 0000000..8b1f411 --- /dev/null +++ b/test/relayerRegistry.js @@ -0,0 +1,65 @@ +/* global artifacts, web3, contract */ +require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should() + +const { takeSnapshot, revertSnapshot } = require('../scripts/ganacheHelper') +const RelayerRegistry = artifacts.require('./RelayerRegistry.sol') + +contract('RelayerRegistry', (accounts) => { + let registry + let snapshotId + const relayer1 = '0x3b43172e77b9e7272c8045d818f7ce325205bed01fb56a3747b78ae9c0ce4334' + + before(async () => { + registry = await RelayerRegistry.new(accounts[0]) + snapshotId = await takeSnapshot() + }) + + describe('#add', () => { + it('should work', async () => { + const { logs } = await registry.add(relayer1) + + logs[0].event.should.be.equal('RelayerAdded') + logs[0].args.relayer.should.be.equal(relayer1) + }) + + it('should prevent double add', async () => { + await registry.add(relayer1) + await registry.add(relayer1).should.be.rejectedWith('The relayer already exists') + }) + + it('should allow readd', async () => { + await registry.add(relayer1) + await registry.remove(relayer1) + await registry.add(relayer1) + }) + + it('should prevent unauthorized access', async () => { + await registry.add(relayer1, { from: accounts[1] }).should.be.rejectedWith('unauthorized') + }) + }) + + describe('#remove', () => { + it('should work', async () => { + await registry.add(relayer1) + const { logs } = await registry.remove(relayer1) + + logs[0].event.should.be.equal('RelayerRemoved') + logs[0].args.relayer.should.be.equal(relayer1) + }) + + it('should prevent remove not existing', async () => { + await registry.remove(relayer1).should.be.rejectedWith('The relayer does not exist') + }) + + it('should prevent unauthorized access', async () => { + await registry.add(relayer1) + await registry.remove(relayer1, { from: accounts[1] }).should.be.rejectedWith('unauthorized') + }) + }) + + afterEach(async () => { + await revertSnapshot(snapshotId.result) + // eslint-disable-next-line require-atomic-updates + snapshotId = await takeSnapshot() + }) +})