v1/v2 tests
This commit is contained in:
parent
74b6021aa7
commit
74f38d68b0
|
@ -1,6 +1,111 @@
|
||||||
node_modules
|
# Logs
|
||||||
cache
|
logs
|
||||||
artifacts
|
*.log
|
||||||
build
|
npm-debug.log*
|
||||||
dist
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
.env
|
.env
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
artifacts
|
||||||
|
cache
|
||||||
|
coverage
|
||||||
|
coverage.json
|
||||||
|
|
||||||
|
.vscode
|
|
@ -1,10 +1,9 @@
|
||||||
# tornado-governance
|
# Tornado governance
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
This repository holds all the tornado.cash governance upgrade and original governance contracts.
|
This repository holds all the tornado.cash governance upgrades and original governance contracts.
|
||||||
The highest governance version right now is version 2, which includes a gas and vault upgrade.
|
|
||||||
|
|
||||||
## Setup
|
## Tests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/tornadocash/tornado-governance.git
|
git clone https://github.com/tornadocash/tornado-governance.git
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Tornado Governance Changes
|
# Tornado Governance Changes
|
||||||
|
|
||||||
Governance proposal [repo]().
|
Governance proposal [repo](https://github.com/Tisamenus/tornado-lottery-period).
|
||||||
|
|
||||||
## Governance Vault Upgrade (GovernanceVaultUpgrade.sol)
|
## Governance Vault Upgrade (GovernanceVaultUpgrade.sol)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pragma solidity ^0.6.12;
|
||||||
|
|
||||||
|
import "../../v1/Governance.sol";
|
||||||
|
|
||||||
|
contract MockProposal {
|
||||||
|
address public constant GovernanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
||||||
|
|
||||||
|
function executeProposal() external {
|
||||||
|
Governance gov = Governance(GovernanceAddress);
|
||||||
|
|
||||||
|
gov.setVotingPeriod(27000);
|
||||||
|
require(gov.VOTING_PERIOD() == 27000, "Voting period change failed!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ require('hardhat-storage-layout')
|
||||||
require('hardhat-log-remover')
|
require('hardhat-log-remover')
|
||||||
require('hardhat-contract-sizer')
|
require('hardhat-contract-sizer')
|
||||||
|
|
||||||
require('./tasks/deploy_proposal.js')
|
|
||||||
/**
|
/**
|
||||||
* @type import('hardhat/config').HardhatUserConfig
|
* @type import('hardhat/config').HardhatUserConfig
|
||||||
*/
|
*/
|
||||||
|
@ -29,7 +28,7 @@ module.exports = {
|
||||||
hardhat: {
|
hardhat: {
|
||||||
forking: {
|
forking: {
|
||||||
url: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
|
url: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
|
||||||
blockNumber: 13042331,
|
blockNumber: 14042331,
|
||||||
},
|
},
|
||||||
initialBaseFeePerGas: 5,
|
initialBaseFeePerGas: 5,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "tornado-governance",
|
"name": "tornado-governance",
|
||||||
"version": "2.0.0",
|
"version": "3.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"files": [
|
"files": [
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
require('dotenv').config()
|
|
||||||
const { task } = require('hardhat/config')
|
|
||||||
const { BigNumber } = require('@ethersproject/bignumber')
|
|
||||||
|
|
||||||
task('deploy_proposal', 'deploy the lottery/vault upgrade proposal')
|
|
||||||
.addParam('votingPeriod', 'the desired new voting period')
|
|
||||||
.setAction(async (taskArgs, hre) => {
|
|
||||||
const GasVaultFactory = await hre.ethers.getContractFactory(
|
|
||||||
'contracts/basefee/GasCompensationVault.sol:GasCompensationVault',
|
|
||||||
)
|
|
||||||
const GasVaultContract = await GasVaultFactory.deploy()
|
|
||||||
|
|
||||||
await GasVaultContract.deployTransaction.wait(5)
|
|
||||||
|
|
||||||
await hre.run('verify:verify', {
|
|
||||||
address: GasVaultContract.address,
|
|
||||||
})
|
|
||||||
|
|
||||||
const ProposalFactory = await hre.ethers.getContractFactory('VaultAndGasProposal')
|
|
||||||
const ProposalContract = await ProposalFactory.deploy(
|
|
||||||
GasVaultContract.address,
|
|
||||||
BigNumber.from(taskArgs.votingPeriod),
|
|
||||||
)
|
|
||||||
|
|
||||||
await ProposalContract.deployTransaction.wait(5)
|
|
||||||
|
|
||||||
await hre.run('verify:verify', {
|
|
||||||
address: ProposalContract.address,
|
|
||||||
constructorArguments: [GasVaultContract.address, BigNumber.from(taskArgs.votingPeriod)],
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log('Successfully deployed proposal contract at: ', ProposalContract.address)
|
|
||||||
})
|
|
|
@ -1,20 +0,0 @@
|
||||||
require('dotenv').config()
|
|
||||||
const { task } = require('hardhat/config')
|
|
||||||
|
|
||||||
task('propose_proposal', 'propose proposal that uses factory')
|
|
||||||
.addParam('proposalAddress', 'address of proposal')
|
|
||||||
.setAction(async (taskArgs, hre) => {
|
|
||||||
const proposalName = 'lottery-and-vault-proposal'
|
|
||||||
const signerArray = hre.ethers.getSigners()
|
|
||||||
|
|
||||||
const GovernanceContract = await hre.ethers.getContractAt(
|
|
||||||
'Governance',
|
|
||||||
'0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce',
|
|
||||||
)
|
|
||||||
await GovernanceContract.propose(taskArgs.proposalAddress, proposalName)
|
|
||||||
|
|
||||||
const id = await GovernanceContract.latestProposalIds(signerArray[0].address)
|
|
||||||
const state = await GovernanceContract.state(id)
|
|
||||||
|
|
||||||
console.log('Proposal with name: ', proposalName, ' proposed with id: ', id, ', has state: ', state)
|
|
||||||
})
|
|
|
@ -1,93 +0,0 @@
|
||||||
{
|
|
||||||
"mainnet": {
|
|
||||||
"tornado_cash_addresses": {
|
|
||||||
"governance": "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce",
|
|
||||||
"multisig": "0xb04E030140b30C27bcdfaafFFA98C57d80eDa7B4",
|
|
||||||
"trees": "0x527653eA119F3E6a1F5BD18fbF4714081D7B31ce",
|
|
||||||
"tornado_proxy": "0x722122dF12D4e14e13Ac3b6895a86e84145b6967"
|
|
||||||
},
|
|
||||||
"token_addresses": {
|
|
||||||
"torn": "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C",
|
|
||||||
"weth": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
||||||
"dai": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
||||||
"usdc": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
||||||
"eth": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
||||||
"cdai": "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643",
|
|
||||||
"usdt": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
||||||
"wbtc": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
||||||
},
|
|
||||||
"project_specific": {
|
|
||||||
"contract_construction": {
|
|
||||||
"RelayerRegistryData": {
|
|
||||||
"tornado_pools": [
|
|
||||||
"0x12d66f87a04a9e220743712ce6d9bb1b5616b8fc",
|
|
||||||
"0x47ce0c6ed5b0ce3d3a51fdb1c52dc66a7c3c2936",
|
|
||||||
"0x910cbd523d972eb0a6f4cae4618ad62622b39dbf",
|
|
||||||
"0xa160cdab225685da1d56aa342ad8841c3b53f291",
|
|
||||||
"0xd4b88df4d29f5cedd6857912842cff3b20c8cfa3",
|
|
||||||
"0xfd8610d20aa15b7b2e3be39b396a1bc3516c7144",
|
|
||||||
"0x07687e702b410fa43f4cb4af7fa097918ffd2730",
|
|
||||||
"0x23773e65ed146a459791799d01336db287f25334",
|
|
||||||
"0x22aaA7720ddd5388A3c0A3333430953C68f1849b",
|
|
||||||
"0x03893a7c7463AE47D46bc7f091665f1893656003",
|
|
||||||
"0x2717c5e28cf931547B621a5dddb772Ab6A35B701",
|
|
||||||
"0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af",
|
|
||||||
"0xd96f2B1c14Db8458374d9Aca76E26c3D18364307",
|
|
||||||
"0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D",
|
|
||||||
"0x169AD27A470D064DEDE56a2D3ff727986b15D52B",
|
|
||||||
"0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f",
|
|
||||||
"0x178169B423a011fff22B9e3F3abeA13414dDD0F1",
|
|
||||||
"0x610B717796ad172B316836AC95a2ffad065CeaB4",
|
|
||||||
"0xbB93e510BbCD0B7beb5A853875f9eC60275CF498"
|
|
||||||
],
|
|
||||||
"uniswap_pool_fees": [
|
|
||||||
3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 500, 500, 500, 500, 500,
|
|
||||||
500, 500
|
|
||||||
],
|
|
||||||
"pool_tokens": [
|
|
||||||
"eth",
|
|
||||||
"eth",
|
|
||||||
"eth",
|
|
||||||
"eth",
|
|
||||||
"dai",
|
|
||||||
"dai",
|
|
||||||
"dai",
|
|
||||||
"dai",
|
|
||||||
"cdai",
|
|
||||||
"cdai",
|
|
||||||
"cdai",
|
|
||||||
"cdai",
|
|
||||||
"usdc",
|
|
||||||
"usdc",
|
|
||||||
"usdt",
|
|
||||||
"usdt",
|
|
||||||
"wbtc",
|
|
||||||
"wbtc",
|
|
||||||
"wbtc"
|
|
||||||
],
|
|
||||||
"pool_denominations": [
|
|
||||||
"0.1",
|
|
||||||
"1",
|
|
||||||
"10",
|
|
||||||
"100",
|
|
||||||
"100",
|
|
||||||
"1000",
|
|
||||||
"10000",
|
|
||||||
"100000",
|
|
||||||
"5000",
|
|
||||||
"50000",
|
|
||||||
"500000",
|
|
||||||
"5000000",
|
|
||||||
"100",
|
|
||||||
"1000",
|
|
||||||
"100",
|
|
||||||
"1000",
|
|
||||||
"0.1",
|
|
||||||
"1",
|
|
||||||
"10"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -934,7 +934,7 @@ describe('Governance tests', () => {
|
||||||
{
|
{
|
||||||
forking: {
|
forking: {
|
||||||
jsonRpcUrl: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
|
jsonRpcUrl: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
|
||||||
blockNumber: process.env.use_latest_block == 'true' ? undefined : 13042331,
|
blockNumber: process.env.use_latest_block == 'true' ? undefined : 14042331,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
|
@ -1,743 +0,0 @@
|
||||||
const { expect } = require('chai')
|
|
||||||
const { ethers } = require('hardhat')
|
|
||||||
const { BigNumber } = require('@ethersproject/bignumber')
|
|
||||||
const { propose } = require('../../scripts/helper/propose_proposal.js')
|
|
||||||
const testcases = require('@ethersproject/testcases')
|
|
||||||
const seedbase = require('../../resources/hdnode.json')
|
|
||||||
const accountList = require('../../resources/accounts.json')
|
|
||||||
const EasyAuctionJson = require('@gnosis.pm/ido-contracts/build/artifacts/contracts/EasyAuction.sol/EasyAuction.json')
|
|
||||||
|
|
||||||
describe('Start of tests', () => {
|
|
||||||
///// ON-CHAIN CONSTANTS
|
|
||||||
let proxy_address = '0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce'
|
|
||||||
let quorumVotes
|
|
||||||
|
|
||||||
///////////////////////////// CONTRACTS
|
|
||||||
let GovernanceContract
|
|
||||||
let TornToken
|
|
||||||
let WETH
|
|
||||||
let TornadoAuctionHandler
|
|
||||||
let GnosisEasyAuction
|
|
||||||
|
|
||||||
let ProposalFactory
|
|
||||||
let ProposalContract
|
|
||||||
|
|
||||||
let GasCompensationFactory
|
|
||||||
let GasCompensationContract
|
|
||||||
|
|
||||||
let OrderHelperFactory
|
|
||||||
let OrderHelper
|
|
||||||
|
|
||||||
//////////////////// IMPERSONATED
|
|
||||||
let tornadoMultisig
|
|
||||||
|
|
||||||
//////////////////////////////// MOCK
|
|
||||||
let MockProposalFactory
|
|
||||||
|
|
||||||
/////// GOV PARAMS
|
|
||||||
const ProposalState = {
|
|
||||||
Pending: 0,
|
|
||||||
Active: 1,
|
|
||||||
Defeated: 2,
|
|
||||||
Timelocked: 3,
|
|
||||||
AwaitingExecution: 4,
|
|
||||||
Executed: 5,
|
|
||||||
Expired: 6,
|
|
||||||
}
|
|
||||||
|
|
||||||
///// ACCOUNTS
|
|
||||||
let dore
|
|
||||||
let whale
|
|
||||||
let signerArray = []
|
|
||||||
let whales = []
|
|
||||||
|
|
||||||
//////////////////////////////////// TESTING & UTILITY
|
|
||||||
let randN = Math.floor(Math.random() * 1023)
|
|
||||||
let testseed = seedbase[randN].seed
|
|
||||||
|
|
||||||
let minewait = async (time) => {
|
|
||||||
await ethers.provider.send('evm_increaseTime', [time])
|
|
||||||
await ethers.provider.send('evm_mine', [])
|
|
||||||
}
|
|
||||||
|
|
||||||
let timestamp = async () => {
|
|
||||||
return (await ethers.provider.getBlock('latest')).timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
let sendr = async (method, params) => {
|
|
||||||
return await ethers.provider.send(method, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
let clog = (...x) => {
|
|
||||||
console.log(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
let pE = (x) => {
|
|
||||||
return ethers.utils.parseEther(`${x}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
let rand = (l, u) => {
|
|
||||||
return testcases.randomNumber(testseed, l, u)
|
|
||||||
}
|
|
||||||
|
|
||||||
let snapshotIdArray = []
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////7
|
|
||||||
before(async function () {
|
|
||||||
signerArray = await ethers.getSigners()
|
|
||||||
dore = signerArray[0]
|
|
||||||
|
|
||||||
GasCompensationFactory = await ethers.getContractFactory(
|
|
||||||
'contracts/v2-vault-and-gas/testing/GasCompensationVault.sol:GasCompensationVault',
|
|
||||||
)
|
|
||||||
GasCompensationContract = await GasCompensationFactory.deploy()
|
|
||||||
|
|
||||||
MockProposalFactory = await ethers.getContractFactory('MockProposal1')
|
|
||||||
|
|
||||||
ProposalFactory = await ethers.getContractFactory('VaultAndGasProposal')
|
|
||||||
|
|
||||||
ProposalContract = await ProposalFactory.deploy(GasCompensationContract.address, 260000)
|
|
||||||
|
|
||||||
OrderHelperFactory = await ethers.getContractFactory('OrderEncoderHelper')
|
|
||||||
OrderHelper = await OrderHelperFactory.deploy()
|
|
||||||
|
|
||||||
GovernanceContract = await ethers.getContractAt('contracts/v1/Governance.sol:Governance', proxy_address)
|
|
||||||
GnosisEasyAuction = await ethers.getContractAt(
|
|
||||||
EasyAuctionJson.abi,
|
|
||||||
'0x0b7fFc1f4AD541A4Ed16b40D8c37f0929158D101',
|
|
||||||
)
|
|
||||||
|
|
||||||
TornToken = await ethers.getContractAt(
|
|
||||||
'@openzeppelin/contracts/token/ERC20/IERC20.sol:IERC20',
|
|
||||||
'0x77777FeDdddFfC19Ff86DB637967013e6C6A116C',
|
|
||||||
)
|
|
||||||
WETH = await ethers.getContractAt('IWETH', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')
|
|
||||||
|
|
||||||
quorumVotes = await GovernanceContract.QUORUM_VOTES()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Test complete functionality', () => {
|
|
||||||
describe('Imitation block', () => {
|
|
||||||
it('Should successfully imitate tornado multisig', async function () {
|
|
||||||
await sendr('hardhat_impersonateAccount', ['0xb04E030140b30C27bcdfaafFFA98C57d80eDa7B4'])
|
|
||||||
tornadoMultisig = await ethers.getSigner('0xb04E030140b30C27bcdfaafFFA98C57d80eDa7B4')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should successfully imitate whale', async function () {
|
|
||||||
await sendr('hardhat_impersonateAccount', ['0xA2b2fBCaC668d86265C45f62dA80aAf3Fd1dEde3'])
|
|
||||||
whale = await ethers.getSigner('0xA2b2fBCaC668d86265C45f62dA80aAf3Fd1dEde3')
|
|
||||||
GovernanceContract = await GovernanceContract.connect(whale)
|
|
||||||
|
|
||||||
let balance = await TornToken.balanceOf(whale.address)
|
|
||||||
TornToken = await TornToken.connect(whale)
|
|
||||||
|
|
||||||
await TornToken.approve(GovernanceContract.address, ethers.utils.parseEther('8000000000'))
|
|
||||||
await expect(GovernanceContract.lockWithApproval(balance)).to.not.be.reverted
|
|
||||||
|
|
||||||
expect((await GovernanceContract.lockedBalance(whale.address)).toString()).to.equal(
|
|
||||||
balance.toString(),
|
|
||||||
)
|
|
||||||
snapshotIdArray[0] = await sendr('evm_snapshot', [])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Proposal passing block', () => {
|
|
||||||
it('Should successfully pass the proposal', async function () {
|
|
||||||
let response, id, state
|
|
||||||
;[response, id, state] = await propose([whale, ProposalContract, 'Gas Upgrade'])
|
|
||||||
|
|
||||||
const { events } = await response.wait()
|
|
||||||
const args = events.find(({ event }) => event == 'ProposalCreated').args
|
|
||||||
expect(args.id).to.be.equal(id)
|
|
||||||
expect(args.proposer).to.be.equal(whale.address)
|
|
||||||
expect(args.target).to.be.equal(ProposalContract.address)
|
|
||||||
expect(args.description).to.be.equal('Gas Upgrade')
|
|
||||||
expect(state).to.be.equal(ProposalState.Pending)
|
|
||||||
|
|
||||||
await minewait((await GovernanceContract.VOTING_DELAY()).add(1).toNumber())
|
|
||||||
await expect(GovernanceContract.castVote(id, true)).to.not.be.reverted
|
|
||||||
state = await GovernanceContract.state(id)
|
|
||||||
expect(state).to.be.equal(ProposalState.Active)
|
|
||||||
await minewait(
|
|
||||||
(
|
|
||||||
await GovernanceContract.VOTING_PERIOD()
|
|
||||||
)
|
|
||||||
.add(await GovernanceContract.EXECUTION_DELAY())
|
|
||||||
.add(86400)
|
|
||||||
.toNumber(),
|
|
||||||
)
|
|
||||||
|
|
||||||
await dore.sendTransaction({ to: whale.address, value: pE(10) })
|
|
||||||
const executeResponse = await GovernanceContract.execute(id)
|
|
||||||
const executeReceipt = await executeResponse.wait()
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
'______________________\n',
|
|
||||||
'Gas used for execution: ',
|
|
||||||
executeReceipt.cumulativeGasUsed.toString(),
|
|
||||||
'\n-------------------------\n',
|
|
||||||
)
|
|
||||||
const topic = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
|
|
||||||
let handlerAddress
|
|
||||||
|
|
||||||
for (let i = 0; i < executeReceipt.logs.length; i++) {
|
|
||||||
if (executeReceipt.logs[i].topics[0] == topic) {
|
|
||||||
handlerAddress = executeReceipt.logs[i].topics[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TornadoAuctionHandler = await ethers.getContractAt(
|
|
||||||
'TornadoAuctionHandler',
|
|
||||||
'0x' + handlerAddress.slice(26),
|
|
||||||
)
|
|
||||||
GovernanceContract = await ethers.getContractAt('GovernanceGasUpgrade', GovernanceContract.address)
|
|
||||||
|
|
||||||
clog(await GovernanceContract.version())
|
|
||||||
const auctionCounter = 38
|
|
||||||
const auctionData = await GnosisEasyAuction.auctionData(auctionCounter)
|
|
||||||
expect(auctionData.auctioningToken).to.equal(TornToken.address)
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
'////////////////AUCTION/////////////////\n',
|
|
||||||
'Started at: ',
|
|
||||||
await timestamp(),
|
|
||||||
', Will end at: ',
|
|
||||||
auctionData.auctionEndDate.toString(),
|
|
||||||
'\n////////////////////////////////',
|
|
||||||
)
|
|
||||||
|
|
||||||
snapshotIdArray[1] = await sendr('evm_snapshot', [])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Mock rewards + proposal distribution with multiple accounts', () => {
|
|
||||||
let addrArray = []
|
|
||||||
let signerArmy = []
|
|
||||||
let delegatedSignerArmy = []
|
|
||||||
let votingAddressArray = []
|
|
||||||
const numberOfVoters = 80
|
|
||||||
const numberOfDelegators = 30
|
|
||||||
|
|
||||||
it('Should create empty address array', () => {
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
votingAddressArray[i] = new Array(numberOfDelegators / 10 + 1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should impersonate and fund 80 accounts', async function () {
|
|
||||||
////////// WRITE WHALE ADDRESSES AND PREPARE FOR TRANSFERS
|
|
||||||
addrArray = [
|
|
||||||
'0x6cC5F688a315f3dC28A7781717a9A798a59fDA7b',
|
|
||||||
'0xF977814e90dA44bFA03b6295A0616a897441aceC',
|
|
||||||
'0xA2b2fBCaC668d86265C45f62dA80aAf3Fd1dEde3',
|
|
||||||
'0x055AD5E56c11c0eF55818155c69ed9BA2f4b3e90',
|
|
||||||
]
|
|
||||||
|
|
||||||
for (let i = 0; i < 4; i++) {
|
|
||||||
await sendr('hardhat_impersonateAccount', [addrArray[i]])
|
|
||||||
whales[i] = await ethers.getSigner(addrArray[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 1; i < 4; i++) {
|
|
||||||
//last test really unnecessary
|
|
||||||
const torn = await TornToken.connect(whales[i])
|
|
||||||
const whaleBalance = await torn.balanceOf(whales[i].address)
|
|
||||||
await torn.approve(addrArray[0], whaleBalance)
|
|
||||||
await expect(() => torn.transfer(addrArray[0], whaleBalance)).to.changeTokenBalance(
|
|
||||||
torn,
|
|
||||||
whales[0],
|
|
||||||
whaleBalance,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const whale0Balance = await TornToken.balanceOf(whales[0].address)
|
|
||||||
const toTransfer = whale0Balance.sub(pE(10000)).div(numberOfVoters * 3)
|
|
||||||
let torn0 = await TornToken.connect(whales[0])
|
|
||||||
const oldBalance = await TornToken.balanceOf(await GovernanceContract.userVault())
|
|
||||||
let lockedSum = BigNumber.from(0)
|
|
||||||
|
|
||||||
////////// TRANSFER TO 50 ACCOUNTS + DELEGATION TO 10
|
|
||||||
|
|
||||||
for (let i = 0; i < numberOfVoters; i++) {
|
|
||||||
/// PREPARE ACCOUNTS
|
|
||||||
const accAddress = accountList[i + 7].checksumAddress
|
|
||||||
await sendr('hardhat_impersonateAccount', [accAddress])
|
|
||||||
|
|
||||||
signerArmy[i] = await ethers.getSigner(accAddress)
|
|
||||||
const tx = { to: signerArmy[i].address, value: pE(1) }
|
|
||||||
|
|
||||||
await signerArray[0].sendTransaction(tx)
|
|
||||||
|
|
||||||
/// FILL WITH GAS FOR LATER
|
|
||||||
await expect(() => torn0.transfer(signerArmy[i].address, toTransfer)).to.changeTokenBalance(
|
|
||||||
torn0,
|
|
||||||
signerArmy[i],
|
|
||||||
toTransfer,
|
|
||||||
)
|
|
||||||
let torn = await torn0.connect(signerArmy[i])
|
|
||||||
|
|
||||||
/// APPROVE TO GOVERNANCE FOR LOCK
|
|
||||||
await expect(torn.approve(GovernanceContract.address, toTransfer)).to.not.be.reverted
|
|
||||||
const gov = await GovernanceContract.connect(signerArmy[i])
|
|
||||||
|
|
||||||
///// LOCK
|
|
||||||
if (i > numberOfVoters / 2) {
|
|
||||||
await expect(() => gov.lockWithApproval(toTransfer.div(i))).to.changeTokenBalance(
|
|
||||||
torn,
|
|
||||||
signerArmy[i],
|
|
||||||
BigNumber.from(0).sub(toTransfer.div(i)),
|
|
||||||
)
|
|
||||||
lockedSum = lockedSum.add(toTransfer.div(i))
|
|
||||||
} else {
|
|
||||||
await expect(() => gov.lockWithApproval(toTransfer)).to.changeTokenBalance(
|
|
||||||
torn,
|
|
||||||
signerArmy[i],
|
|
||||||
BigNumber.from(0).sub(toTransfer),
|
|
||||||
)
|
|
||||||
lockedSum = lockedSum.add(toTransfer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > numberOfVoters - numberOfDelegators - 1) {
|
|
||||||
delegatedSignerArmy[i - (numberOfVoters - numberOfDelegators)] = signerArmy[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < 10) {
|
|
||||||
votingAddressArray[i][0] = signerArmy[i].address
|
|
||||||
}
|
|
||||||
|
|
||||||
const restBalance = await torn.balanceOf(signerArmy[i].address)
|
|
||||||
await torn.transfer(whale.address, restBalance)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < numberOfDelegators; i++) {
|
|
||||||
const gov = await GovernanceContract.connect(delegatedSignerArmy[i])
|
|
||||||
/// DELEGATE TO 10 FIRST SIGNERS
|
|
||||||
await expect(gov.delegate(signerArmy[i % 10].address)).to.emit(gov, 'Delegated')
|
|
||||||
votingAddressArray[i % 10][Math.floor(i / 10) + 1] = delegatedSignerArmy[i].address
|
|
||||||
}
|
|
||||||
|
|
||||||
const TornVault = await GovernanceContract.userVault()
|
|
||||||
expect(await TornToken.balanceOf(TornVault)).to.equal(lockedSum.add(oldBalance))
|
|
||||||
|
|
||||||
const gov = await GovernanceContract.connect(whales[0])
|
|
||||||
await expect(torn0.approve(GovernanceContract.address, pE(10000))).to.not.be.reverted
|
|
||||||
await expect(() => gov.lockWithApproval(toTransfer)).to.changeTokenBalance(
|
|
||||||
torn0,
|
|
||||||
whales[0],
|
|
||||||
BigNumber.from(0).sub(toTransfer),
|
|
||||||
)
|
|
||||||
|
|
||||||
snapshotIdArray[2] = await sendr('evm_snapshot', [])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should test if auction handler can convert ETH to gov', async function () {
|
|
||||||
WETH = await WETH.connect(signerArray[4])
|
|
||||||
await WETH.deposit({ value: pE(100) })
|
|
||||||
await WETH.transfer(TornadoAuctionHandler.address, pE(100))
|
|
||||||
await expect(() => TornadoAuctionHandler.convertAndTransferToGovernance()).to.changeEtherBalance(
|
|
||||||
GovernanceContract,
|
|
||||||
pE(100),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should test if auction will behave properly', async function () {
|
|
||||||
snapshotIdArray[2] = await sendr('evm_snapshot', [])
|
|
||||||
|
|
||||||
let orderArray = []
|
|
||||||
const initialHandlerBalance = await WETH.balanceOf(TornadoAuctionHandler.address)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 100 TORN in to total
|
|
||||||
* Price as of time of writing 1 ETH == 51.66 TORN
|
|
||||||
* First test is an overbought auction, 20 buyers compete for 40 TORN
|
|
||||||
*/
|
|
||||||
for (let i = 0; i < signerArray.length; i++) {
|
|
||||||
const bidder = signerArray[i]
|
|
||||||
|
|
||||||
WETH = await WETH.connect(bidder)
|
|
||||||
await expect(() => WETH.deposit({ value: pE(100) })).to.changeEtherBalance(
|
|
||||||
bidder,
|
|
||||||
BigNumber.from(0).sub(pE(100)),
|
|
||||||
)
|
|
||||||
|
|
||||||
const buyAmount = pE(240)
|
|
||||||
const sellAmount = pE(23.73 + i / 100)
|
|
||||||
|
|
||||||
await WETH.approve(GnosisEasyAuction.address, sellAmount)
|
|
||||||
|
|
||||||
GnosisEasyAuction = await GnosisEasyAuction.connect(bidder)
|
|
||||||
|
|
||||||
await GnosisEasyAuction.placeSellOrders(
|
|
||||||
38,
|
|
||||||
[buyAmount],
|
|
||||||
[sellAmount],
|
|
||||||
['0x0000000000000000000000000000000000000000000000000000000000000001'],
|
|
||||||
'0x',
|
|
||||||
)
|
|
||||||
|
|
||||||
orderArray[i] = await OrderHelper.encodeOrder(
|
|
||||||
await GnosisEasyAuction.numUsers(),
|
|
||||||
buyAmount,
|
|
||||||
sellAmount,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let auctionEndDt = (await GnosisEasyAuction.auctionData(38))[3].sub(BigNumber.from(await timestamp()))
|
|
||||||
|
|
||||||
await minewait(auctionEndDt.toNumber())
|
|
||||||
|
|
||||||
await GnosisEasyAuction.settleAuction(38)
|
|
||||||
|
|
||||||
expect(await WETH.balanceOf(TornadoAuctionHandler.address)).to.be.gt(initialHandlerBalance)
|
|
||||||
|
|
||||||
for (let i = 0; i < signerArray.length; i++) {
|
|
||||||
await GnosisEasyAuction.claimFromParticipantOrder(38, [orderArray[i]])
|
|
||||||
const balance = await TornToken.balanceOf(signerArray[i].address)
|
|
||||||
if (balance.toString() != '0') console.log(`Signer ${i} claimed:`, balance.toString(), ' torn')
|
|
||||||
}
|
|
||||||
console.log('All other signers got nothing!')
|
|
||||||
|
|
||||||
let claimedSum = BigNumber.from(0)
|
|
||||||
|
|
||||||
for (let i = 0; i < signerArray.length; i++) {
|
|
||||||
const claimed = await TornToken.balanceOf(signerArray[i].address)
|
|
||||||
claimedSum = claimedSum.add(claimed)
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(claimedSum).to.closeTo(ethers.utils.parseEther('787'), ethers.utils.parseUnits('1', 'szabo'))
|
|
||||||
|
|
||||||
/// Now revert and test with lower
|
|
||||||
await sendr('evm_revert', [snapshotIdArray[2]])
|
|
||||||
snapshotIdArray[2] = await sendr('evm_snapshot', [])
|
|
||||||
|
|
||||||
for (let i = 0; i < signerArray.length; i++) {
|
|
||||||
const bidder = signerArray[i]
|
|
||||||
|
|
||||||
WETH = await WETH.connect(bidder)
|
|
||||||
await expect(() => WETH.deposit({ value: pE(100) })).to.changeEtherBalance(
|
|
||||||
bidder,
|
|
||||||
BigNumber.from(0).sub(pE(100)),
|
|
||||||
)
|
|
||||||
|
|
||||||
const buyAmount = pE(0.5)
|
|
||||||
const sellAmount = pE(22 + i / 100)
|
|
||||||
|
|
||||||
await WETH.approve(GnosisEasyAuction.address, sellAmount)
|
|
||||||
|
|
||||||
GnosisEasyAuction = await GnosisEasyAuction.connect(bidder)
|
|
||||||
|
|
||||||
await GnosisEasyAuction.placeSellOrders(
|
|
||||||
38,
|
|
||||||
[buyAmount],
|
|
||||||
[sellAmount],
|
|
||||||
['0x0000000000000000000000000000000000000000000000000000000000000001'],
|
|
||||||
'0x',
|
|
||||||
)
|
|
||||||
|
|
||||||
orderArray[i] = await OrderHelper.encodeOrder(
|
|
||||||
await GnosisEasyAuction.numUsers(),
|
|
||||||
buyAmount,
|
|
||||||
sellAmount,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
auctionEndDt = (await GnosisEasyAuction.auctionData(38))[3].sub(BigNumber.from(await timestamp()))
|
|
||||||
|
|
||||||
await minewait(auctionEndDt.toNumber())
|
|
||||||
|
|
||||||
await GnosisEasyAuction.settleAuction(38)
|
|
||||||
|
|
||||||
expect(await WETH.balanceOf(TornadoAuctionHandler.address)).to.be.gt(initialHandlerBalance)
|
|
||||||
|
|
||||||
for (let i = 0; i < signerArray.length; i++) {
|
|
||||||
await GnosisEasyAuction.claimFromParticipantOrder(38, [orderArray[i]])
|
|
||||||
console.log(
|
|
||||||
`Signer ${i} claimed: `,
|
|
||||||
(await TornToken.balanceOf(signerArray[i].address)).toString(),
|
|
||||||
' torn',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
claimedSum = BigNumber.from(0)
|
|
||||||
|
|
||||||
for (let i = 0; i < signerArray.length; i++) {
|
|
||||||
const claimed = await TornToken.balanceOf(signerArray[i].address)
|
|
||||||
claimedSum = claimedSum.add(claimed)
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(claimedSum).to.be.closeTo(
|
|
||||||
ethers.utils.parseEther('787'),
|
|
||||||
ethers.utils.parseUnits('1', 'szabo'),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Test multiple accounts proposal', async function () {
|
|
||||||
let checkIfQuorumFulfilled = async function (proposalId) {
|
|
||||||
const proposalData = await GovernanceContract.proposals(proposalId)
|
|
||||||
const allVotes = proposalData[4].add(proposalData[5])
|
|
||||||
return allVotes.gte(quorumVotes)
|
|
||||||
}
|
|
||||||
|
|
||||||
ProposalContract = await MockProposalFactory.deploy()
|
|
||||||
|
|
||||||
clog(
|
|
||||||
'Torn balance of governance contract: ',
|
|
||||||
(await TornToken.balanceOf(GovernanceContract.address)).toString(),
|
|
||||||
)
|
|
||||||
|
|
||||||
////////////// STANDARD PROPOSAL ARGS TEST //////////////////////
|
|
||||||
let response, id, state
|
|
||||||
;[response, id, state] = await propose([whales[0], ProposalContract, 'LotteryUpgrade'])
|
|
||||||
const { events } = await response.wait()
|
|
||||||
const args = events.find(({ event }) => event == 'ProposalCreated').args
|
|
||||||
expect(args.id).to.be.equal(id)
|
|
||||||
expect(args.target).to.be.equal(ProposalContract.address)
|
|
||||||
expect(args.description).to.be.equal('LotteryUpgrade')
|
|
||||||
expect(state).to.be.equal(ProposalState.Pending)
|
|
||||||
|
|
||||||
////////////////////////INCREMENT TO VOTING TIME////////////////////////
|
|
||||||
await minewait((await GovernanceContract.VOTING_DELAY()).add(1).toNumber())
|
|
||||||
|
|
||||||
/////////////////// PREPARE MULTISIG AND COMPENSATIONS
|
|
||||||
let multiGov = await GovernanceContract.connect(tornadoMultisig)
|
|
||||||
|
|
||||||
await dore.sendTransaction({ to: tornadoMultisig.address, value: pE(1) })
|
|
||||||
await expect(multiGov.setGasCompensations(pE(500))).to.not.be.reverted
|
|
||||||
///////////////////////////// VOTE ////////////////////////////
|
|
||||||
const overrides = {
|
|
||||||
gasPrice: BigNumber.from(5),
|
|
||||||
}
|
|
||||||
|
|
||||||
let signerArmyBalanceInitial = []
|
|
||||||
let signerArmyBalanceDiff = []
|
|
||||||
let gasUsedArray = []
|
|
||||||
|
|
||||||
snapshotIdArray[3] = await sendr('evm_snapshot', [])
|
|
||||||
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
let gov = await GovernanceContract.connect(signerArmy[i])
|
|
||||||
let randN = rand(i * 5, i * 6)
|
|
||||||
randN = randN % 2
|
|
||||||
let response
|
|
||||||
|
|
||||||
signerArmyBalanceInitial[i] = await signerArmy[i].getBalance()
|
|
||||||
|
|
||||||
if (randN > 0) {
|
|
||||||
response = await gov.castDelegatedVote(votingAddressArray[i], id, true, overrides)
|
|
||||||
} else {
|
|
||||||
response = await gov.castDelegatedVote(votingAddressArray[i], id, false, overrides)
|
|
||||||
}
|
|
||||||
|
|
||||||
signerArmyBalanceDiff[i] = !(await checkIfQuorumFulfilled(id))
|
|
||||||
? signerArmyBalanceInitial[i].sub(await signerArmy[i].getBalance())
|
|
||||||
: signerArmyBalanceDiff[i - 1]
|
|
||||||
|
|
||||||
const receipt = await response.wait()
|
|
||||||
gasUsedArray[i] = receipt.cumulativeGasUsed
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 10; i < numberOfVoters - numberOfDelegators; i++) {
|
|
||||||
let gov = await GovernanceContract.connect(signerArmy[i])
|
|
||||||
let randN = rand(i * 5, i * 6)
|
|
||||||
randN = randN % 2
|
|
||||||
let response
|
|
||||||
|
|
||||||
signerArmyBalanceInitial[i] = await signerArmy[i].getBalance()
|
|
||||||
|
|
||||||
if (randN > 0) {
|
|
||||||
response = await gov.castVote(id, true, overrides)
|
|
||||||
} else {
|
|
||||||
response = await gov.castVote(id, false, overrides)
|
|
||||||
}
|
|
||||||
|
|
||||||
signerArmyBalanceDiff[i] = !(await checkIfQuorumFulfilled(id))
|
|
||||||
? signerArmyBalanceInitial[i].sub(await signerArmy[i].getBalance())
|
|
||||||
: signerArmyBalanceDiff[i - 1]
|
|
||||||
|
|
||||||
const receipt = await response.wait()
|
|
||||||
gasUsedArray[i] = receipt.cumulativeGasUsed
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////// GET STATE ///////////////////////////////
|
|
||||||
state = await GovernanceContract.state(id)
|
|
||||||
expect(state).to.be.equal(ProposalState.Active)
|
|
||||||
|
|
||||||
///////////////////////////// VOTER INFO ///////////////////////////////////
|
|
||||||
// (uncomment for more data)
|
|
||||||
/*
|
|
||||||
for (i = 0; i < numberOfVoters; i+=5) {
|
|
||||||
const j = BigNumber.from(i);
|
|
||||||
console.log(
|
|
||||||
`Voter ${i} sqrt: `,
|
|
||||||
((await GovernanceLottery.lotteryUserData(id,j))[0]).toString(),
|
|
||||||
`Voter ${i+1} sqrt: `,
|
|
||||||
((await GovernanceLottery.lotteryUserData(id,j.add(1)))[0]).toString(),
|
|
||||||
`Voter ${i+2} sqrt: `,
|
|
||||||
((await GovernanceLottery.lotteryUserData(id,j.add(2)))[0]).toString(),
|
|
||||||
`Voter ${i+3} sqrt: `,
|
|
||||||
((await GovernanceLottery.lotteryUserData(id,j.add(3)))[0]).toString(),
|
|
||||||
`Voter ${i+4} sqrt: `,
|
|
||||||
((await GovernanceLottery.lotteryUserData(id,j.add(4)))[0]).toString(),
|
|
||||||
"\n",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < numberOfVoters; i+=5) {
|
|
||||||
console.log(
|
|
||||||
`Voter ${i} ether used: `,
|
|
||||||
gasUsedArray[i],
|
|
||||||
`Voter ${i+1} ether used: `,
|
|
||||||
gasUsedArray[i+1],
|
|
||||||
`Voter ${i+2} ether used: `,
|
|
||||||
gasUsedArray[i+2],
|
|
||||||
`Voter ${i+3} ether used: `,
|
|
||||||
gasUsedArray[i+3],
|
|
||||||
`Voter ${i+4} ether used: `,
|
|
||||||
gasUsedArray[i+4],
|
|
||||||
"\n",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
await sendr('evm_revert', [snapshotIdArray[3]])
|
|
||||||
|
|
||||||
///////////////////////////////// VOTE WITHOUT COMPENSATION //////////////////////////////////////
|
|
||||||
let gasUsedWithoutCompensation = []
|
|
||||||
await multiGov.setGasCompensations(pE(100000))
|
|
||||||
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
let gov = await GovernanceContract.connect(signerArmy[i])
|
|
||||||
let randN = rand(i * 5, i * 6)
|
|
||||||
randN = randN % 2
|
|
||||||
let response
|
|
||||||
|
|
||||||
if (randN > 0) {
|
|
||||||
response = await gov.castDelegatedVote(votingAddressArray[i], id, true, overrides)
|
|
||||||
} else {
|
|
||||||
response = await gov.castDelegatedVote(votingAddressArray[i], id, false, overrides)
|
|
||||||
}
|
|
||||||
|
|
||||||
const receipt = await response.wait()
|
|
||||||
gasUsedWithoutCompensation[i] = receipt.cumulativeGasUsed
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 10; i < numberOfVoters - numberOfDelegators; i++) {
|
|
||||||
let gov = await GovernanceContract.connect(signerArmy[i])
|
|
||||||
let randN = rand(i * 5, i * 6)
|
|
||||||
randN = randN % 2
|
|
||||||
let response
|
|
||||||
|
|
||||||
if (randN > 0) {
|
|
||||||
response = await gov.castVote(id, true, overrides)
|
|
||||||
} else {
|
|
||||||
response = await gov.castVote(id, false, overrides)
|
|
||||||
}
|
|
||||||
|
|
||||||
const receipt = await response.wait()
|
|
||||||
|
|
||||||
gasUsedWithoutCompensation[i] = receipt.cumulativeGasUsed
|
|
||||||
}
|
|
||||||
|
|
||||||
await multiGov.setGasCompensations(pE(100))
|
|
||||||
//////////////////////////////// GET STATE ///////////////////////////////
|
|
||||||
state = await GovernanceContract.state(id)
|
|
||||||
expect(state).to.be.equal(ProposalState.Active)
|
|
||||||
|
|
||||||
///////////////////////////// VOTING GAS INFO ///////////////////////////////////
|
|
||||||
let gasUsedSumNoComp = BigNumber.from(0)
|
|
||||||
let gasUsedSum = BigNumber.from(0)
|
|
||||||
let gasSumDiff = BigNumber.from(0)
|
|
||||||
let gasUsedSumNoCompDel = BigNumber.from(0)
|
|
||||||
let gasUsedSumDel = BigNumber.from(0)
|
|
||||||
let gasSumDiffDel = BigNumber.from(0)
|
|
||||||
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
gasUsedSumDel = gasUsedSumDel.add(gasUsedArray[i])
|
|
||||||
gasUsedSumNoCompDel = gasUsedSumNoCompDel.add(gasUsedWithoutCompensation[i])
|
|
||||||
gasSumDiffDel = gasSumDiffDel.add(signerArmyBalanceDiff[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 10; i < numberOfVoters - numberOfDelegators; i++) {
|
|
||||||
gasUsedSum = gasUsedSum.add(gasUsedArray[i])
|
|
||||||
gasUsedSumNoComp = gasUsedSumNoComp.add(gasUsedWithoutCompensation[i])
|
|
||||||
gasSumDiff = gasSumDiff.add(signerArmyBalanceDiff[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
const gasUsedAverageNoCompDel = gasUsedSumNoCompDel.div(10)
|
|
||||||
const gasUsedAverageDel = gasUsedSumDel.div(10)
|
|
||||||
const gasSumAverageDiffDel = gasSumDiffDel.div(10)
|
|
||||||
|
|
||||||
const gasUsedAverageNoComp = gasUsedSumNoComp.div(numberOfVoters - 10)
|
|
||||||
const gasUsedAverage = gasUsedSum.div(numberOfVoters - 10)
|
|
||||||
const gasSumAverageDiff = gasSumDiff.div(numberOfVoters - 10)
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
'\n',
|
|
||||||
'----------------------------CAST VOTE INFO------------------------',
|
|
||||||
'\n',
|
|
||||||
'Gas use average: ',
|
|
||||||
gasUsedAverage.toString(),
|
|
||||||
'\n',
|
|
||||||
'Gas use without compensation average: ',
|
|
||||||
gasUsedAverageNoComp.toString(),
|
|
||||||
'\n',
|
|
||||||
'Gas diff average: ',
|
|
||||||
gasSumAverageDiff.toString(),
|
|
||||||
'\n',
|
|
||||||
'Gas compensated in average: ',
|
|
||||||
gasUsedAverage.sub(gasSumAverageDiff).toString(),
|
|
||||||
'\n',
|
|
||||||
'--------------------------------------------------------------------',
|
|
||||||
'\n',
|
|
||||||
)
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
'\n',
|
|
||||||
'----------------------------CAST DELEGATED VOTE INFO------------------------',
|
|
||||||
'\n',
|
|
||||||
'Gas use average: ',
|
|
||||||
gasUsedAverageDel.toString(),
|
|
||||||
'\n',
|
|
||||||
'Gas use without compensation average: ',
|
|
||||||
gasUsedAverageNoCompDel.toString(),
|
|
||||||
'\n',
|
|
||||||
'Gas diff average: ',
|
|
||||||
gasSumAverageDiffDel.toString(),
|
|
||||||
'\n',
|
|
||||||
'Gas compensated in average: ',
|
|
||||||
gasUsedAverageDel.sub(gasSumAverageDiffDel).toString(),
|
|
||||||
'\n',
|
|
||||||
'--------------------------------------------------------------------',
|
|
||||||
'\n',
|
|
||||||
)
|
|
||||||
/////////////////////////////// INCREMENT AGAIN //////////////////////////////////
|
|
||||||
await minewait(
|
|
||||||
(
|
|
||||||
await GovernanceContract.VOTING_PERIOD()
|
|
||||||
)
|
|
||||||
.add(await GovernanceContract.EXECUTION_DELAY())
|
|
||||||
.add(10000)
|
|
||||||
.toNumber(),
|
|
||||||
)
|
|
||||||
|
|
||||||
////////////// EXECUTE
|
|
||||||
if (BigNumber.from(await GovernanceContract.state(id)).eq(ProposalState.Defeated)) {
|
|
||||||
await expect(GovernanceContract.execute(id)).to.be.reverted
|
|
||||||
} else {
|
|
||||||
await expect(GovernanceContract.execute(id)).to.not.be.reverted
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
after(async function () {
|
|
||||||
await ethers.provider.send('hardhat_reset', [
|
|
||||||
{
|
|
||||||
forking: {
|
|
||||||
jsonRpcUrl: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
|
|
||||||
blockNumber: process.env.use_latest_block == 'true' ? undefined : 13211966,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -0,0 +1,495 @@
|
||||||
|
const { expect } = require('chai')
|
||||||
|
const { ethers } = require('hardhat')
|
||||||
|
const { BigNumber } = require('@ethersproject/bignumber')
|
||||||
|
const { propose } = require('../../scripts/helper/propose_proposal.js')
|
||||||
|
const testcases = require('@ethersproject/testcases')
|
||||||
|
const seedbase = require('../../resources/hdnode.json')
|
||||||
|
const accountList = require('../../resources/accounts.json')
|
||||||
|
|
||||||
|
describe('V2 governance tests', () => {
|
||||||
|
///// ON-CHAIN CONSTANTS
|
||||||
|
let proxy_address = '0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce'
|
||||||
|
let quorumVotes
|
||||||
|
|
||||||
|
///////////////////////////// CONTRACTS
|
||||||
|
let GovernanceContract
|
||||||
|
let TornToken
|
||||||
|
|
||||||
|
//////////////////// IMPERSONATED
|
||||||
|
let tornadoMultisig
|
||||||
|
|
||||||
|
//////////////////////////////// MOCK
|
||||||
|
let MockProposalFactory
|
||||||
|
|
||||||
|
/////// GOV PARAMS
|
||||||
|
const ProposalState = {
|
||||||
|
Pending: 0,
|
||||||
|
Active: 1,
|
||||||
|
Defeated: 2,
|
||||||
|
Timelocked: 3,
|
||||||
|
AwaitingExecution: 4,
|
||||||
|
Executed: 5,
|
||||||
|
Expired: 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
///// ACCOUNTS
|
||||||
|
let dore
|
||||||
|
let whale
|
||||||
|
let signerArray = []
|
||||||
|
let whales = []
|
||||||
|
|
||||||
|
//////////////////////////////////// TESTING & UTILITY
|
||||||
|
let randN = Math.floor(Math.random() * 1023)
|
||||||
|
let testseed = seedbase[randN].seed
|
||||||
|
|
||||||
|
let minewait = async (time) => {
|
||||||
|
await ethers.provider.send('evm_increaseTime', [time])
|
||||||
|
await ethers.provider.send('evm_mine', [])
|
||||||
|
}
|
||||||
|
|
||||||
|
let sendr = async (method, params) => {
|
||||||
|
return await ethers.provider.send(method, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
let clog = (...x) => {
|
||||||
|
console.log(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
let pE = (x) => {
|
||||||
|
return ethers.utils.parseEther(`${x}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
let rand = (l, u) => {
|
||||||
|
return testcases.randomNumber(testseed, l, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
let snapshotIdArray = []
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////7
|
||||||
|
before(async function () {
|
||||||
|
signerArray = await ethers.getSigners()
|
||||||
|
dore = signerArray[0]
|
||||||
|
|
||||||
|
MockProposalFactory = await ethers.getContractFactory('MockProposal')
|
||||||
|
|
||||||
|
GovernanceContract = await ethers.getContractAt('GovernanceGasUpgrade', proxy_address)
|
||||||
|
|
||||||
|
TornToken = await ethers.getContractAt(
|
||||||
|
'@openzeppelin/contracts/token/ERC20/IERC20.sol:IERC20',
|
||||||
|
'0x77777FeDdddFfC19Ff86DB637967013e6C6A116C',
|
||||||
|
)
|
||||||
|
|
||||||
|
quorumVotes = await GovernanceContract.QUORUM_VOTES()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#imitation block', () => {
|
||||||
|
it('Should successfully imitate tornado multisig', async function () {
|
||||||
|
await sendr('hardhat_impersonateAccount', ['0xb04E030140b30C27bcdfaafFFA98C57d80eDa7B4'])
|
||||||
|
tornadoMultisig = await ethers.getSigner('0xb04E030140b30C27bcdfaafFFA98C57d80eDa7B4')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should successfully imitate whale', async function () {
|
||||||
|
await sendr('hardhat_impersonateAccount', ['0xA2b2fBCaC668d86265C45f62dA80aAf3Fd1dEde3'])
|
||||||
|
whale = await ethers.getSigner('0xA2b2fBCaC668d86265C45f62dA80aAf3Fd1dEde3')
|
||||||
|
GovernanceContract = await GovernanceContract.connect(whale)
|
||||||
|
|
||||||
|
let balance = await TornToken.balanceOf(whale.address)
|
||||||
|
TornToken = await TornToken.connect(whale)
|
||||||
|
|
||||||
|
await TornToken.approve(GovernanceContract.address, ethers.utils.parseEther('8000000000'))
|
||||||
|
await expect(GovernanceContract.lockWithApproval(balance)).to.not.be.reverted
|
||||||
|
|
||||||
|
expect((await GovernanceContract.lockedBalance(whale.address)).toString()).to.equal(balance.toString())
|
||||||
|
snapshotIdArray[0] = await sendr('evm_snapshot', [])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#mock rewards + proposal distribution with multiple accounts', () => {
|
||||||
|
let addrArray = []
|
||||||
|
let signerArmy = []
|
||||||
|
let delegatedSignerArmy = []
|
||||||
|
let votingAddressArray = []
|
||||||
|
const numberOfVoters = 80
|
||||||
|
const numberOfDelegators = 30
|
||||||
|
|
||||||
|
it('Should create empty address array', () => {
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
votingAddressArray[i] = new Array(numberOfDelegators / 10 + 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should impersonate and fund 80 accounts', async function () {
|
||||||
|
////////// WRITE WHALE ADDRESSES AND PREPARE FOR TRANSFERS
|
||||||
|
addrArray = [
|
||||||
|
'0x6cC5F688a315f3dC28A7781717a9A798a59fDA7b',
|
||||||
|
'0xF977814e90dA44bFA03b6295A0616a897441aceC',
|
||||||
|
'0xA2b2fBCaC668d86265C45f62dA80aAf3Fd1dEde3',
|
||||||
|
'0x055AD5E56c11c0eF55818155c69ed9BA2f4b3e90',
|
||||||
|
]
|
||||||
|
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
await sendr('hardhat_impersonateAccount', [addrArray[i]])
|
||||||
|
whales[i] = await ethers.getSigner(addrArray[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i < 4; i++) {
|
||||||
|
//last test really unnecessary
|
||||||
|
const torn = await TornToken.connect(whales[i])
|
||||||
|
const whaleBalance = await torn.balanceOf(whales[i].address)
|
||||||
|
await torn.approve(addrArray[0], whaleBalance)
|
||||||
|
await expect(() => torn.transfer(addrArray[0], whaleBalance)).to.changeTokenBalance(
|
||||||
|
torn,
|
||||||
|
whales[0],
|
||||||
|
whaleBalance,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const whale0Balance = await TornToken.balanceOf(whales[0].address)
|
||||||
|
const toTransfer = whale0Balance.sub(pE(10000)).div(numberOfVoters * 3)
|
||||||
|
let torn0 = await TornToken.connect(whales[0])
|
||||||
|
const oldBalance = await TornToken.balanceOf(await GovernanceContract.userVault())
|
||||||
|
let lockedSum = BigNumber.from(0)
|
||||||
|
|
||||||
|
////////// TRANSFER TO 50 ACCOUNTS + DELEGATION TO 10
|
||||||
|
|
||||||
|
for (let i = 0; i < numberOfVoters; i++) {
|
||||||
|
/// PREPARE ACCOUNTS
|
||||||
|
const accAddress = accountList[i + 7].checksumAddress
|
||||||
|
await sendr('hardhat_impersonateAccount', [accAddress])
|
||||||
|
|
||||||
|
signerArmy[i] = await ethers.getSigner(accAddress)
|
||||||
|
const tx = { to: signerArmy[i].address, value: pE(1) }
|
||||||
|
|
||||||
|
await signerArray[0].sendTransaction(tx)
|
||||||
|
|
||||||
|
/// FILL WITH GAS FOR LATER
|
||||||
|
await expect(() => torn0.transfer(signerArmy[i].address, toTransfer)).to.changeTokenBalance(
|
||||||
|
torn0,
|
||||||
|
signerArmy[i],
|
||||||
|
toTransfer,
|
||||||
|
)
|
||||||
|
let torn = await torn0.connect(signerArmy[i])
|
||||||
|
|
||||||
|
/// APPROVE TO GOVERNANCE FOR LOCK
|
||||||
|
await expect(torn.approve(GovernanceContract.address, toTransfer)).to.not.be.reverted
|
||||||
|
const gov = await GovernanceContract.connect(signerArmy[i])
|
||||||
|
|
||||||
|
///// LOCK
|
||||||
|
if (i > numberOfVoters / 2) {
|
||||||
|
await expect(() => gov.lockWithApproval(toTransfer.div(i))).to.changeTokenBalance(
|
||||||
|
torn,
|
||||||
|
signerArmy[i],
|
||||||
|
BigNumber.from(0).sub(toTransfer.div(i)),
|
||||||
|
)
|
||||||
|
lockedSum = lockedSum.add(toTransfer.div(i))
|
||||||
|
} else {
|
||||||
|
await expect(() => gov.lockWithApproval(toTransfer)).to.changeTokenBalance(
|
||||||
|
torn,
|
||||||
|
signerArmy[i],
|
||||||
|
BigNumber.from(0).sub(toTransfer),
|
||||||
|
)
|
||||||
|
lockedSum = lockedSum.add(toTransfer)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > numberOfVoters - numberOfDelegators - 1) {
|
||||||
|
delegatedSignerArmy[i - (numberOfVoters - numberOfDelegators)] = signerArmy[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 10) {
|
||||||
|
votingAddressArray[i][0] = signerArmy[i].address
|
||||||
|
}
|
||||||
|
|
||||||
|
const restBalance = await torn.balanceOf(signerArmy[i].address)
|
||||||
|
await torn.transfer(whale.address, restBalance)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < numberOfDelegators; i++) {
|
||||||
|
const gov = await GovernanceContract.connect(delegatedSignerArmy[i])
|
||||||
|
/// DELEGATE TO 10 FIRST SIGNERS
|
||||||
|
await expect(gov.delegate(signerArmy[i % 10].address)).to.emit(gov, 'Delegated')
|
||||||
|
votingAddressArray[i % 10][Math.floor(i / 10) + 1] = delegatedSignerArmy[i].address
|
||||||
|
}
|
||||||
|
|
||||||
|
const TornVault = await GovernanceContract.userVault()
|
||||||
|
expect(await TornToken.balanceOf(TornVault)).to.equal(lockedSum.add(oldBalance))
|
||||||
|
|
||||||
|
const gov = await GovernanceContract.connect(whales[0])
|
||||||
|
await expect(torn0.approve(GovernanceContract.address, pE(10000))).to.not.be.reverted
|
||||||
|
await expect(() => gov.lockWithApproval(toTransfer)).to.changeTokenBalance(
|
||||||
|
torn0,
|
||||||
|
whales[0],
|
||||||
|
BigNumber.from(0).sub(toTransfer),
|
||||||
|
)
|
||||||
|
|
||||||
|
snapshotIdArray[1] = await sendr('evm_snapshot', [])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Test multiple accounts proposal', async function () {
|
||||||
|
let checkIfQuorumFulfilled = async function (proposalId) {
|
||||||
|
const proposalData = await GovernanceContract.proposals(proposalId)
|
||||||
|
const allVotes = proposalData[4].add(proposalData[5])
|
||||||
|
return allVotes.gte(quorumVotes)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProposalContract = await MockProposalFactory.deploy()
|
||||||
|
|
||||||
|
clog(
|
||||||
|
'Torn balance of governance contract: ',
|
||||||
|
(await TornToken.balanceOf(GovernanceContract.address)).toString(),
|
||||||
|
)
|
||||||
|
|
||||||
|
////////////// STANDARD PROPOSAL ARGS TEST //////////////////////
|
||||||
|
let response, id, state
|
||||||
|
;[response, id, state] = await propose([whales[0], ProposalContract, 'LotteryUpgrade'])
|
||||||
|
const { events } = await response.wait()
|
||||||
|
const args = events.find(({ event }) => event == 'ProposalCreated').args
|
||||||
|
expect(args.id).to.be.equal(id)
|
||||||
|
expect(args.target).to.be.equal(ProposalContract.address)
|
||||||
|
expect(args.description).to.be.equal('LotteryUpgrade')
|
||||||
|
expect(state).to.be.equal(ProposalState.Pending)
|
||||||
|
|
||||||
|
////////////////////////INCREMENT TO VOTING TIME////////////////////////
|
||||||
|
await minewait((await GovernanceContract.VOTING_DELAY()).add(1).toNumber())
|
||||||
|
|
||||||
|
/////////////////// PREPARE MULTISIG AND COMPENSATIONS
|
||||||
|
let multiGov = await GovernanceContract.connect(tornadoMultisig)
|
||||||
|
|
||||||
|
await dore.sendTransaction({ to: tornadoMultisig.address, value: pE(1) })
|
||||||
|
await expect(multiGov.setGasCompensations(pE(500))).to.not.be.reverted
|
||||||
|
///////////////////////////// VOTE ////////////////////////////
|
||||||
|
const overrides = {
|
||||||
|
gasPrice: BigNumber.from(5),
|
||||||
|
}
|
||||||
|
|
||||||
|
let signerArmyBalanceInitial = []
|
||||||
|
let signerArmyBalanceDiff = []
|
||||||
|
let gasUsedArray = []
|
||||||
|
|
||||||
|
snapshotIdArray[2] = await sendr('evm_snapshot', [])
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
let gov = await GovernanceContract.connect(signerArmy[i])
|
||||||
|
let randN = rand(i * 5, i * 6)
|
||||||
|
randN = randN % 2
|
||||||
|
let response
|
||||||
|
|
||||||
|
signerArmyBalanceInitial[i] = await signerArmy[i].getBalance()
|
||||||
|
|
||||||
|
if (randN > 0) {
|
||||||
|
response = await gov.castDelegatedVote(votingAddressArray[i], id, true, overrides)
|
||||||
|
} else {
|
||||||
|
response = await gov.castDelegatedVote(votingAddressArray[i], id, false, overrides)
|
||||||
|
}
|
||||||
|
|
||||||
|
signerArmyBalanceDiff[i] = !(await checkIfQuorumFulfilled(id))
|
||||||
|
? signerArmyBalanceInitial[i].sub(await signerArmy[i].getBalance())
|
||||||
|
: signerArmyBalanceDiff[i - 1]
|
||||||
|
|
||||||
|
const receipt = await response.wait()
|
||||||
|
gasUsedArray[i] = receipt.cumulativeGasUsed
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 10; i < numberOfVoters - numberOfDelegators; i++) {
|
||||||
|
let gov = await GovernanceContract.connect(signerArmy[i])
|
||||||
|
let randN = rand(i * 5, i * 6)
|
||||||
|
randN = randN % 2
|
||||||
|
let response
|
||||||
|
|
||||||
|
signerArmyBalanceInitial[i] = await signerArmy[i].getBalance()
|
||||||
|
|
||||||
|
if (randN > 0) {
|
||||||
|
response = await gov.castVote(id, true, overrides)
|
||||||
|
} else {
|
||||||
|
response = await gov.castVote(id, false, overrides)
|
||||||
|
}
|
||||||
|
|
||||||
|
signerArmyBalanceDiff[i] = !(await checkIfQuorumFulfilled(id))
|
||||||
|
? signerArmyBalanceInitial[i].sub(await signerArmy[i].getBalance())
|
||||||
|
: signerArmyBalanceDiff[i - 1]
|
||||||
|
|
||||||
|
const receipt = await response.wait()
|
||||||
|
gasUsedArray[i] = receipt.cumulativeGasUsed
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////// GET STATE ///////////////////////////////
|
||||||
|
state = await GovernanceContract.state(id)
|
||||||
|
expect(state).to.be.equal(ProposalState.Active)
|
||||||
|
|
||||||
|
///////////////////////////// VOTER INFO ///////////////////////////////////
|
||||||
|
// (uncomment for more data)
|
||||||
|
/*
|
||||||
|
for (i = 0; i < numberOfVoters; i+=5) {
|
||||||
|
const j = BigNumber.from(i);
|
||||||
|
console.log(
|
||||||
|
`Voter ${i} sqrt: `,
|
||||||
|
((await GovernanceLottery.lotteryUserData(id,j))[0]).toString(),
|
||||||
|
`Voter ${i+1} sqrt: `,
|
||||||
|
((await GovernanceLottery.lotteryUserData(id,j.add(1)))[0]).toString(),
|
||||||
|
`Voter ${i+2} sqrt: `,
|
||||||
|
((await GovernanceLottery.lotteryUserData(id,j.add(2)))[0]).toString(),
|
||||||
|
`Voter ${i+3} sqrt: `,
|
||||||
|
((await GovernanceLottery.lotteryUserData(id,j.add(3)))[0]).toString(),
|
||||||
|
`Voter ${i+4} sqrt: `,
|
||||||
|
((await GovernanceLottery.lotteryUserData(id,j.add(4)))[0]).toString(),
|
||||||
|
"\n",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numberOfVoters; i+=5) {
|
||||||
|
console.log(
|
||||||
|
`Voter ${i} ether used: `,
|
||||||
|
gasUsedArray[i],
|
||||||
|
`Voter ${i+1} ether used: `,
|
||||||
|
gasUsedArray[i+1],
|
||||||
|
`Voter ${i+2} ether used: `,
|
||||||
|
gasUsedArray[i+2],
|
||||||
|
`Voter ${i+3} ether used: `,
|
||||||
|
gasUsedArray[i+3],
|
||||||
|
`Voter ${i+4} ether used: `,
|
||||||
|
gasUsedArray[i+4],
|
||||||
|
"\n",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
await sendr('evm_revert', [snapshotIdArray[2]])
|
||||||
|
|
||||||
|
///////////////////////////////// VOTE WITHOUT COMPENSATION //////////////////////////////////////
|
||||||
|
let gasUsedWithoutCompensation = []
|
||||||
|
await multiGov.setGasCompensations(pE(100000))
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
let gov = await GovernanceContract.connect(signerArmy[i])
|
||||||
|
let randN = rand(i * 5, i * 6)
|
||||||
|
randN = randN % 2
|
||||||
|
let response
|
||||||
|
|
||||||
|
if (randN > 0) {
|
||||||
|
response = await gov.castDelegatedVote(votingAddressArray[i], id, true, overrides)
|
||||||
|
} else {
|
||||||
|
response = await gov.castDelegatedVote(votingAddressArray[i], id, false, overrides)
|
||||||
|
}
|
||||||
|
|
||||||
|
const receipt = await response.wait()
|
||||||
|
gasUsedWithoutCompensation[i] = receipt.cumulativeGasUsed
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 10; i < numberOfVoters - numberOfDelegators; i++) {
|
||||||
|
let gov = await GovernanceContract.connect(signerArmy[i])
|
||||||
|
let randN = rand(i * 5, i * 6)
|
||||||
|
randN = randN % 2
|
||||||
|
let response
|
||||||
|
|
||||||
|
if (randN > 0) {
|
||||||
|
response = await gov.castVote(id, true, overrides)
|
||||||
|
} else {
|
||||||
|
response = await gov.castVote(id, false, overrides)
|
||||||
|
}
|
||||||
|
|
||||||
|
const receipt = await response.wait()
|
||||||
|
|
||||||
|
gasUsedWithoutCompensation[i] = receipt.cumulativeGasUsed
|
||||||
|
}
|
||||||
|
|
||||||
|
await multiGov.setGasCompensations(pE(100))
|
||||||
|
//////////////////////////////// GET STATE ///////////////////////////////
|
||||||
|
state = await GovernanceContract.state(id)
|
||||||
|
expect(state).to.be.equal(ProposalState.Active)
|
||||||
|
|
||||||
|
///////////////////////////// VOTING GAS INFO ///////////////////////////////////
|
||||||
|
let gasUsedSumNoComp = BigNumber.from(0)
|
||||||
|
let gasUsedSum = BigNumber.from(0)
|
||||||
|
let gasSumDiff = BigNumber.from(0)
|
||||||
|
let gasUsedSumNoCompDel = BigNumber.from(0)
|
||||||
|
let gasUsedSumDel = BigNumber.from(0)
|
||||||
|
let gasSumDiffDel = BigNumber.from(0)
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
gasUsedSumDel = gasUsedSumDel.add(gasUsedArray[i])
|
||||||
|
gasUsedSumNoCompDel = gasUsedSumNoCompDel.add(gasUsedWithoutCompensation[i])
|
||||||
|
gasSumDiffDel = gasSumDiffDel.add(signerArmyBalanceDiff[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 10; i < numberOfVoters - numberOfDelegators; i++) {
|
||||||
|
gasUsedSum = gasUsedSum.add(gasUsedArray[i])
|
||||||
|
gasUsedSumNoComp = gasUsedSumNoComp.add(gasUsedWithoutCompensation[i])
|
||||||
|
gasSumDiff = gasSumDiff.add(signerArmyBalanceDiff[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
const gasUsedAverageNoCompDel = gasUsedSumNoCompDel.div(10)
|
||||||
|
const gasUsedAverageDel = gasUsedSumDel.div(10)
|
||||||
|
const gasSumAverageDiffDel = gasSumDiffDel.div(10)
|
||||||
|
|
||||||
|
const gasUsedAverageNoComp = gasUsedSumNoComp.div(numberOfVoters - 10)
|
||||||
|
const gasUsedAverage = gasUsedSum.div(numberOfVoters - 10)
|
||||||
|
const gasSumAverageDiff = gasSumDiff.div(numberOfVoters - 10)
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
'\n',
|
||||||
|
'----------------------------CAST VOTE INFO------------------------',
|
||||||
|
'\n',
|
||||||
|
'Gas use average: ',
|
||||||
|
gasUsedAverage.toString(),
|
||||||
|
'\n',
|
||||||
|
'Gas use without compensation average: ',
|
||||||
|
gasUsedAverageNoComp.toString(),
|
||||||
|
'\n',
|
||||||
|
'Gas diff average: ',
|
||||||
|
gasSumAverageDiff.toString(),
|
||||||
|
'\n',
|
||||||
|
'Gas compensated in average: ',
|
||||||
|
gasUsedAverage.sub(gasSumAverageDiff).toString(),
|
||||||
|
'\n',
|
||||||
|
'--------------------------------------------------------------------',
|
||||||
|
'\n',
|
||||||
|
)
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
'\n',
|
||||||
|
'----------------------------CAST DELEGATED VOTE INFO------------------------',
|
||||||
|
'\n',
|
||||||
|
'Gas use average: ',
|
||||||
|
gasUsedAverageDel.toString(),
|
||||||
|
'\n',
|
||||||
|
'Gas use without compensation average: ',
|
||||||
|
gasUsedAverageNoCompDel.toString(),
|
||||||
|
'\n',
|
||||||
|
'Gas diff average: ',
|
||||||
|
gasSumAverageDiffDel.toString(),
|
||||||
|
'\n',
|
||||||
|
'Gas compensated in average: ',
|
||||||
|
gasUsedAverageDel.sub(gasSumAverageDiffDel).toString(),
|
||||||
|
'\n',
|
||||||
|
'--------------------------------------------------------------------',
|
||||||
|
'\n',
|
||||||
|
)
|
||||||
|
/////////////////////////////// INCREMENT AGAIN //////////////////////////////////
|
||||||
|
await minewait(
|
||||||
|
(
|
||||||
|
await GovernanceContract.VOTING_PERIOD()
|
||||||
|
)
|
||||||
|
.add(await GovernanceContract.EXECUTION_DELAY())
|
||||||
|
.add(10000)
|
||||||
|
.toNumber(),
|
||||||
|
)
|
||||||
|
|
||||||
|
////////////// EXECUTE
|
||||||
|
if (BigNumber.from(await GovernanceContract.state(id)).eq(ProposalState.Defeated)) {
|
||||||
|
await expect(GovernanceContract.execute(id)).to.be.reverted
|
||||||
|
} else {
|
||||||
|
await expect(GovernanceContract.execute(id)).to.not.be.reverted
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(async function () {
|
||||||
|
await ethers.provider.send('hardhat_reset', [
|
||||||
|
{
|
||||||
|
forking: {
|
||||||
|
jsonRpcUrl: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
|
||||||
|
blockNumber: process.env.use_latest_block == 'true' ? undefined : 14042331,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,35 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
networks: {
|
|
||||||
// development: {
|
|
||||||
// // host: '127.0.0.1', // Localhost (default: none)
|
|
||||||
// // port: 8545, // Standard Ethereum port (default: none)
|
|
||||||
// network_id: '*', // Any network (default: none)
|
|
||||||
// accounts: 20,
|
|
||||||
// },
|
|
||||||
coverage: {
|
|
||||||
host: 'localhost',
|
|
||||||
network_id: '*',
|
|
||||||
port: 8554, // <-- If you change this, also set the port option in .solcover.js.
|
|
||||||
gas: 0xfffffffffff, // <-- Use this high gas value
|
|
||||||
gasPrice: 0x01, // <-- Use this low gas price
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
mocha: {
|
|
||||||
// timeout: 100000
|
|
||||||
},
|
|
||||||
|
|
||||||
compilers: {
|
|
||||||
solc: {
|
|
||||||
version: '0.6.12',
|
|
||||||
docker: false,
|
|
||||||
settings: {
|
|
||||||
optimizer: {
|
|
||||||
enabled: true,
|
|
||||||
runs: 200,
|
|
||||||
},
|
|
||||||
// evmVersion: "byzantium"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
5599
yarn-error.log
5599
yarn-error.log
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue