code and tests
This commit is contained in:
parent
1b1779070e
commit
3e2d286379
@ -1,6 +1,6 @@
|
|||||||
# Proposal 36
|
# Proposal 36
|
||||||
|
|
||||||
Unregister all cheating relayers and restore mistakenly unregistered in last proposal
|
Restore mistakenly unregistered in last proposal
|
||||||
|
|
||||||
Deploy: `npx hardhat run --network mainnet script/deploy.js`
|
Deploy: `npx hardhat run --network mainnet script/deploy.js`
|
||||||
|
|
||||||
|
@ -5,70 +5,35 @@ pragma experimental ABIEncoderV2;
|
|||||||
|
|
||||||
import { IRelayerRegistryProxy } from "./interfaces/RelayerRegistryProxy.sol";
|
import { IRelayerRegistryProxy } from "./interfaces/RelayerRegistryProxy.sol";
|
||||||
import { IRelayerRegistry } from "./interfaces/RelayerRegistry.sol";
|
import { IRelayerRegistry } from "./interfaces/RelayerRegistry.sol";
|
||||||
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
contract Proposal {
|
contract Proposal {
|
||||||
address public immutable newRelayerRegistry;
|
address public immutable newRelayerRegistry;
|
||||||
address public constant relayerRegistryProxyAddr = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
|
address public constant relayerRegistryProxyAddr = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
|
||||||
|
address public constant tornTokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
||||||
|
address public constant me = 0xeb3E49Af2aB5D5D0f83A9289cF5a34d9e1f6C5b4;
|
||||||
|
|
||||||
|
event RelayerRegistrationFailed(address relayer, string ensName, uint256 stake);
|
||||||
|
|
||||||
constructor(address _newRelayerRegistry) public {
|
constructor(address _newRelayerRegistry) public {
|
||||||
newRelayerRegistry = _newRelayerRegistry;
|
newRelayerRegistry = _newRelayerRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNullifiedTotal(address payable[15] memory relayers) public view returns (uint256) {
|
function safeRegisterRelayerAdmin(address relayer, string memory ensName, uint256 newStake) public {
|
||||||
uint256 nullifiedTotal;
|
try IRelayerRegistry(relayerRegistryProxyAddr).registerRelayerAdmin(relayer, ensName, newStake) {} catch {
|
||||||
|
emit RelayerRegistrationFailed(relayer, ensName, newStake);
|
||||||
for (uint8 i = 0; i < relayers.length; i++) {
|
|
||||||
nullifiedTotal += IRelayerRegistry(relayerRegistryProxyAddr).getRelayerBalance(relayers[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullifiedTotal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function executeProposal() public {
|
function executeProposal() public {
|
||||||
IRelayerRegistryProxy relayerRegistryProxy = IRelayerRegistryProxy(relayerRegistryProxyAddr);
|
IRelayerRegistryProxy relayerRegistryProxy = IRelayerRegistryProxy(relayerRegistryProxyAddr);
|
||||||
relayerRegistryProxy.upgradeTo(newRelayerRegistry);
|
relayerRegistryProxy.upgradeTo(newRelayerRegistry);
|
||||||
|
|
||||||
address payable[15] memory cheatingRelayers = [
|
safeRegisterRelayerAdmin(0x4750BCfcC340AA4B31be7e71fa072716d28c29C5, "reltor.eth", 19612626855788464787775);
|
||||||
0x853281B7676DFB66B87e2f26c9cB9D10Ce883F37, // available-reliable-relayer.eth,
|
safeRegisterRelayerAdmin(0xa0109274F53609f6Be97ec5f3052C659AB80f012, "relayer007.eth", 15242825423346070140850);
|
||||||
0x0000208a6cC0299dA631C08fE8c2EDe435Ea83B8, // 0xtornadocash.eth,
|
safeRegisterRelayerAdmin(0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c, "k-relayer.eth", 11850064862377598277981);
|
||||||
0xaaaaD0b504B4CD22348C4Db1071736646Aa314C6, // tornrelayers.eth
|
|
||||||
0x36DD7b862746fdD3eDd3577c8411f1B76FDC2Af5, // tornado-crypto-bot-exchange.eth
|
|
||||||
0x5007565e69E5c23C278c2e976beff38eF4D27B3d, // official-tornado.eth
|
|
||||||
0xa42303EE9B2eC1DB7E2a86Ed6C24AF7E49E9e8B9, // relayer-tornado.eth
|
|
||||||
0x18F516dD6D5F46b2875Fd822B994081274be2a8b, // torn69.eth
|
|
||||||
0x2ffAc4D796261ba8964d859867592B952b9FC158, // safe-tornado.eth
|
|
||||||
0x12D92FeD171F16B3a05ACB1542B40648E7CEd384, // torn-relayers.eth
|
|
||||||
0x996ad81FD83eD7A87FD3D03694115dff19db0B3b, // secure-tornado.eth
|
|
||||||
0x7853E027F37830790685622cdd8685fF0c8255A2, // tornado-secure.eth
|
|
||||||
0xf0D9b969925116074eF43e7887Bcf035Ff1e7B19, // lowfee-relayer.eth
|
|
||||||
0xEFa22d23de9f293B11e0c4aC865d7b440647587a, // tornado-relayer.eth
|
|
||||||
0x14812AE927e2BA5aA0c0f3C0eA016b3039574242, // pls-im-poor.eth
|
|
||||||
0x87BeDf6AD81A2907633Ab68D02c44f0415bc68C1 // tornrelayer.eth
|
|
||||||
];
|
|
||||||
|
|
||||||
IRelayerRegistry relayerRegistry = IRelayerRegistry(relayerRegistryProxyAddr);
|
// Compensation, will be a real value
|
||||||
|
IERC20(tornTokenAddress).transfer(me, 1);
|
||||||
uint256 nullifiedTotal = getNullifiedTotal(cheatingRelayers);
|
|
||||||
uint256 compensation = nullifiedTotal / 3;
|
|
||||||
|
|
||||||
for (uint i = 0; i < cheatingRelayers.length; i++) {
|
|
||||||
relayerRegistry.unregisterRelayer(cheatingRelayers[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
relayerRegistry.registerRelayerAdmin(
|
|
||||||
0x4750BCfcC340AA4B31be7e71fa072716d28c29C5,
|
|
||||||
"reltor.eth",
|
|
||||||
19612626855788464787775 + compensation
|
|
||||||
);
|
|
||||||
relayerRegistry.registerRelayerAdmin(
|
|
||||||
0xa0109274F53609f6Be97ec5f3052C659AB80f012,
|
|
||||||
"relayer007.eth",
|
|
||||||
15242825423346070140850 + compensation
|
|
||||||
);
|
|
||||||
relayerRegistry.registerRelayerAdmin(
|
|
||||||
0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c,
|
|
||||||
"k-relayer.eth",
|
|
||||||
11850064862377598277981 + compensation
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,5 @@
|
|||||||
pragma solidity ^0.6.12;
|
pragma solidity ^0.6.12;
|
||||||
|
|
||||||
interface IRelayerRegistry {
|
interface IRelayerRegistry {
|
||||||
function unregisterRelayer(address relayer) external;
|
|
||||||
|
|
||||||
function registerRelayerAdmin(address relayer, string calldata ensName, uint256 stake) external;
|
function registerRelayerAdmin(address relayer, string calldata ensName, uint256 stake) external;
|
||||||
|
|
||||||
function setOperator(address newOperator) external;
|
|
||||||
|
|
||||||
function getRelayerBalance(address relayer) external view returns (uint256);
|
|
||||||
}
|
}
|
||||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "proposal-34",
|
"name": "proposal-36",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "proposal-34",
|
"name": "proposal-36",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,18 +1,14 @@
|
|||||||
const { expect, assert } = require("chai");
|
const { expect, assert } = require("chai");
|
||||||
const { ethers, network, config } = require("hardhat");
|
const { ethers, network, config } = require("hardhat");
|
||||||
const {
|
const {
|
||||||
sendMinimalStakeAmount,
|
|
||||||
resolveAddr,
|
resolveAddr,
|
||||||
getEnsRegistryContract,
|
|
||||||
getOldRelayerRegistryContract,
|
|
||||||
getRegisterRelayerParams,
|
getRegisterRelayerParams,
|
||||||
getManyEth,
|
|
||||||
deployAndExecuteProposal,
|
deployAndExecuteProposal,
|
||||||
unregisterRelayer,
|
|
||||||
getRelayerRegistryContract,
|
getRelayerRegistryContract,
|
||||||
getRelayerBalance,
|
getRelayerBalance,
|
||||||
|
getEnsRegistryContract,
|
||||||
governanceAddr,
|
governanceAddr,
|
||||||
cheatingRelayers
|
getManyEth,
|
||||||
} = require("./utils");
|
} = require("./utils");
|
||||||
|
|
||||||
describe("Registry update", function () {
|
describe("Registry update", function () {
|
||||||
@ -41,195 +37,54 @@ describe("Registry update", function () {
|
|||||||
expect(implementationAddr).to.equal(deployedRegistryAddr);
|
expect(implementationAddr).to.equal(deployedRegistryAddr);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Unregister relayer", function () {
|
|
||||||
it("Uregister relayer function should work", async function () {
|
|
||||||
const testRelayerAddr = await resolveAddr("first-relayer.eth");
|
|
||||||
|
|
||||||
const relayerRegistryOldContract = await getOldRelayerRegistryContract();
|
|
||||||
let isRelayer = await relayerRegistryOldContract.isRelayer(testRelayerAddr);
|
|
||||||
let isRelayerRegistered = await relayerRegistryOldContract.isRelayerRegistered(testRelayerAddr, testRelayerAddr);
|
|
||||||
expect(isRelayer).to.equal(true);
|
|
||||||
expect(isRelayerRegistered).to.equal(true);
|
|
||||||
|
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
|
||||||
await unregisterRelayer(testRelayerAddr);
|
|
||||||
|
|
||||||
isRelayer = await relayerRegistryContract.isRelayer(testRelayerAddr);
|
|
||||||
isRelayerRegistered = await relayerRegistryContract.isRelayerRegistered(testRelayerAddr, testRelayerAddr);
|
|
||||||
|
|
||||||
expect(isRelayer).to.equal(false);
|
|
||||||
expect(isRelayerRegistered).to.equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Unregistered relayer should have zero balance", async function () {
|
|
||||||
const testRelayerAddr = await resolveAddr("first-relayer.eth");
|
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
|
||||||
await unregisterRelayer(testRelayerAddr);
|
|
||||||
|
|
||||||
const relayerBalance = await relayerRegistryContract.getRelayerBalance(testRelayerAddr);
|
|
||||||
expect(relayerBalance).to.equal(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Unregister function should revert if called not by Governance", async function () {
|
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
|
||||||
|
|
||||||
const me = await resolveAddr("🦋️-effect.eth");
|
|
||||||
await getManyEth(me);
|
|
||||||
const meAsSigner = await ethers.getImpersonatedSigner(me);
|
|
||||||
const testRelayerAddr = await resolveAddr("first-relayer.eth");
|
|
||||||
const relayerRegistryWithMeAsSigner = relayerRegistryContract.connect(meAsSigner);
|
|
||||||
|
|
||||||
await expect(relayerRegistryWithMeAsSigner.unregisterRelayer(testRelayerAddr)).to.be.revertedWith(
|
|
||||||
"only governance",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Tornado router address should be valid", async function () {
|
|
||||||
const relayerRegistryOldContract = await getOldRelayerRegistryContract();
|
|
||||||
const oldRegistryRouterAddress = await relayerRegistryOldContract.tornadoRouter();
|
|
||||||
|
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
|
||||||
expect(await relayerRegistryContract.tornadoRouter()).to.equal(oldRegistryRouterAddress);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Aggregator contract data for unregistered relayers should be valid", async function () {
|
|
||||||
const aggregatorAddr = "0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49";
|
|
||||||
const aggregatorContract = await ethers.getContractAt(require("./abi/aggregator.abi.json"), aggregatorAddr);
|
|
||||||
const notRelayer = "🦋️-effect.eth";
|
|
||||||
const testRelayer = "first-relayer.eth";
|
|
||||||
|
|
||||||
const callAggr = async () =>
|
|
||||||
await aggregatorContract.relayersData([notRelayer, testRelayer].map(ethers.namehash), [
|
|
||||||
"mainnet-tornado",
|
|
||||||
"bsc-tornado",
|
|
||||||
]);
|
|
||||||
const oldData = await callAggr();
|
|
||||||
|
|
||||||
await deployAndExecuteProposal();
|
|
||||||
await unregisterRelayer(testRelayer);
|
|
||||||
|
|
||||||
const newData = await callAggr();
|
|
||||||
|
|
||||||
assert.deepEqual(oldData[0], newData[0]);
|
|
||||||
expect(oldData[1][1]).to.greaterThan(500n * 10n ** 18n);
|
|
||||||
expect(newData[1][1]).to.equal(0);
|
|
||||||
expect(oldData[1][2]).to.equal(true);
|
|
||||||
expect(newData[1][2]).to.equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Cheating relayers should be unregistered", async function () {
|
|
||||||
const relayerRegistryOldContract = await getOldRelayerRegistryContract();
|
|
||||||
let areRegistered = await Promise.all(cheatingRelayers.map((r) => relayerRegistryOldContract.isRelayer(r)));
|
|
||||||
let balances = await Promise.all(cheatingRelayers.map((r) => relayerRegistryOldContract.getRelayerBalance(r)));
|
|
||||||
|
|
||||||
expect(areRegistered).satisfy((v) => v.every((v) => v === true));
|
|
||||||
expect(balances).satisfy((v) => v.every((v) => v >= 0n));
|
|
||||||
|
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
|
||||||
areRegistered = await Promise.all(cheatingRelayers.map((r) => relayerRegistryContract.isRelayer(r)));
|
|
||||||
balances = await Promise.all(cheatingRelayers.map((r) => relayerRegistryContract.getRelayerBalance(r)));
|
|
||||||
|
|
||||||
expect(areRegistered).satisfy((v) => v.every((v) => v === false));
|
|
||||||
expect(balances).satisfy((v) => v.every((v) => v === 0n));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Unregistered relayers can register again", async function () {
|
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
|
||||||
const relayerEns = "moon-relayer.eth";
|
|
||||||
const unregisteredRelayer = await resolveAddr(relayerEns);
|
|
||||||
const toStake = await sendMinimalStakeAmount(unregisteredRelayer);
|
|
||||||
|
|
||||||
const relayerSigner = await ethers.getImpersonatedSigner(unregisteredRelayer);
|
|
||||||
await relayerRegistryContract.connect(relayerSigner).register(relayerEns, toStake, []);
|
|
||||||
const isRelayerRegistered = await relayerRegistryContract.isRelayerRegistered(
|
|
||||||
unregisteredRelayer,
|
|
||||||
unregisteredRelayer,
|
|
||||||
);
|
|
||||||
const relayerBalance = await relayerRegistryContract.getRelayerBalance(unregisteredRelayer);
|
|
||||||
|
|
||||||
expect(isRelayerRegistered).to.be.equal(true);
|
|
||||||
expect(relayerBalance).to.be.equal(toStake);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Fix ENS owner checks", async function () {
|
|
||||||
it("ENS owner of wrapped domain should be a wrapper", async function () {
|
|
||||||
const wrappedDomain = "butterfly-attractor.eth";
|
|
||||||
const realOwner = await resolveAddr(wrappedDomain);
|
|
||||||
const ensRegistry = await getEnsRegistryContract();
|
|
||||||
const wrapperOwner = await ensRegistry.owner(ethers.namehash(wrappedDomain));
|
|
||||||
|
|
||||||
expect(wrapperOwner).to.be.not.equal(realOwner);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Registering relayer with wrapped ENS domain should revert", async function () {
|
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
|
||||||
const relayerWrappedEns = "butterfly-attractor.eth";
|
|
||||||
const registerParams = await getRegisterRelayerParams(relayerWrappedEns);
|
|
||||||
const [relayer] = await ethers.getSigners();
|
|
||||||
const relayerRegistry = relayerRegistryContract.connect(relayer);
|
|
||||||
|
|
||||||
await expect(relayerRegistry.registerPermit(...registerParams)).to.be.revertedWith("only unwrapped ens domains");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("After ENS domain unwrapping owner can register relayer", async function () {
|
|
||||||
await deployAndExecuteProposal();
|
|
||||||
const ensWrapperAddr = "0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401";
|
|
||||||
const wrappedEnsDomain = "butterfly-attractor.eth";
|
|
||||||
const addr = await resolveAddr(wrappedEnsDomain);
|
|
||||||
const wrapperContract = await ethers.getContractAt(require("./abi/ensWrapper.abi.json"), ensWrapperAddr);
|
|
||||||
const labelhash = ethers.keccak256(ethers.toUtf8Bytes(wrappedEnsDomain.split(".")[0]));
|
|
||||||
await wrapperContract.unwrapETH2LD(labelhash, addr, addr);
|
|
||||||
|
|
||||||
const relayerSigner = await ethers.getSigner(addr);
|
|
||||||
const relayerRegistryContract = await getRelayerRegistryContract(relayerSigner);
|
|
||||||
const registerParams = await getRegisterRelayerParams(wrappedEnsDomain);
|
|
||||||
await relayerRegistryContract.registerPermit(...registerParams);
|
|
||||||
|
|
||||||
expect(await relayerRegistryContract.isRelayerRegistered(addr, addr)).to.be.equal(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Restore relayers", async function () {
|
describe("Restore relayers", async function () {
|
||||||
const blockBeforeProposal32Execution = 18484836;
|
const blockBeforeProposal32Execution = 18484836;
|
||||||
const unregisteredByMistake = ["reltor.eth", "relayer007.eth", "k-relayer.eth"];
|
const unregisteredByMistake = ["reltor.eth", "relayer007.eth", "k-relayer.eth"];
|
||||||
const unregisteredAddrs = ["0x4750BCfcC340AA4B31be7e71fa072716d28c29C5", "0xa0109274F53609f6Be97ec5f3052C659AB80f012", "0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c"];
|
const unregisteredAddrs = [
|
||||||
|
"0x4750BCfcC340AA4B31be7e71fa072716d28c29C5",
|
||||||
|
"0xa0109274F53609f6Be97ec5f3052C659AB80f012",
|
||||||
|
"0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c",
|
||||||
|
];
|
||||||
|
|
||||||
it("Relayer ENS names links to mistakenly unregistered relayers", async function () {
|
it("Relayer ENS names links to mistakenly unregistered relayers", async function () {
|
||||||
const maybeUnregisteredAddrs = await Promise.all(unregisteredByMistake.map(resolveAddr));
|
const maybeUnregisteredAddrs = await Promise.all(unregisteredByMistake.map(resolveAddr));
|
||||||
|
|
||||||
expect(maybeUnregisteredAddrs.map(ethers.getAddress)).to.deep.equal(unregisteredAddrs);
|
expect(maybeUnregisteredAddrs.map(ethers.getAddress)).to.deep.equal(unregisteredAddrs);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Current balance of mistakenly unregistered relayers should be zero", async function () {
|
it("Current balance of mistakenly unregistered relayers should be zero", async function () {
|
||||||
const balances = await Promise.all(unregisteredAddrs.map(addr => getRelayerBalance(addr)));
|
const balances = await Promise.all(unregisteredAddrs.map((addr) => getRelayerBalance(addr)));
|
||||||
|
|
||||||
expect(balances).to.deep.equal([0, 0, 0]);
|
expect(balances).to.deep.equal([0, 0, 0]);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Mistakenly unregistered relayers should be really unregistered before proposal", async function () {
|
it("Mistakenly unregistered relayers should be really unregistered before proposal", async function () {
|
||||||
const relayerRegistryContract = await getRelayerRegistryContract();
|
const relayerRegistryContract = await getRelayerRegistryContract();
|
||||||
const areWorkers = await Promise.all(unregisteredAddrs.map(addr => relayerRegistryContract.isRelayer(addr)));
|
const areWorkers = await Promise.all(unregisteredAddrs.map((addr) => relayerRegistryContract.isRelayer(addr)));
|
||||||
const areRelayers = await Promise.all(unregisteredAddrs.map(addr => relayerRegistryContract.isRelayerRegistered(addr, addr)));
|
const areRelayers = await Promise.all(
|
||||||
|
unregisteredAddrs.map((addr) => relayerRegistryContract.isRelayerRegistered(addr, addr)),
|
||||||
|
);
|
||||||
|
|
||||||
expect(areWorkers).to.deep.equal([false, false, false]);
|
expect(areWorkers).to.deep.equal([false, false, false]);
|
||||||
expect(areRelayers).to.deep.equal([false, false, false]);
|
expect(areRelayers).to.deep.equal([false, false, false]);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Should return before-proposal stake plus compensation to mistakenly unregistered relayers and register them again", async function() {
|
it("Should return before-proposal to mistakenly unregistered relayers and register them again", async function () {
|
||||||
const relayerBalancesOld = await Promise.all(unregisteredAddrs.map(addr => getRelayerBalance(addr, blockBeforeProposal32Execution)));
|
const relayerBalancesOld = await Promise.all(
|
||||||
const cheatingRelayersBalances = await Promise.all(cheatingRelayers.map((r) => getRelayerBalance(r)));
|
unregisteredAddrs.map((addr) => getRelayerBalance(addr, blockBeforeProposal32Execution)),
|
||||||
const compensationForOneRelayer = cheatingRelayersBalances.reduce((a, b) => a + b, 0n) / 3n;
|
);
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
||||||
const relayerBalancesNew = await Promise.all(unregisteredAddrs.map(addr => getRelayerBalance(addr)));
|
const relayerBalancesNew = await Promise.all(unregisteredAddrs.map((addr) => getRelayerBalance(addr)));
|
||||||
const areWorkers = await Promise.all(unregisteredAddrs.map(addr => relayerRegistryContract.isRelayer(addr)));
|
const areWorkers = await Promise.all(unregisteredAddrs.map((addr) => relayerRegistryContract.isRelayer(addr)));
|
||||||
const areRelayers = await Promise.all(unregisteredAddrs.map(addr => relayerRegistryContract.isRelayerRegistered(addr, addr)));
|
const areRelayers = await Promise.all(
|
||||||
|
unregisteredAddrs.map((addr) => relayerRegistryContract.isRelayerRegistered(addr, addr)),
|
||||||
|
);
|
||||||
|
|
||||||
expect(relayerBalancesNew).to.deep.equal(relayerBalancesOld.map(b => b + compensationForOneRelayer));
|
expect(relayerBalancesNew).to.deep.equal(relayerBalancesOld);
|
||||||
expect(relayerBalancesNew).satisfy((b) => b.every((b) => b < 20000n * 10n ** 18n && b > 10000n * 10n ** 18n));
|
expect(relayerBalancesNew).satisfy((b) => b.every((b) => b < 20000n * 10n ** 18n && b > 10000n * 10n ** 18n));
|
||||||
expect(areWorkers).to.deep.equal([true, true, true]);
|
expect(areWorkers).to.deep.equal([true, true, true]);
|
||||||
expect(areRelayers).to.deep.equal([true, true, true]);
|
expect(areRelayers).to.deep.equal([true, true, true]);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Should register relayer even if someone steal address as a worker", async function () {
|
it("Should register relayer even if someone steal address as a worker", async function () {
|
||||||
await deployAndExecuteProposal();
|
await deployAndExecuteProposal();
|
||||||
@ -258,23 +113,27 @@ describe("Registry update", function () {
|
|||||||
expect(await relayerRegistryContract.isRelayer(addr)).to.be.equal(true);
|
expect(await relayerRegistryContract.isRelayer(addr)).to.be.equal(true);
|
||||||
expect(await relayerRegistryContract.isRelayerRegistered(addr, addr)).to.be.equal(true);
|
expect(await relayerRegistryContract.isRelayerRegistered(addr, addr)).to.be.equal(true);
|
||||||
expect(await getRelayerBalance(addr)).to.be.equal(2000n * 10n ** 18n);
|
expect(await getRelayerBalance(addr)).to.be.equal(2000n * 10n ** 18n);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Should revert if trying to register existing relayer via Governance", async function () {
|
it("Should revert if trying to register existing relayer via Governance", async function () {
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
||||||
const realRelayerDomain = "torrelayer.eth";
|
const realRelayerDomain = "torrelayer.eth";
|
||||||
const realRelayer = await resolveAddr(realRelayerDomain);
|
const realRelayer = await resolveAddr(realRelayerDomain);
|
||||||
|
|
||||||
await expect(relayerRegistryContract.registerRelayerAdmin(realRelayer, realRelayerDomain, 1)).to.be.revertedWith("cant register again")
|
await expect(relayerRegistryContract.registerRelayerAdmin(realRelayer, realRelayerDomain, 1)).to.be.revertedWith(
|
||||||
})
|
"cant register again",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("Should revert if trying to register relayer with domain that he not own", async function () {
|
it("Should revert if trying to register relayer with domain that he not own", async function () {
|
||||||
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
||||||
const someDomain = "vitalik.eth";
|
const someDomain = "vitalik.eth";
|
||||||
const me = "0xeb3E49Af2aB5D5D0f83A9289cF5a34d9e1f6C5b4";
|
const me = "0xeb3E49Af2aB5D5D0f83A9289cF5a34d9e1f6C5b4";
|
||||||
|
|
||||||
await expect(relayerRegistryContract.registerRelayerAdmin(me, someDomain, 1)).to.be.revertedWith("only ens domain owner");
|
await expect(relayerRegistryContract.registerRelayerAdmin(me, someDomain, 1)).to.be.revertedWith(
|
||||||
})
|
"only ens domain owner",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("Admin register function should fail, if called not from Governance", async function () {
|
it("Admin register function should fail, if called not from Governance", async function () {
|
||||||
await deployAndExecuteProposal();
|
await deployAndExecuteProposal();
|
||||||
@ -282,7 +141,34 @@ describe("Registry update", function () {
|
|||||||
const meAsSigner = await ethers.getImpersonatedSigner(me);
|
const meAsSigner = await ethers.getImpersonatedSigner(me);
|
||||||
const relayerRegistryContract = await getRelayerRegistryContract(meAsSigner);
|
const relayerRegistryContract = await getRelayerRegistryContract(meAsSigner);
|
||||||
|
|
||||||
await expect(relayerRegistryContract.registerRelayerAdmin(me, "butterfly-attractor.eth", 1)).to.be.revertedWith("only governance");
|
await expect(relayerRegistryContract.registerRelayerAdmin(me, "butterfly-attractor.eth", 1)).to.be.revertedWith(
|
||||||
})
|
"only governance",
|
||||||
})
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Proposal execution should not fail, if one relayer can not be registered", async function () {
|
||||||
|
const relayerEns = "reltor.eth";
|
||||||
|
const relayerAddr = await resolveAddr("reltor.eth");
|
||||||
|
const relayerSigner = await ethers.getImpersonatedSigner(relayerAddr);
|
||||||
|
const me = "0xeb3E49Af2aB5D5D0f83A9289cF5a34d9e1f6C5b4";
|
||||||
|
const ens = await getEnsRegistryContract(relayerSigner);
|
||||||
|
await getManyEth(relayerAddr);
|
||||||
|
await ens.setOwner(ethers.namehash(relayerEns), me);
|
||||||
|
expect(await ens.owner(ethers.namehash(relayerEns))).to.be.equal(me);
|
||||||
|
|
||||||
|
const { relayerRegistryContract } = await deployAndExecuteProposal();
|
||||||
|
await expect(relayerRegistryContract.registerRelayerAdmin(relayerAddr, relayerEns, 1)).to.be.revertedWith(
|
||||||
|
"only ens domain owner",
|
||||||
|
);
|
||||||
|
|
||||||
|
const areWorkers = await Promise.all(unregisteredAddrs.map((addr) => relayerRegistryContract.isRelayer(addr)));
|
||||||
|
const areRelayers = await Promise.all(
|
||||||
|
unregisteredAddrs.map((addr) => relayerRegistryContract.isRelayerRegistered(addr, addr)),
|
||||||
|
);
|
||||||
|
expect(relayerAddr).to.be.equal(unregisteredAddrs[0]);
|
||||||
|
expect(relayerEns).to.be.equal(unregisteredByMistake[0]);
|
||||||
|
expect(areRelayers).to.deep.equal([false, true, true]);
|
||||||
|
expect(areWorkers).to.deep.equal([false, true, true]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -4,24 +4,6 @@ const ensAddr = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
|
|||||||
const relayerRegistryProxyAddr = "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2";
|
const relayerRegistryProxyAddr = "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2";
|
||||||
const tornAddr = "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C";
|
const tornAddr = "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C";
|
||||||
const governanceAddr = "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce";
|
const governanceAddr = "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce";
|
||||||
const cheatingRelayers = [
|
|
||||||
"0x853281B7676DFB66B87e2f26c9cB9D10Ce883F37", // available-reliable-relayer.eth,
|
|
||||||
"0x0000208a6cC0299dA631C08fE8c2EDe435Ea83B8", // 0xtornadocash.eth,
|
|
||||||
"0xaaaaD0b504B4CD22348C4Db1071736646Aa314C6", // tornrelayers.eth
|
|
||||||
"0x36DD7b862746fdD3eDd3577c8411f1B76FDC2Af5", // tornado-crypto-bot-exchange.eth
|
|
||||||
"0x5007565e69E5c23C278c2e976beff38eF4D27B3d", // official-tornado.eth
|
|
||||||
"0xa42303EE9B2eC1DB7E2a86Ed6C24AF7E49E9e8B9", // relayer-tornado.eth
|
|
||||||
"0x18F516dD6D5F46b2875Fd822B994081274be2a8b", // torn69.eth
|
|
||||||
"0x2ffAc4D796261ba8964d859867592B952b9FC158", // safe-tornado.eth
|
|
||||||
"0x12D92FeD171F16B3a05ACB1542B40648E7CEd384", // torn-relayers.eth
|
|
||||||
"0x996ad81FD83eD7A87FD3D03694115dff19db0B3b", // secure-tornado.eth
|
|
||||||
"0x7853E027F37830790685622cdd8685fF0c8255A2", // tornado-secure.eth
|
|
||||||
"0xf0D9b969925116074eF43e7887Bcf035Ff1e7B19", // lowfee-relayer.eth
|
|
||||||
"0xEFa22d23de9f293B11e0c4aC865d7b440647587a", // tornado-relayer.eth
|
|
||||||
"0x14812AE927e2BA5aA0c0f3C0eA016b3039574242", // pls-im-poor.eth
|
|
||||||
"0x87BeDf6AD81A2907633Ab68D02c44f0415bc68C1" // tornrelayer.eth
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
async function getPermitSignature(signer, tokenContract, spender, value, deadline) {
|
async function getPermitSignature(signer, tokenContract, spender, value, deadline) {
|
||||||
const [nonce, name, version, chainId] = await Promise.all([
|
const [nonce, name, version, chainId] = await Promise.all([
|
||||||
@ -89,8 +71,8 @@ async function getRegisterRelayerParams(ensDomain, additionalStake = 0, workerAd
|
|||||||
return [ensDomain, toStake, workerAddrs, relayerAddr, ethers.MaxUint256, v, r, s];
|
return [ensDomain, toStake, workerAddrs, relayerAddr, ethers.MaxUint256, v, r, s];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getEnsRegistryContract() {
|
async function getEnsRegistryContract(signer) {
|
||||||
return await ethers.getContractAt(require("./abi/ensRegistry.abi.json"), ensAddr);
|
return await ethers.getContractAt(require("./abi/ensRegistry.abi.json"), ensAddr, signer);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resolveAddr(ensName) {
|
async function resolveAddr(ensName) {
|
||||||
@ -192,5 +174,4 @@ module.exports = {
|
|||||||
getRegisterRelayerParams,
|
getRegisterRelayerParams,
|
||||||
getRelayerBalance,
|
getRelayerBalance,
|
||||||
governanceAddr,
|
governanceAddr,
|
||||||
cheatingRelayers
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user