ens error if domain wrapped + tests
This commit is contained in:
parent
8e57772160
commit
c9eb84d312
@ -130,7 +130,11 @@ contract RelayerRegistry is Initializable, EnsResolve {
|
|||||||
address[] calldata workersToRegister
|
address[] calldata workersToRegister
|
||||||
) internal {
|
) internal {
|
||||||
bytes32 ensHash = bytes(ensName).namehash();
|
bytes32 ensHash = bytes(ensName).namehash();
|
||||||
require(relayer == ens.owner(ensHash), "only ens owner");
|
address domainOwner = ens.owner(ensHash);
|
||||||
|
address ensNameWrapper = 0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401;
|
||||||
|
|
||||||
|
require(domainOwner != ensNameWrapper, "only unwrapped ens domains");
|
||||||
|
require(relayer == domainOwner, "only ens domain owner");
|
||||||
require(workers[relayer] == address(0), "cant register again");
|
require(workers[relayer] == address(0), "cant register again");
|
||||||
RelayerState storage metadata = relayers[relayer];
|
RelayerState storage metadata = relayers[relayer];
|
||||||
|
|
||||||
|
41
contracts/libraries/Permit.sol
Normal file
41
contracts/libraries/Permit.sol
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pragma solidity ^0.6.12;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
contract Permit {
|
||||||
|
function getPermitMessage(
|
||||||
|
string memory tokenName,
|
||||||
|
address tokenAddress,
|
||||||
|
string memory version,
|
||||||
|
address owner,
|
||||||
|
address spender,
|
||||||
|
uint256 chainId,
|
||||||
|
uint256 nonce,
|
||||||
|
uint256 amount,
|
||||||
|
uint256 deadline
|
||||||
|
) public pure returns (bytes32) {
|
||||||
|
bytes32 permitTypehash = keccak256(
|
||||||
|
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
|
||||||
|
);
|
||||||
|
uint16 permitFuncSelector = uint16(0x1901);
|
||||||
|
bytes32 domain = keccak256(
|
||||||
|
abi.encode(
|
||||||
|
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
|
||||||
|
keccak256(bytes(tokenName)),
|
||||||
|
keccak256(bytes(version)),
|
||||||
|
chainId,
|
||||||
|
tokenAddress
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return
|
||||||
|
keccak256(
|
||||||
|
abi.encodePacked(
|
||||||
|
permitFuncSelector,
|
||||||
|
domain,
|
||||||
|
keccak256(abi.encode(permitTypehash, owner, spender, amount, nonce, deadline))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +1,33 @@
|
|||||||
require("@nomicfoundation/hardhat-toolbox");
|
require("@nomicfoundation/hardhat-toolbox");
|
||||||
require("dotenv").config()
|
require("dotenv").config();
|
||||||
|
|
||||||
/** @type import('hardhat/config').HardhatUserConfig */
|
/** @type import('hardhat/config').HardhatUserConfig */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
solidity: "0.6.12",
|
solidity: "0.6.12",
|
||||||
|
mocha: {
|
||||||
|
timeout: 100000000,
|
||||||
|
},
|
||||||
networks: {
|
networks: {
|
||||||
mainnet: {
|
mainnet: {
|
||||||
url: "https://eth.llamarpc.com"
|
url: "https://eth.llamarpc.com",
|
||||||
|
accounts: [process.env.REAL_PK],
|
||||||
},
|
},
|
||||||
testnet: {
|
testnet: {
|
||||||
url: "https://ethereum-goerli.publicnode.com",
|
url: "https://ethereum-goerli.publicnode.com",
|
||||||
accounts: [process.env.TEST_PK]
|
accounts: [process.env.TEST_PK],
|
||||||
},
|
},
|
||||||
hardhat: {
|
hardhat: {
|
||||||
forking: {
|
forking: {
|
||||||
url: "https://eth.llamarpc.com",
|
url: "https://eth.llamarpc.com",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
blockNumber: 18391425,
|
blockNumber: 18431526,
|
||||||
|
accounts: [process.env.REAL_PK],
|
||||||
|
},
|
||||||
|
chainId: 1,
|
||||||
|
accounts: [{ privateKey: process.env.REAL_PK, balance: "10000000000000000000000000000000" }],
|
||||||
},
|
},
|
||||||
chainId: 1
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
etherscan: {
|
etherscan: {
|
||||||
apiKey: process.env.ETHERSCAN_KEY
|
apiKey: process.env.ETHERSCAN_KEY,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,80 +1,33 @@
|
|||||||
const { time, loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers");
|
const { loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers");
|
||||||
const { expect, assert } = require("chai");
|
const { expect, assert } = require("chai");
|
||||||
const { ethers, network } = require("hardhat");
|
const { ethers, network, config } = require("hardhat");
|
||||||
const { relayerRegistry } = require("torn-token");
|
const {
|
||||||
|
sendMinimalStakeAmount,
|
||||||
|
resolveAddr,
|
||||||
|
getEnsRegistryContract,
|
||||||
|
getOldRelayerRegistryContractFixture,
|
||||||
|
getRegisterRelayerParams,
|
||||||
|
getManyEth,
|
||||||
|
deployAndExecuteFixture,
|
||||||
|
unregisterRelayer,
|
||||||
|
getRelayerRegistryContract,
|
||||||
|
} = require("./utils");
|
||||||
|
|
||||||
describe("Registry update", function () {
|
describe("Registry update", function () {
|
||||||
async function deployAndExecuteFixture() {
|
|
||||||
const RelayerRegistryFactory = await ethers.getContractFactory("RelayerRegistry");
|
|
||||||
const constructorArgs = [
|
|
||||||
"0x77777FeDdddFfC19Ff86DB637967013e6C6A116C",
|
|
||||||
"0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce",
|
|
||||||
"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
|
|
||||||
"0x5B3f656C80E8ddb9ec01Dd9018815576E9238c29",
|
|
||||||
"0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7",
|
|
||||||
];
|
|
||||||
const relayerRegistry = await RelayerRegistryFactory.deploy(...constructorArgs);
|
|
||||||
const deployedRegistryAddr = await relayerRegistry.getAddress();
|
|
||||||
const proposalFactory = await ethers.getContractFactory("Proposal");
|
|
||||||
const proposal = await proposalFactory.deploy(deployedRegistryAddr);
|
|
||||||
const deployedProposalAddr = await proposal.getAddress();
|
|
||||||
|
|
||||||
|
|
||||||
const bigStakerAddr = "0xE4143f6377AEcd7193b9731d1C28815b57C4f5Ab";
|
|
||||||
await network.provider.send("hardhat_setBalance", [
|
|
||||||
bigStakerAddr,
|
|
||||||
"0x116663015358483537"
|
|
||||||
]);
|
|
||||||
const stakerSigner = await ethers.getImpersonatedSigner(bigStakerAddr);
|
|
||||||
const governanceAddr = "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce";
|
|
||||||
const governanceContract = await ethers.getContractAt(require("./abi/governance.abi.json"), governanceAddr, stakerSigner);
|
|
||||||
await governanceContract.propose(deployedProposalAddr, "");
|
|
||||||
const proposalId = await governanceContract.proposalCount();
|
|
||||||
await time.increase(60 * 60);
|
|
||||||
await governanceContract.castVote(proposalId, true);
|
|
||||||
await time.increase(60 * 60 * 24 * 7 + 60);
|
|
||||||
await governanceContract.execute(proposalId);
|
|
||||||
|
|
||||||
const governanceSigner = await ethers.getImpersonatedSigner(governanceAddr);
|
|
||||||
const relayerRegistryProxyAddr = "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2";
|
|
||||||
const relayerRegistryContract = await ethers.getContractAt("RelayerRegistry", relayerRegistryProxyAddr, governanceSigner);
|
|
||||||
|
|
||||||
return { relayerRegistryProxyAddr, deployedRegistryAddr, relayerRegistryContract, governanceSigner };
|
|
||||||
}
|
|
||||||
|
|
||||||
async function unregisterRelayer(ensNameOrAddress){
|
|
||||||
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
|
||||||
const relayerAddr = ethers.isAddress(ensNameOrAddress) ? ensNameOrAddress : resolveAddr(ensNameOrAddress);
|
|
||||||
await relayerRegistryContract.unregisterRelayer(relayerAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function resolveAddr(ensName){
|
|
||||||
const ensNode = ethers.namehash(ensName);
|
|
||||||
const ensAddr = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
|
|
||||||
const registryContract = await ethers.getContractAt(require("./abi/ensRegistry.abi.json"), ensAddr);
|
|
||||||
const resolverAddr = await registryContract.resolver(ensNode);
|
|
||||||
const resolverContract = await ethers.getContractAt(require("./abi/ensResolver.abi.json"), resolverAddr);
|
|
||||||
|
|
||||||
return await resolverContract.addr(ensNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getOldRelayerRegistryContractFixture(){
|
|
||||||
const relayerRegistryProxyAddr = "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2";
|
|
||||||
return await ethers.getContractAt(require("./abi/relayerRegistryOld.abi.json"), relayerRegistryProxyAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
it("Implementation address should be updated", async function () {
|
it("Implementation address should be updated", async function () {
|
||||||
await loadFixture(getOldRelayerRegistryContractFixture);
|
await loadFixture(getOldRelayerRegistryContractFixture);
|
||||||
const { relayerRegistryProxyAddr, deployedRegistryAddr } = await loadFixture(deployAndExecuteFixture);
|
const { relayerRegistryProxyAddr, deployedRegistryAddr } = await loadFixture(deployAndExecuteFixture);
|
||||||
const implementation = await ethers.provider.getStorage(relayerRegistryProxyAddr, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
|
const implementation = await ethers.provider.getStorage(
|
||||||
|
relayerRegistryProxyAddr,
|
||||||
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||||
|
);
|
||||||
const [implementationAddr] = new ethers.AbiCoder().decode(["address"], implementation);
|
const [implementationAddr] = new ethers.AbiCoder().decode(["address"], implementation);
|
||||||
|
|
||||||
expect(implementationAddr).to.equal(deployedRegistryAddr)
|
expect(implementationAddr).to.equal(deployedRegistryAddr);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Unregister relayer", function(){
|
describe("Unregister relayer", function () {
|
||||||
|
it("Uregister relayer function should work", async function () {
|
||||||
it("Uregister relayer function should work", async function(){
|
|
||||||
const testRelayerAddr = await resolveAddr("first-relayer.eth");
|
const testRelayerAddr = await resolveAddr("first-relayer.eth");
|
||||||
|
|
||||||
const relayerRegistryOldContract = await loadFixture(getOldRelayerRegistryContractFixture);
|
const relayerRegistryOldContract = await loadFixture(getOldRelayerRegistryContractFixture);
|
||||||
@ -91,32 +44,50 @@ describe("Registry update", function () {
|
|||||||
|
|
||||||
expect(isRelayer).to.equal(false);
|
expect(isRelayer).to.equal(false);
|
||||||
expect(isRelayerRegistered).to.equal(false);
|
expect(isRelayerRegistered).to.equal(false);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Unregistered relayer should have zero balance", async function(){
|
it("Unregistered relayer should have zero balance", async function () {
|
||||||
const testRelayerAddr = await resolveAddr("first-relayer.eth");
|
const testRelayerAddr = await resolveAddr("first-relayer.eth");
|
||||||
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
||||||
await unregisterRelayer(testRelayerAddr);
|
await unregisterRelayer(testRelayerAddr);
|
||||||
|
|
||||||
const relayerBalance = await relayerRegistryContract.getRelayerBalance(testRelayerAddr);
|
const relayerBalance = await relayerRegistryContract.getRelayerBalance(testRelayerAddr);
|
||||||
expect(relayerBalance).to.equal(0);
|
expect(relayerBalance).to.equal(0);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Tornado router address should be valid", async function(){
|
it("Unregister function should revert if called not by Governance", async function () {
|
||||||
|
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
||||||
|
|
||||||
|
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 loadFixture(getOldRelayerRegistryContractFixture);
|
const relayerRegistryOldContract = await loadFixture(getOldRelayerRegistryContractFixture);
|
||||||
const oldRegistryRouterAddress = await relayerRegistryOldContract.tornadoRouter();
|
const oldRegistryRouterAddress = await relayerRegistryOldContract.tornadoRouter();
|
||||||
|
|
||||||
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
||||||
expect(await relayerRegistryContract.tornadoRouter()).to.equal(oldRegistryRouterAddress);
|
expect(await relayerRegistryContract.tornadoRouter()).to.equal(oldRegistryRouterAddress);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Aggregator contract data for unregistered relayers should be valid", async function(){
|
it("Aggregator contract data for unregistered relayers should be valid", async function () {
|
||||||
const aggregatorAddr = "0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49";
|
const aggregatorAddr = "0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49";
|
||||||
const aggregatorContract = await ethers.getContractAt(require("./abi/aggregator.abi.json"), aggregatorAddr);
|
const aggregatorContract = await ethers.getContractAt(require("./abi/aggregator.abi.json"), aggregatorAddr);
|
||||||
const notRelayer = "🦋️-effect.eth";
|
const notRelayer = "🦋️-effect.eth";
|
||||||
const testRelayer = "first-relayer.eth";
|
const testRelayer = "first-relayer.eth";
|
||||||
|
|
||||||
const callAggr = async () => await aggregatorContract.relayersData([notRelayer, testRelayer].map(ethers.namehash), ["mainnet-tornado", "bsc-tornado"]);
|
const callAggr = async () =>
|
||||||
|
await aggregatorContract.relayersData([notRelayer, testRelayer].map(ethers.namehash), [
|
||||||
|
"mainnet-tornado",
|
||||||
|
"bsc-tornado",
|
||||||
|
]);
|
||||||
const oldData = await callAggr();
|
const oldData = await callAggr();
|
||||||
|
|
||||||
await loadFixture(deployAndExecuteFixture);
|
await loadFixture(deployAndExecuteFixture);
|
||||||
@ -129,47 +100,99 @@ describe("Registry update", function () {
|
|||||||
expect(newData[1][1]).to.equal(0);
|
expect(newData[1][1]).to.equal(0);
|
||||||
expect(oldData[1][2]).to.equal(true);
|
expect(oldData[1][2]).to.equal(true);
|
||||||
expect(newData[1][2]).to.equal(false);
|
expect(newData[1][2]).to.equal(false);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Cheating relayers should be unregistered", async function(){
|
it("Cheating relayers should be unregistered", async function () {
|
||||||
const cheatingRelayers = await Promise.all([
|
const cheatingRelayers = await Promise.all(
|
||||||
|
[
|
||||||
"available-reliable-relayer.eth",
|
"available-reliable-relayer.eth",
|
||||||
"0xtornadocash.eth",
|
"0xtornadocash.eth",
|
||||||
"0xtorn365.eth",
|
"0xtorn365.eth",
|
||||||
"tornrelayers.eth",
|
"tornrelayers.eth",
|
||||||
"moon-relayer.eth"
|
"moon-relayer.eth",
|
||||||
].map(resolveAddr));
|
].map(resolveAddr),
|
||||||
|
);
|
||||||
|
|
||||||
const relayerRegistryOldContract = await loadFixture(getOldRelayerRegistryContractFixture);
|
const relayerRegistryOldContract = await loadFixture(getOldRelayerRegistryContractFixture);
|
||||||
let areRegistered = await Promise.all(cheatingRelayers.map(r => relayerRegistryOldContract.isRelayer(r)));
|
let areRegistered = await Promise.all(cheatingRelayers.map((r) => relayerRegistryOldContract.isRelayer(r)));
|
||||||
let balances = await Promise.all(cheatingRelayers.map(r => relayerRegistryOldContract.getRelayerBalance(r)));
|
let balances = await Promise.all(cheatingRelayers.map((r) => relayerRegistryOldContract.getRelayerBalance(r)));
|
||||||
|
|
||||||
expect(areRegistered).satisfy(v => v.every(v => v === true));
|
expect(areRegistered).satisfy((v) => v.every((v) => v === true));
|
||||||
expect(balances).satisfy(v => v.every(v => v >= 0n));
|
expect(balances).satisfy((v) => v.every((v) => v >= 0n));
|
||||||
|
|
||||||
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
||||||
areRegistered = await Promise.all(cheatingRelayers.map(r => relayerRegistryContract.isRelayer(r)));
|
areRegistered = await Promise.all(cheatingRelayers.map((r) => relayerRegistryContract.isRelayer(r)));
|
||||||
balances = await Promise.all(cheatingRelayers.map(r => relayerRegistryContract.getRelayerBalance(r)));
|
balances = await Promise.all(cheatingRelayers.map((r) => relayerRegistryContract.getRelayerBalance(r)));
|
||||||
|
|
||||||
expect(areRegistered).satisfy(v => v.every(v => v === false));
|
expect(areRegistered).satisfy((v) => v.every((v) => v === false));
|
||||||
expect(balances).satisfy(v => v.every(v => v === 0n));
|
expect(balances).satisfy((v) => v.every((v) => v === 0n));
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Unregistered relayers can register again", async function(){
|
it("Unregistered relayers can register again", async function () {
|
||||||
const { relayerRegistryContract, governanceSigner } = await loadFixture(deployAndExecuteFixture);
|
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
||||||
const relayerEns = "moon-relayer.eth";
|
const relayerEns = "moon-relayer.eth";
|
||||||
const unregisteredRelayer = await resolveAddr(relayerEns);
|
const unregisteredRelayer = await resolveAddr(relayerEns);
|
||||||
const tornContract = await ethers.getContractAt(require("./abi/torn.abi.json"), "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C", governanceSigner);
|
const toStake = await sendMinimalStakeAmount(unregisteredRelayer);
|
||||||
const toStake = 2000n * 10n ** 18n;
|
|
||||||
await tornContract.transfer(unregisteredRelayer, toStake);
|
|
||||||
|
|
||||||
const relayerSigner = await ethers.getImpersonatedSigner(unregisteredRelayer);
|
const relayerSigner = await ethers.getImpersonatedSigner(unregisteredRelayer);
|
||||||
await relayerRegistryContract.connect(relayerSigner).register(relayerEns, toStake, []);
|
await relayerRegistryContract.connect(relayerSigner).register(relayerEns, toStake, []);
|
||||||
const isRelayerRegistered = await relayerRegistryContract.isRelayerRegistered(unregisteredRelayer, unregisteredRelayer);
|
const isRelayerRegistered = await relayerRegistryContract.isRelayerRegistered(
|
||||||
|
unregisteredRelayer,
|
||||||
|
unregisteredRelayer,
|
||||||
|
);
|
||||||
const relayerBalance = await relayerRegistryContract.getRelayerBalance(unregisteredRelayer);
|
const relayerBalance = await relayerRegistryContract.getRelayerBalance(unregisteredRelayer);
|
||||||
|
|
||||||
expect(isRelayerRegistered).to.be.equal(true);
|
expect(isRelayerRegistered).to.be.equal(true);
|
||||||
expect(relayerBalance).to.be.equal(toStake);
|
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 loadFixture(deployAndExecuteFixture);
|
||||||
|
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 () {
|
||||||
|
const { relayerRegistryProxyAddr } = await loadFixture(deployAndExecuteFixture);
|
||||||
|
const ensWrapperAddr = "0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401";
|
||||||
|
const wrappedEnsDomain = "butterfly-attractor.eth";
|
||||||
|
const addr = await resolveAddr(wrappedEnsDomain);
|
||||||
|
const ensContract = await getEnsRegistryContract();
|
||||||
|
const wrapperContract = await ethers.getContractAt(require("./abi/ensWrapper.abi.json"), ensWrapperAddr);
|
||||||
|
const labelhash = ethers.keccak256(ethers.toUtf8Bytes(wrappedEnsDomain.split(".")[0]));
|
||||||
|
console.log(await ensContract.owner(ethers.namehash(wrappedEnsDomain)));
|
||||||
|
console.log(await ethers.provider.getBlockNumber());
|
||||||
|
await wrapperContract.unwrapETH2LD(labelhash, addr, addr);
|
||||||
|
console.log(await ensContract.owner(ethers.namehash(wrappedEnsDomain)));
|
||||||
|
console.log(await ethers.provider.getBlockNumber());
|
||||||
|
console.log(await network.provider.send("evm_mine"));
|
||||||
|
console.log(await ethers.provider.getBlockNumber());
|
||||||
|
|
||||||
|
const [relayerSigner] = await ethers.getSigners();
|
||||||
|
const relayerRegistry = await ethers.getContractAt(
|
||||||
|
require("./abi/relayerRegistry.abi.json"),
|
||||||
|
relayerRegistryProxyAddr,
|
||||||
|
relayerSigner,
|
||||||
|
);
|
||||||
|
const registerParams = await getRegisterRelayerParams(wrappedEnsDomain);
|
||||||
|
await relayerRegistry.registerPermit(...registerParams);
|
||||||
|
|
||||||
|
expect(await relayerRegistry.isRelayerRegistered(addr, addr)).to.be.equal(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
1
test/abi/ensWrapper.abi.json
Normal file
1
test/abi/ensWrapper.abi.json
Normal file
File diff suppressed because one or more lines are too long
696
test/abi/relayerRegistry.abi.json
Normal file
696
test/abi/relayerRegistry.abi.json
Normal file
@ -0,0 +1,696 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_torn",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_governance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_ens",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_staking",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_feeManager",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "constructor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "minStakeAmount",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "MinimumStakeAmount",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RelayerBalanceNullified",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "ensName",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayerAddress",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "stakedAmount",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RelayerRegistered",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RelayerUnregistered",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "tornadoRouter",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RouterRegistered",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "amountStakeAdded",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "StakeAddedToRelayer",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "amountBurned",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "StakeBurned",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "worker",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "WorkerRegistered",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "worker",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "WorkerUnregistered",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32[]",
|
||||||
|
"name": "domains",
|
||||||
|
"type": "bytes32[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "bulkResolve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "result",
|
||||||
|
"type": "address[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "sender",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "contract ITornadoInstance",
|
||||||
|
"name": "pool",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "burn",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "ens",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract IENS",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "feeManager",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract IFeeManager",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getRelayerBalance",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getRelayerEnsHash",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "governance",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_tornadoRouter",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "initialize",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "toResolve",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "isRelayer",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "toResolve",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "isRelayerRegistered",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "minStakeAmount",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "nullifyBalance",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "ensName",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "stake",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "workersToRegister",
|
||||||
|
"type": "address[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "register",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "ensName",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "stake",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "workersToRegister",
|
||||||
|
"type": "address[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "deadline",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint8",
|
||||||
|
"name": "v",
|
||||||
|
"type": "uint8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "r",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "s",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "registerPermit",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "worker",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "registerWorker",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "relayers",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "balance",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "ensHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "node",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "resolve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "minAmount",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setMinStakeAmount",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "tornadoRouterAddress",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setTornadoRouter",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "stake",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "stakeToRelayer",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "stake",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "staker",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "deadline",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint8",
|
||||||
|
"name": "v",
|
||||||
|
"type": "uint8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "r",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "s",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "stakeToRelayerPermit",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "staking",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract ITornadoStakingRewards",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "torn",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract TORN",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "tornadoRouter",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unregisterRelayer",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "worker",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unregisterWorker",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "workers",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
]
|
169
test/utils.js
Normal file
169
test/utils.js
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
const { ethers, network } = require("hardhat");
|
||||||
|
const { time, loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers");
|
||||||
|
const { keccak256, toUtf8Bytes } = require("ethers");
|
||||||
|
|
||||||
|
const ensAddr = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
|
||||||
|
const relayerRegistryProxyAddr = "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2";
|
||||||
|
const tornAddr = "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C";
|
||||||
|
const governanceAddr = "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce";
|
||||||
|
|
||||||
|
async function getPermitSignature(signer, tokenContract, spender, value, deadline) {
|
||||||
|
const [nonce, name, version, chainId] = await Promise.all([
|
||||||
|
tokenContract.nonces(signer.address),
|
||||||
|
tokenContract.name(),
|
||||||
|
"1",
|
||||||
|
tokenContract.chainID(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const domain = {
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
chainId,
|
||||||
|
verifyingContract: tornAddr,
|
||||||
|
};
|
||||||
|
const types = {
|
||||||
|
Permit: [
|
||||||
|
{
|
||||||
|
name: "owner",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "spender",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "value",
|
||||||
|
type: "uint256",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nonce",
|
||||||
|
type: "uint256",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deadline",
|
||||||
|
type: "uint256",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const values = {
|
||||||
|
owner: signer.address,
|
||||||
|
spender,
|
||||||
|
value,
|
||||||
|
nonce,
|
||||||
|
deadline,
|
||||||
|
};
|
||||||
|
|
||||||
|
const signature = await signer.signTypedData(domain, types, values);
|
||||||
|
return ethers.Signature.from(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRegisterRelayerParams(ensDomain, additionalStake = 0, workerAddrs = []) {
|
||||||
|
const relayerAddr = await resolveAddr(ensDomain);
|
||||||
|
const toStake = await sendMinimalStakeAmount(relayerAddr, BigInt(additionalStake));
|
||||||
|
const tornContract = await ethers.getContractAt(require("./abi/torn.abi.json"), tornAddr);
|
||||||
|
const relayerSigner = await ethers.getSigner(relayerAddr);
|
||||||
|
const { v, r, s } = await getPermitSignature(
|
||||||
|
relayerSigner,
|
||||||
|
tornContract,
|
||||||
|
relayerRegistryProxyAddr,
|
||||||
|
toStake,
|
||||||
|
ethers.MaxUint256,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [ensDomain, toStake, workerAddrs, relayerAddr, ethers.MaxUint256, v, r, s];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getEnsRegistryContract() {
|
||||||
|
return await ethers.getContractAt(require("./abi/ensRegistry.abi.json"), ensAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveAddr(ensName) {
|
||||||
|
const ensNode = ethers.namehash(ensName);
|
||||||
|
const registryContract = await getEnsRegistryContract();
|
||||||
|
const resolverAddr = await registryContract.resolver(ensNode);
|
||||||
|
const resolverContract = await ethers.getContractAt(require("./abi/ensResolver.abi.json"), resolverAddr);
|
||||||
|
|
||||||
|
return await resolverContract.addr(ensNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRelayerRegistryContract(signer) {
|
||||||
|
return await ethers.getContractAt("RelayerRegistry", relayerRegistryProxyAddr, signer);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getOldRelayerRegistryContractFixture() {
|
||||||
|
return await ethers.getContractAt(require("./abi/relayerRegistryOld.abi.json"), relayerRegistryProxyAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getManyEth(addr) {
|
||||||
|
await network.provider.send("hardhat_setBalance", [addr, "0x111166630153555558483537"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendMinimalStakeAmount(addr, additionalStake = 0n) {
|
||||||
|
const { relayerRegistryContract } = await loadFixture(deployAndExecuteFixture);
|
||||||
|
const minRelayerStakeAmount = await relayerRegistryContract.minStakeAmount();
|
||||||
|
const governanceSigner = await ethers.getImpersonatedSigner(governanceAddr);
|
||||||
|
const tornContract = await ethers.getContractAt(require("./abi/torn.abi.json"), tornAddr, governanceSigner);
|
||||||
|
await tornContract.transfer(addr, minRelayerStakeAmount + additionalStake);
|
||||||
|
|
||||||
|
return minRelayerStakeAmount + additionalStake;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deployAndExecuteFixture() {
|
||||||
|
const RelayerRegistryFactory = await ethers.getContractFactory("RelayerRegistry");
|
||||||
|
const constructorArgs = [
|
||||||
|
tornAddr,
|
||||||
|
governanceAddr,
|
||||||
|
ensAddr,
|
||||||
|
"0x5B3f656C80E8ddb9ec01Dd9018815576E9238c29",
|
||||||
|
"0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7",
|
||||||
|
];
|
||||||
|
const relayerRegistry = await RelayerRegistryFactory.deploy(...constructorArgs);
|
||||||
|
const deployedRegistryAddr = await relayerRegistry.getAddress();
|
||||||
|
const proposalFactory = await ethers.getContractFactory("Proposal");
|
||||||
|
const proposal = await proposalFactory.deploy(deployedRegistryAddr);
|
||||||
|
const deployedProposalAddr = await proposal.getAddress();
|
||||||
|
|
||||||
|
const bigStakerAddr = "0xE4143f6377AEcd7193b9731d1C28815b57C4f5Ab";
|
||||||
|
await getManyEth(bigStakerAddr);
|
||||||
|
const stakerSigner = await ethers.getImpersonatedSigner(bigStakerAddr);
|
||||||
|
const governanceContract = await ethers.getContractAt(
|
||||||
|
require("./abi/governance.abi.json"),
|
||||||
|
governanceAddr,
|
||||||
|
stakerSigner,
|
||||||
|
);
|
||||||
|
await governanceContract.propose(deployedProposalAddr, "");
|
||||||
|
const proposalId = await governanceContract.proposalCount();
|
||||||
|
await time.increase(60 * 60);
|
||||||
|
await governanceContract.castVote(proposalId, true);
|
||||||
|
await time.increase(60 * 60 * 24 * 7 + 60);
|
||||||
|
await governanceContract.execute(proposalId);
|
||||||
|
|
||||||
|
const governanceSigner = await ethers.getImpersonatedSigner(governanceAddr);
|
||||||
|
const relayerRegistryContract = await ethers.getContractAt(
|
||||||
|
"RelayerRegistry",
|
||||||
|
relayerRegistryProxyAddr,
|
||||||
|
governanceSigner,
|
||||||
|
);
|
||||||
|
|
||||||
|
return { relayerRegistryProxyAddr, deployedRegistryAddr, relayerRegistryContract, governanceSigner, constructorArgs };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function unregisterRelayer(ensNameOrAddress) {
|
||||||
|
const governanceSigner = await ethers.getImpersonatedSigner(governanceAddr);
|
||||||
|
const relayerRegistryContract = await getRelayerRegistryContract(governanceSigner);
|
||||||
|
const relayerAddr = ethers.isAddress(ensNameOrAddress) ? ensNameOrAddress : resolveAddr(ensNameOrAddress);
|
||||||
|
await relayerRegistryContract.unregisterRelayer(relayerAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
sendMinimalStakeAmount,
|
||||||
|
getEnsRegistryContract,
|
||||||
|
getOldRelayerRegistryContractFixture,
|
||||||
|
getRelayerRegistryContract,
|
||||||
|
getPermitSignature,
|
||||||
|
resolveAddr,
|
||||||
|
getManyEth,
|
||||||
|
unregisterRelayer,
|
||||||
|
deployAndExecuteFixture,
|
||||||
|
getRegisterRelayerParams,
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user