Skip to content

Commit

Permalink
fix: check trustedCaller, enhance simulation logic
Browse files Browse the repository at this point in the history
  • Loading branch information
krogla committed Oct 25, 2023
1 parent a6240d4 commit ce07567
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 57 deletions.
1 change: 1 addition & 0 deletions deployed-holesky.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
"moduleFee": 800,
"treasuryFee": 200,
"penaltyDelay": 86400,
"easyTrackTrustedCaller": "0xD76001b33b23452243E2FDa833B6e7B8E3D43198",
"easyTrackAddress": "0x1763b9ED3586B08AE796c7787811a2E1bc16163a",
"easyTrackFactories": {
"AddNodeOperators": "0xeF5233A5bbF243149E35B353A73FFa8931FDA02b",
Expand Down
7 changes: 6 additions & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const getNetConfig = (networkName, ethAccountName) => {
const byNetName = {
localhost: {
...base,
url: 'http://localhost:8545',
url: 'http://127.0.0.1:8545',
chainId: 31337,
},
mainnetfork: {
Expand All @@ -67,6 +67,11 @@ const getNetConfig = (networkName, ethAccountName) => {
url: RPC_URL,
chainId: Number(process.env.CHAIN_ID) || 5,
},
holeskyfork: {
...base,
url: RPC_URL,
chainId: Number(process.env.CHAIN_ID) || 17000,
},
local: {
url: RPC_URL,
chainId: Number(process.env.CHAIN_ID) || 1337,
Expand Down
53 changes: 43 additions & 10 deletions scripts/simpledvt/02-clone-nor.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { encodeCallScript } = require('@aragon/contract-helpers-test/src/aragon-o
const { getEventArgument } = require('@aragon/contract-helpers-test')
const { EVMScriptDecoder, abiProviders } = require('evm-script-decoder')
const runOrWrapScript = require('../helpers/run-or-wrap-script')
const { log, yl, gr, cy, mg } = require('../helpers/log')
const { log, yl, gr, cy } = require('../helpers/log')
// const { saveCallTxData } = require('../helpers/tx-data')
const { resolveLatestVersion } = require('../components/apm')
const {
Expand All @@ -29,8 +29,10 @@ const {
REQUEST_BURN_SHARES_ROLE,
SIMPLE_DVT_IPFS_CID,
easyTrackABI,
easyTrackFactoryABI,
_pause,
_checkLog,
_checkEqLog,
} = require('./helpers')
const { ETH, toBN } = require('../../test/helpers/utils')

Expand Down Expand Up @@ -113,6 +115,7 @@ async function deploySimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid
treasuryFee,
penaltyDelay,
easyTrackAddress,
easyTrackTrustedCaller,
easyTrackFactories = {},
} = state[`app:${trgAppName}`].stakingRouterModuleParams

Expand Down Expand Up @@ -177,12 +180,16 @@ async function deploySimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid

log(`EasyTrack`, yl(easyTrackAddress))
log(`EasyTrack EVM Script Executor`, yl(easyTrackEVMScriptExecutor))
log(`EasyTrack Trusted caller`, yl(easyTrackTrustedCaller))

for (const f of Object.keys(easyTrackFactories)) {
log(`EasyTrack Factory <${cy(f)}>`, yl(easyTrackFactories[f]))
const fc = new Contract(easyTrackFactories[f], easyTrackFactoryABI, ethers.provider)
_checkEqLog(await fc.trustedCaller(), easyTrackTrustedCaller, `EasyTrack Factory <${cy(f)}> trusted caller`)
}

log.splitter()
log(yl('^^^ check all the params above ^^^'))
await _pause()
log.splitter()

Expand Down Expand Up @@ -413,9 +420,10 @@ async function deploySimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid
}

log.splitter()
log(yl('^^^ check the decoded voting script above ^^^'))

if (SIMULATE) {
await _pause(mg('>>> Enter Y to start simulation, interrupt process otherwise:'))
await _pause('Ready for simulation')
log.splitter()
log(gr(`Simulating voting creation and enact!`))
const voters = getVoters(
Expand All @@ -432,29 +440,54 @@ async function deploySimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid
log(`Creating voting on behalf holder`, yl(voters[0]))
const result = await tokenManager.forward(newVoteEvmScript, { from: voters[0], gasPrice: 0 })
voteId = getEventArgument(result, 'StartVote', 'voteId', { decodeForAbi: voting.abi })
log(`Voting created, id`, yl(voteId))
log(`Voting created, Vote ID:`, yl(voteId))
} else {
voteId = VOTE_ID
}

// vote
log(`Collect votes...`)
log(`Checking state, Vote ID:`, yl(voteId))
let vote = await voting.getVote(voteId)
if (vote.executed) {
log.error(`Vote ID: ${yl(voteId)} is already executed, can't simulate!`)
return
}

log(`Collecting votes...`)
for (const voter of voters) {
await ethers.getImpersonatedSigner(voter)
log(`Cast voting on behalf holder`, yl(voters[0]))
await voting.vote(voteId, true, true, { from: voter, gasPrice: 0 })
if (vote.yea >= vote.supportRequired) {
break
}
const canVote = await voting.canVote(voteId, voter)
if (canVote) {
await ethers.getImpersonatedSigner(voter)
log(`Cast voting on behalf holder:`, yl(voters[0]))

await voting.vote(voteId, true, true, { from: voter, gasPrice: 0 })
vote = await voting.getVote(voteId)
} else {
log(`Skip holder (can't vote):`, voters[0])
}
}

if (vote.yea < vote.supportRequired) {
log.error(`Not enough voting power for Vote ID:`, yl(voteId))
return
}
log(`Vote quorum passed`)

const voteTime = (await voting.voteTime()).toNumber()
// pass time and enact
log(`Pass time...`)
await ethers.provider.send('evm_increaseTime', [voteTime])
await ethers.provider.send('evm_mine')
log(`Enacting voting, id`, yl(voteId))
log(`Enacting vote...`)
await voting.executeVote(voteId, { from: deployer, gasPrice: 0 })

log(`Target App initialized`, yl(await trgApp.hasInitialized()))
log(`Vote executed!`)
_checkEqLog(await trgApp.hasInitialized(), true, `Target App initialized`)
} else {
await _pause(mg('>>> Ready fo TX, enter Y to continue, interrupt process otherwise:'))
await _pause('Ready for TX')
log.splitter()

const tx = await log.tx(
Expand Down
93 changes: 51 additions & 42 deletions scripts/simpledvt/03-check-deployed.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ const { network, ethers } = require('hardhat')
const { Contract, utils } = require('ethers')
const chalk = require('chalk')
const runOrWrapScript = require('../helpers/run-or-wrap-script')
const { log, yl, gr, cy, mg } = require('../helpers/log')
const { log, yl, gr, cy } = require('../helpers/log')
const {
getDeployer,
readStateAppAddress,
_checkEq,
_pause,
Expand All @@ -23,7 +22,7 @@ const { readNetworkState, assertRequiredNetworkState } = require('../helpers/per
const { hash: namehash } = require('eth-ens-namehash')
const { resolveLatestVersion } = require('../components/apm')
const { APP_NAMES, APP_ARTIFACTS } = require('../constants')
const { ETH, toBN, genKeys } = require('../../test/helpers/utils')
const { ETH, toBN, genKeys, ethToStr } = require('../../test/helpers/utils')
const { EvmSnapshot } = require('../../test/helpers/blockchain')

const APP_TRG = process.env.APP_TRG || 'simple-dvt'
Expand Down Expand Up @@ -92,6 +91,7 @@ async function checkSimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid =
treasuryFee,
penaltyDelay,
easyTrackAddress,
easyTrackTrustedCaller,
easyTrackFactories = {},
} = state[`app:${trgAppName}`].stakingRouterModuleParams

Expand Down Expand Up @@ -231,16 +231,17 @@ async function checkSimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid =
_checkEq(allFactories.includes(factories[name].address), true, `- in global list`)
_checkEq(await easytrack.isEVMScriptFactory(factories[name].address), true, `- isEVMScriptFactory`)
_checkEq(await factories[name].nodeOperatorsRegistry(), trgProxyAddress, `- matches target App`)
_checkEq(await factories[name].trustedCaller(), easyTrackTrustedCaller, `- trusted caller`)
}

log.splitter()

if (SIMULATE) {
await _pause(mg('>>> Enter Y to start simulation, interrupt process otherwise:'))
await _pause('Ready for simulation')
log.splitter()

log(gr(`Simulating adding keys and deposit!`))
const stranger = await getDeployer(web3)
const strangers = await web3.eth.getAccounts()

const abiCoder = new utils.AbiCoder()

Expand All @@ -266,13 +267,13 @@ async function checkSimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid =
const keysAmount = op1keysAmount + op2keysAmount
if ((await trgApp.getNodeOperatorsCount()) < 1) {
// prepare node operators
const trustedCaller = await factories.AddNodeOperators.trustedCaller()

// add 2 NO via ET
// equivalent of:
// await trgApp.addNodeOperator('op 1', ADDRESS_1, { from: easyTrackEVMScriptExecutor, gasPrice: 0 })
// await trgApp.addNodeOperator('op 2', ADDRESS_2, { from: easyTrackEVMScriptExecutor, gasPrice: 0 })

log(`Adding 2 operators via ET ${cy('AddNodeOperators')} factory...`)
let callData = abiCoder.encode(
// struct AddNodeOperatorInput {
// string name;
Expand All @@ -290,41 +291,34 @@ async function checkSimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid =
],
]
)
let evmScript = await factories.AddNodeOperators.createEVMScript(trustedCaller, callData, {
from: stranger,
gasPrice: 0,
})
let evmScript = await factories.AddNodeOperators.createEVMScript(easyTrackTrustedCaller, callData)
await evmExecutor.executeEVMScript(evmScript, { gasPrice: 0 })
_checkEq(await trgApp.getNodeOperatorsCount(), 2, `Simulate init: operators count = 2`)
_checkEq(await trgApp.getNodeOperatorsCount(), 2, `Module operators count = 2`)

// add keys to module for op1 (on behalf op1 reward addr)
log(`Adding ${op1keysAmount} keys for op1 (on behalf op1 reward addr)...`)
await ethers.getImpersonatedSigner(ADDRESS_1)
let keys = genKeys(op1keysAmount)
await trgApp.addSigningKeys(0, op1keysAmount, keys.pubkeys, keys.sigkeys, { from: ADDRESS_1, gasPrice: 0 })

// add keys to module for op2 (on behalf op2 manager)
log(`Adding ${op2keysAmount} keys for op1 (on behalf op2 manager)...`)
await ethers.getImpersonatedSigner(MANAGER_2)
keys = genKeys(op2keysAmount)
await trgApp.addSigningKeys(1, op2keysAmount, keys.pubkeys, keys.sigkeys, { from: MANAGER_2, gasPrice: 0 })

log('Checking operators initial state...')
let opInfo = await trgApp.getNodeOperator(0, true)
_checkEq(
opInfo.totalAddedValidators,
op1keysAmount,
`Simulate init: NO 1 totalAddedValidators = ${op1keysAmount}`
)
_checkEq(opInfo.totalAddedValidators, op1keysAmount, `NO 1 totalAddedValidators = ${op1keysAmount}`)
opInfo = await trgApp.getNodeOperator(1, true)
_checkEq(
opInfo.totalAddedValidators,
op2keysAmount,
`Simulate init: NO 2 totalAddedValidators = ${op2keysAmount}`
)
_checkEq(opInfo.totalAddedValidators, op2keysAmount, `NO 2 totalAddedValidators = ${op2keysAmount}`)

// increase keys limit via ET
// equivalent of:
// await trgApp.setNodeOperatorStakingLimit(0, op1keysAmount, { from: easyTrackEVMScriptExecutor, gasPrice: 0 })
// await trgApp.setNodeOperatorStakingLimit(1, op2keysAmount, { from: easyTrackEVMScriptExecutor, gasPrice: 0 })

log(`Increasing operator's vetted keys limit via ET ${cy('SetVettedValidatorsLimits')} factory...`)
callData = abiCoder.encode(
// struct VettedValidatorsLimitInput {
// uint256 nodeOperatorId;
Expand All @@ -340,20 +334,14 @@ async function checkSimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid =
],
]
)
evmScript = await factories.SetVettedValidatorsLimits.createEVMScript(trustedCaller, callData, {
from: stranger,
gasPrice: 0,
})
evmScript = await factories.SetVettedValidatorsLimits.createEVMScript(easyTrackTrustedCaller, callData)
await evmExecutor.executeEVMScript(evmScript)
}

log(`Checking SimpleDVT module state in StakingRouter...`)
let summary = await trgApp.getStakingModuleSummary()
_checkEq(summary.totalDepositedValidators, 0, `Simulate init: module totalDepositedValidators = 0`)
_checkEq(
summary.depositableValidatorsCount,
keysAmount,
`Simulate init: module depositableValidatorsCount = ${keysAmount}`
)
_checkEq(summary.totalDepositedValidators, 0, `Module totalDepositedValidators = 0`)
_checkEq(summary.depositableValidatorsCount, keysAmount, `Module depositableValidatorsCount = ${keysAmount}`)

const wqAddress = readStateAppAddress(state, 'withdrawalQueueERC721')
const withdrwalQueue = await artifacts.require('WithdrawalQueueERC721').at(wqAddress)
Expand All @@ -362,19 +350,39 @@ async function checkSimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid =
const ethToDeposit = toBN(ETH(32 * depositsCount))
let depositableEther = await lido.getDepositableEther()

log(`Depositable ETH ${yl(ethToStr(depositableEther))} ETH`)
log(`Need (${yl(ethToStr(ethToDeposit))} ETH to deposit ${yl(depositsCount)} keys`)

// simulate deposits by transfering ethers to Lido contract
if (depositableEther.lt(ethToDeposit)) {
log(`Simulating additional ETH submitting...`)
const bufferedEther = await lido.getBufferedEther()
const wqDebt = unfinalizedStETH.gt(bufferedEther) ? unfinalizedStETH.sub(bufferedEther) : toBN(0)
const ethToSubmit = ethToDeposit.add(wqDebt)
await web3.eth.sendTransaction({ value: ethToSubmit, to: lido.address, from: stranger, gasPrice: 0 })
let ethToSubmit = ethToDeposit.add(wqDebt)

let i = 0
const minBalance = toBN(ETH(1))
while (!ethToSubmit.isZero() && i < strangers.length) {
const balance = toBN(await web3.eth.getBalance(strangers[i]))
if (balance.gt(minBalance)) {
let ethToTransfer = balance.sub(minBalance)
if (ethToTransfer.gt(ethToSubmit)) {
ethToTransfer = ethToSubmit
}
log(`- ${ethToStr(ethToTransfer)} ETH from stranger ${strangers[i]}...`)
await web3.eth.sendTransaction({ value: ethToTransfer, to: lido.address, from: strangers[i], gasPrice: 0 })
ethToSubmit = ethToSubmit.sub(ethToTransfer)
}
++i
}
}
depositableEther = await lido.getDepositableEther()

_checkEq(
depositableEther >= ethToDeposit,
depositableEther.gte(ethToDeposit),
true,
`Simulate init: enough depositable ether for ${depositsCount} keys`
`Enough depositable ${yl(ethToStr(depositableEther))} ETH to` +
` deposit ${yl(depositsCount)} keys (${yl(ethToStr(ethToDeposit))} ETH)`
)

// get max deposits count from SR (according targetShare value)
Expand All @@ -384,7 +392,7 @@ async function checkSimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid =
// SimpleDVT module id = 2
const maxDepositsCount2 = (await stakingRouter.getStakingModuleMaxDepositsCount(2, ethToDeposit)).toNumber()

log(`Depositing ${depositsCount} keys ..`)
log(`Depositing ${depositsCount} keys (on behalf DSM)..`)
const trgModuleId = 2 // sr module id
await ethers.getImpersonatedSigner(dsmAddress)
await lido.deposit(depositsCount, trgModuleId, '0x', {
Expand All @@ -394,34 +402,35 @@ async function checkSimpleDVT({ web3, artifacts, trgAppName = APP_TRG, ipfsCid =
await ethers.provider.send('evm_increaseTime', [600])
await ethers.provider.send('evm_mine')

log(`Checking SimpleDVT module new state in StakingRouter...`)
summary = await trgApp.getStakingModuleSummary()
_checkEq(
summary.totalDepositedValidators,
maxDepositsCount2,
`Simulate deposited: summary totalDepositedValidators = ${maxDepositsCount2}`
`Summary totalDepositedValidators = ${maxDepositsCount2}`
)
_checkEq(
summary.depositableValidatorsCount,
keysAmount - maxDepositsCount2,
`Simulate deposited: summary depositableValidatorsCount = ${keysAmount - maxDepositsCount2}`
`Summary depositableValidatorsCount = ${keysAmount - maxDepositsCount2}`
)

// as only 2 ops in module and each has 0 deposited keys before
const depositedKeysPerOp = maxDepositsCount2 / 2
const op1 = await trgApp.getNodeOperator(0, false)
_checkEq(op1.totalAddedValidators, op1keysAmount, `Simulate op1 state: totalAddedValidators = 100`)
_checkEq(op1.totalAddedValidators, op1keysAmount, `op1 state: totalAddedValidators = 100`)
_checkEq(
op1.totalDepositedValidators,
depositedKeysPerOp,
`Simulate op1 state: totalDepositedValidators = ${depositedKeysPerOp}`
`op1 state: totalDepositedValidators = ${depositedKeysPerOp}`
)

const op2 = await trgApp.getNodeOperator(1, false)
_checkEq(op2.totalAddedValidators, op2keysAmount, `Simulate op2 state: totalAddedValidators = 50`)
_checkEq(op2.totalAddedValidators, op2keysAmount, `op2 state: totalAddedValidators = 50`)
_checkEq(
op2.totalDepositedValidators,
depositedKeysPerOp,
`Simulate op2 state: totalDepositedValidators = ${depositedKeysPerOp}`
`op2 state: totalDepositedValidators = ${depositedKeysPerOp}`
)
} finally {
log('Reverting snapshot...')
Expand Down
Loading

0 comments on commit ce07567

Please sign in to comment.