first commit
This commit is contained in:
commit
35bb437ad9
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
node_modules
|
||||
.env
|
||||
|
||||
# Hardhat files
|
||||
/cache
|
||||
/artifacts
|
||||
|
||||
# TypeChain files
|
||||
/typechain
|
||||
/typechain-types
|
||||
|
||||
# solidity-coverage files
|
||||
/coverage
|
||||
/coverage.json
|
7
README.md
Normal file
7
README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Proposal 38
|
||||
|
||||
Compensating for relayers being incorrectly burned torn in oracle attacks.
|
||||
|
||||
Deploy: `npx hardhat run --network mainnet script/deploy.js`
|
||||
Tests: `npx hardhat test`
|
||||
Dont forget to fill env file
|
35
contracts/Proposal.sol
Executable file
35
contracts/Proposal.sol
Executable file
@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
// import { IGovernance } from "@interfaces/IGovernance.sol";
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
contract Proposal {
|
||||
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
|
||||
address public constant me = 0x9b78e16456c8C0A1FE386894c6f1E7F7C0104ADC;
|
||||
|
||||
struct RelayerLoss {
|
||||
address relayer;
|
||||
uint256 lostAmountInTorn;
|
||||
}
|
||||
|
||||
function executeProposal() public {
|
||||
// Data from 'data/relayerLosses.txt', generated by 'scripts/calculateLosses.ts'
|
||||
RelayerLoss[6] memory relayerLosses = [
|
||||
RelayerLoss(0x076D4E32C6A5D888fC4658281539c94E778C796d, 2_380_374_405_606_021_763_001),
|
||||
RelayerLoss(0x28907F21F43B419F34226d6f10aCbCf1832b1D4d, 4_468_422_129_821_830_327_039),
|
||||
RelayerLoss(0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C, 3_040_216_359_787_595_395_455),
|
||||
RelayerLoss(0xb0Cdc0AB2D454F2360d4629d519819E13DBE816A, 103_765_685_766_980_694_091),
|
||||
RelayerLoss(0xb578603D3fB9216158c29488c1A902Dd0300c115, 816_848_044_379_099_935_494),
|
||||
RelayerLoss(0xD8f1Eb586Ecb93745392EE254a028f1F67E1437E, 6_688_475_991_532_709_870_006)
|
||||
];
|
||||
|
||||
for (uint256 i = 0; i < relayerLosses.length; i++) {
|
||||
TORN.transfer(relayerLosses[i].relayer, relayerLosses[i].lostAmountInTorn);
|
||||
}
|
||||
|
||||
// Deployment and execution cost
|
||||
TORN.transfer(me, 50 ether);
|
||||
}
|
||||
}
|
6
data/relayerLosses.txt
Executable file
6
data/relayerLosses.txt
Executable file
@ -0,0 +1,6 @@
|
||||
0x076D4E32C6A5D888fC4658281539c94E778C796d = 2380374405606021763001 // 2380.374405606021763001 TORN
|
||||
0x28907F21F43B419F34226d6f10aCbCf1832b1D4d = 4468422129821830327039 // 4468.422129821830327039 TORN
|
||||
0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C = 3040216359787595395455 // 3040.216359787595395455 TORN
|
||||
0xb0Cdc0AB2D454F2360d4629d519819E13DBE816A = 103765685766980694091 // 103.765685766980694091 TORN
|
||||
0xb578603D3fB9216158c29488c1A902Dd0300c115 = 816848044379099935494 // 816.848044379099935494 TORN
|
||||
0xD8f1Eb586Ecb93745392EE254a028f1F67E1437E = 6688475991532709870006 // 6688.475991532709870006 TORN
|
30
hardhat.config.ts
Normal file
30
hardhat.config.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { HardhatUserConfig } from "hardhat/config";
|
||||
import "@nomicfoundation/hardhat-toolbox";
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
const config: HardhatUserConfig = {
|
||||
solidity: "0.8.19",
|
||||
mocha: {
|
||||
timeout: 100000000,
|
||||
},
|
||||
networks: {
|
||||
mainnet: {
|
||||
url: "https://eth.llamarpc.com",
|
||||
accounts: [process.env.REAL_PK!],
|
||||
},
|
||||
hardhat: {
|
||||
forking: {
|
||||
url: "https://eth.llamarpc.com",
|
||||
enabled: true,
|
||||
},
|
||||
chainId: 1
|
||||
}
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: process.env.ETHERSCAN_KEY,
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
26
package.json
Normal file
26
package.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "proposal-38",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@nomicfoundation/hardhat-chai-matchers": "^2.0.0",
|
||||
"@nomicfoundation/hardhat-ethers": "^3.0.0",
|
||||
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
|
||||
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
|
||||
"@nomicfoundation/hardhat-verify": "^2.0.0",
|
||||
"@openzeppelin/contracts": "4.9.3",
|
||||
"@typechain/ethers-v6": "^0.5.0",
|
||||
"@typechain/hardhat": "^9.0.0",
|
||||
"@types/chai": "^4.2.0",
|
||||
"@types/mocha": ">=9.1.0",
|
||||
"@types/node": ">=16.0.0",
|
||||
"chai": "^4.2.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"ethers": "^6.4.0",
|
||||
"hardhat": "^2.19.1",
|
||||
"hardhat-gas-reporter": "^1.0.8",
|
||||
"solidity-coverage": "^0.8.0",
|
||||
"ts-node": ">=8.0.0",
|
||||
"typechain": "^8.3.0",
|
||||
"typescript": ">=4.5.0"
|
||||
}
|
||||
}
|
719
scripts/abi/RelayerRegistry.abi.json
Normal file
719
scripts/abi/RelayerRegistry.abi.json
Normal file
@ -0,0 +1,719 @@
|
||||
[
|
||||
{
|
||||
"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": "string",
|
||||
"name": "ensName",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "stake",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "registerRelayerAdmin",
|
||||
"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"
|
||||
}
|
||||
]
|
519
scripts/abi/TornadoCash_eth.abi.json
Normal file
519
scripts/abi/TornadoCash_eth.abi.json
Normal file
@ -0,0 +1,519 @@
|
||||
[
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_newOperator",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "changeOperator",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "nullifierHashes",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "_proof",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "_root",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "_nullifierHash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "address payable",
|
||||
"name": "_recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address payable",
|
||||
"name": "_relayer",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_fee",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_refund",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "verifier",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IVerifier",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "_left",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "_right",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "hashLeftRight",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "FIELD_SIZE",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "levels",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "operator",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "_root",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "isKnownRoot",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "commitments",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "denomination",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "currentRootIndex",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_newVerifier",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "updateVerifier",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32[]",
|
||||
"name": "_nullifierHashes",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "isSpentArray",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool[]",
|
||||
"name": "spent",
|
||||
"type": "bool[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "_commitment",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "deposit",
|
||||
"outputs": [],
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getLastRoot",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "roots",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "ROOT_HISTORY_SIZE",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "_nullifierHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "isSpent",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "zeros",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "ZERO_VALUE",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "filledSubtrees",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "nextIndex",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "contract IVerifier",
|
||||
"name": "_verifier",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_denomination",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "_merkleTreeHeight",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_operator",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "bytes32",
|
||||
"name": "commitment",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint32",
|
||||
"name": "leafIndex",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "timestamp",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Deposit",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "bytes32",
|
||||
"name": "nullifierHash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "relayer",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "fee",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Withdrawal",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
100
scripts/calculateLosses.ts
Executable file
100
scripts/calculateLosses.ts
Executable file
@ -0,0 +1,100 @@
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
import relayerAbi from './abi/RelayerRegistry.abi.json';
|
||||
import tornethAbi from './abi/TornadoCash_eth.abi.json';
|
||||
|
||||
const RPC = 'https://eth.llamarpc.com';
|
||||
|
||||
// Affected TORN instance
|
||||
const tornAddrs = [
|
||||
// ETH
|
||||
{
|
||||
// 1
|
||||
addr: '0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936',
|
||||
from: 18577000,
|
||||
to: 18583515,
|
||||
},
|
||||
{
|
||||
// 10
|
||||
addr: '0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF',
|
||||
from: 18577000,
|
||||
to: 18583515,
|
||||
},
|
||||
{
|
||||
// 100
|
||||
addr: '0xA160cdAB225685dA1d56aa342Ad8841c3b53f291',
|
||||
from: 18577000,
|
||||
to: 18583515,
|
||||
},
|
||||
|
||||
// DAI
|
||||
{
|
||||
// 10000
|
||||
addr: '0x07687e702b410Fa43f4cB4Af7FA097918ffD2730',
|
||||
from: 18577000,
|
||||
to: 18591849,
|
||||
},
|
||||
];
|
||||
|
||||
const relayerAddr = '0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2';
|
||||
const relayerFrom = 18577000;
|
||||
const relayerTo = 18591849;
|
||||
|
||||
type BurnInfo = {
|
||||
relayer: string;
|
||||
toBurn: bigint;
|
||||
};
|
||||
|
||||
async function getBurnInfos() {
|
||||
const p = new ethers.JsonRpcProvider(RPC);
|
||||
const cont = new ethers.Contract(relayerAddr, relayerAbi, p);
|
||||
const filter = cont.filters.StakeBurned();
|
||||
|
||||
let ret: { [key: string]: BurnInfo } = {};
|
||||
const events = await cont.queryFilter(filter, relayerFrom, relayerTo);
|
||||
for (const e of events) {
|
||||
// decode StakeBurned data
|
||||
const [ relayer, toBurn ] = ethers.AbiCoder.defaultAbiCoder().decode(
|
||||
['address', 'uint256'],
|
||||
e.data
|
||||
);
|
||||
|
||||
ret[e.transactionHash] = {
|
||||
relayer,
|
||||
toBurn,
|
||||
};
|
||||
}
|
||||
|
||||
await p.destroy();
|
||||
return ret;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const burnInfo = await getBurnInfos();
|
||||
|
||||
let relayerLost: { [key: string]: bigint } = {};
|
||||
await Promise.all(tornAddrs.map(async ({ addr, from, to }) => {
|
||||
const p = new ethers.JsonRpcProvider(RPC);
|
||||
const cont = new ethers.Contract(addr, tornethAbi, p);
|
||||
const filter = cont.filters.Withdrawal();
|
||||
|
||||
const events = await cont.queryFilter(filter, from, to);
|
||||
for (const e of events) {
|
||||
const info = burnInfo[e.transactionHash];
|
||||
if (!info) continue;
|
||||
|
||||
if (!(info.relayer in relayerLost)) {
|
||||
relayerLost[info.relayer] = BigInt(0);
|
||||
}
|
||||
relayerLost[info.relayer] += info.toBurn;
|
||||
}
|
||||
|
||||
await p.destroy();
|
||||
}));
|
||||
|
||||
for (const key in relayerLost) {
|
||||
console.log(`${key} = ${relayerLost[key]} // ${ethers.formatEther(relayerLost[key])} TORN`);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
15
scripts/deploy.ts
Normal file
15
scripts/deploy.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { ethers } from "hardhat";
|
||||
|
||||
async function main() {
|
||||
const proposal = await ethers.deployContract("Proposal", []);
|
||||
await proposal.waitForDeployment();
|
||||
|
||||
console.log(`Proposal deployed to ${proposal.target}`);
|
||||
}
|
||||
|
||||
// We recommend this pattern to be able to use async/await everywhere
|
||||
// and properly handle errors.
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
41
test/Proposal.ts
Normal file
41
test/Proposal.ts
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers";
|
||||
import { ethers } from "hardhat";
|
||||
import { expect } from "chai";
|
||||
import { deployAndExecuteProposal } from "./utils";
|
||||
|
||||
const tornAddr = "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C";
|
||||
const myAddr = "0x9b78e16456c8C0A1FE386894c6f1E7F7C0104ADC";
|
||||
|
||||
describe("Proposal", function () {
|
||||
describe("Deployment", async function () {
|
||||
it("Relayer Got Compensation", async function () {
|
||||
const TORN = await ethers.getContractAt("IERC20", tornAddr);
|
||||
|
||||
// Data from 'data/relayerLosses.txt', generated by 'scripts/calculateLosses.ts'
|
||||
const relayerLosses: { [key: string]: bigint } = {
|
||||
'0x076D4E32C6A5D888fC4658281539c94E778C796d': BigInt('2380374405606021763001'), // 2380.374405606021763001 TORN
|
||||
'0x28907F21F43B419F34226d6f10aCbCf1832b1D4d': BigInt('4468422129821830327039'), // 4468.422129821830327039 TORN
|
||||
'0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C': BigInt('3040216359787595395455'), // 3040.216359787595395455 TORN
|
||||
'0xb0Cdc0AB2D454F2360d4629d519819E13DBE816A': BigInt('103765685766980694091'), // 103.765685766980694091 TORN
|
||||
'0xb578603D3fB9216158c29488c1A902Dd0300c115': BigInt('816848044379099935494'), // 816.848044379099935494 TORN
|
||||
'0xD8f1Eb586Ecb93745392EE254a028f1F67E1437E': BigInt('6688475991532709870006') // 6688.475991532709870006 TORN
|
||||
}
|
||||
|
||||
let relayerBalance: { [key: string]: bigint } = {};
|
||||
for (const addr in relayerLosses) {
|
||||
relayerBalance[addr] = await TORN.balanceOf(addr);
|
||||
}
|
||||
const myBalance = await TORN.balanceOf(myAddr);
|
||||
|
||||
await loadFixture(deployAndExecuteProposal);
|
||||
|
||||
for (const addr in relayerBalance) {
|
||||
const balance = await TORN.balanceOf(addr);
|
||||
expect(balance).to.equal(relayerBalance[addr] + relayerLosses[addr]);
|
||||
}
|
||||
|
||||
expect(await TORN.balanceOf(myAddr)).to.equal(myBalance + BigInt(5e19));
|
||||
});
|
||||
});
|
||||
})
|
1003
test/abi/governance.abi.json
Normal file
1003
test/abi/governance.abi.json
Normal file
File diff suppressed because it is too large
Load Diff
33
test/utils.ts
Normal file
33
test/utils.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { ethers, network } from "hardhat";
|
||||
import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers";
|
||||
import governanceAbi from "./abi/governance.abi.json";
|
||||
|
||||
const governanceAddr = "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce";
|
||||
|
||||
async function getManyEth(addr: string) {
|
||||
await network.provider.send("hardhat_setBalance", [addr, "0x111166630153555558483537"]);
|
||||
}
|
||||
|
||||
async function deployAndExecuteProposal() {
|
||||
const proposal = await ethers.deployContract("Proposal", []);
|
||||
await proposal.waitForDeployment();
|
||||
|
||||
const bigStakerAddr = "0xE4143f6377AEcd7193b9731d1C28815b57C4f5Ab";
|
||||
await getManyEth(bigStakerAddr);
|
||||
const stakerSigner = await ethers.getImpersonatedSigner(bigStakerAddr);
|
||||
const governanceContract = await ethers.getContractAt(
|
||||
governanceAbi,
|
||||
governanceAddr,
|
||||
stakerSigner,
|
||||
);
|
||||
await governanceContract.propose(proposal.target, "");
|
||||
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);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
deployAndExecuteProposal,
|
||||
};
|
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user