diff --git a/.env.example b/.env.example index 39dfdf3..dd83bd4 100644 --- a/.env.example +++ b/.env.example @@ -5,4 +5,4 @@ LATEST_BLOCK=false # For deploying the proposal REGISTRY_IMPL_ADDRESS= -STAKING_ADDRESS= \ No newline at end of file +STAKING_PROXY_ADDRESS= \ No newline at end of file diff --git a/config.js b/config.js index fcf03ba..6083551 100644 --- a/config.js +++ b/config.js @@ -4,7 +4,6 @@ module.exports = { tornWhale: '0xF977814e90dA44bFA03b6295A0616a897441aceC', ens: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', feeManager: '0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7', - staking: '0x2FC93484614a34f26F7970CBB94615bA109BB4bf', registry: '0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2', compensations: '0xFA4C1f3f7D5dd7c12a9Adb82Cd7dDA542E3d59ef', vault: '0x2F50508a8a3D323B91336FA3eA6ae50E55f32185', diff --git a/contracts/v4-patch/PatchProposal.sol b/contracts/v4-patch/PatchProposal.sol index db063e4..43808a6 100644 --- a/contracts/v4-patch/PatchProposal.sol +++ b/contracts/v4-patch/PatchProposal.sol @@ -12,10 +12,6 @@ import { GovernancePatchUpgrade } from "./GovernancePatchUpgrade.sol"; import { TornadoStakingRewards } from "./TornadoStakingRewards.sol"; import { RelayerRegistry } from "./RelayerRegistry.sol"; -interface Proxy { - function upgradeTo(address newImplementation) external; -} - /** * @notice Proposal which should patch governance against the metamorphic contract replacement vulnerability. */ @@ -39,13 +35,14 @@ contract PatchProposal { IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C); // These are the contracts we deployed - address public immutable deployedStakingContractAddress; + address public immutable deployedStakingProxyContractAddress; address public immutable deployedRelayerRegistryImplementationAddress; - constructor(address _deployedStakingContractAddress, address _deployedRelayerRegistryImplementationAddress) - public - { - deployedStakingContractAddress = _deployedStakingContractAddress; + constructor( + address _deployedStakingProxyContractAddress, + address _deployedRelayerRegistryImplementationAddress + ) public { + deployedStakingProxyContractAddress = _deployedStakingProxyContractAddress; deployedRelayerRegistryImplementationAddress = _deployedRelayerRegistryImplementationAddress; } @@ -57,23 +54,23 @@ contract PatchProposal { // Get the small amount of TORN left oldStaking.withdrawTorn(TORN.balanceOf(address(oldStaking))); - // Just to make compiler stfu - bytes memory bempty; - - // And create a new staking contract proxy - TornadoStakingRewards newStaking = TornadoStakingRewards( - address(new AdminUpgradeableProxy(deployedStakingContractAddress, governanceProxyAddress, bempty)) - ); - // Upgrade the registry proxy - Proxy(registryProxyAddress).upgradeTo(deployedRelayerRegistryImplementationAddress); + AdminUpgradeableProxy(payable(registryProxyAddress)).upgradeTo( + deployedRelayerRegistryImplementationAddress + ); // Now upgrade the governance to the latest stuff LoopbackProxy(governanceProxyAddress).upgradeTo( - address(new GovernancePatchUpgrade(address(newStaking), gasCompensationVaultAddress, userVaultAddress)) + address( + new GovernancePatchUpgrade( + deployedStakingProxyContractAddress, + gasCompensationVaultAddress, + userVaultAddress + ) + ) ); // Transfer TORN in compensation to the staking proxy - TORN.transfer(address(newStaking), 94_092 ether); + TORN.transfer(deployedStakingProxyContractAddress, 94_092 ether); } } diff --git a/deploy/deployPatch.js b/deploy/deployPatch.js index bf4e923..f73c51c 100644 --- a/deploy/deployPatch.js +++ b/deploy/deployPatch.js @@ -39,11 +39,11 @@ const promptMessageBase = (middle) => `\n${middle}\n\nAre you sure you would lik async function deploy() { const signer = await ethers.getSigner() - if (process.env.STAKING_ADDRESS === undefined) throw Error('Missing STAKING_ADDRESS.') + if (process.env.STAKING_PROXY_ADDRESS === undefined) throw Error('Missing STAKING_PROXY_ADDRESS.') if (process.env.REGISTRY_IMPL_ADDRESS === undefined) throw Error('Missing REGISTRY_IMPL_ADDRESS.') - const stakingAddress = `${process.env.STAKING_ADDRESS}` + const stakingProxyAddress = `${process.env.STAKING_PROXY_ADDRESS}` const registryImplementationAddress = `${process.env.REGISTRY_IMPL_ADDRESS}` @@ -52,7 +52,7 @@ async function deploy() { let patchProposal if (await prompt(promptMessageBase('Continuing to PatchProposal deployment.'))) { - patchProposal = await patchProposalDeployer.deploy(stakingAddress, registryImplementationAddress) + patchProposal = await patchProposalDeployer.deploy(stakingProxyAddress, registryImplementationAddress) console.log(deployedMessage('PatchProposal', 1, patchProposal.address)) } else { return '\nDecided to stop at PatchProposal deployment.\n' @@ -61,7 +61,7 @@ async function deploy() { if (await prompt(promptMessageBase('Continuing to contract verification.'))) { await hre.run('verify:verify', { address: patchProposal.address, - constructorArguments: [stakingAddress, registryImplementationAddress], + constructorArguments: [stakingProxyAddress, registryImplementationAddress], }) console.log(verifiedMessage('PatchProposal')) diff --git a/deploy/deployRegistryImplementation.js b/deploy/deployRegistryImplementation.js index 1116fe8..d52d5e5 100644 --- a/deploy/deployRegistryImplementation.js +++ b/deploy/deployRegistryImplementation.js @@ -41,6 +41,10 @@ const promptMessageBase = (middle) => `\n${middle}\n\nAre you sure you would lik async function deploy() { const signer = await ethers.getSigner() + if (process.env.STAKING_PROXY_ADDRESS === undefined) throw Error('Missing STAKING_PROXY_ADDRESS.') + + const stakingProxyAddress = `${process.env.STAKING_PROXY_ADDRESS}` + const registryImplementationDeployer = (await ethers.getContractFactory('RelayerRegistry')).connect(signer) let registry @@ -50,7 +54,7 @@ async function deploy() { config.TORN, config.governance, config.ens, - config.staking, + stakingProxyAddress, config.feeManager, ) console.log(deployedMessage('RelayerRegistry (Implementation)', 1, registry.address)) @@ -61,7 +65,13 @@ async function deploy() { if (await prompt(promptMessageBase('Continuing to contract verification.'))) { await hre.run('verify:verify', { address: registry.address, - constructorArguments: [config.TORN, config.governance, config.ens, config.staking, config.feeManager], + constructorArguments: [ + config.TORN, + config.governance, + config.ens, + stakingProxyAddress, + config.feeManager, + ], }) console.log(verifiedMessage('RelayerRegistry (Implementation)')) } else { diff --git a/deploy/deployStaking.js b/deploy/deployStaking.js index f81dbc2..7c409c2 100644 --- a/deploy/deployStaking.js +++ b/deploy/deployStaking.js @@ -42,22 +42,40 @@ async function deploy() { const signer = await ethers.getSigner() const stakingDeployer = (await ethers.getContractFactory('TornadoStakingRewards')).connect(signer) + const proxyDeployer = (await ethers.getContractFactory('AdminUpgradeableProxy')).connect(signer) - let staking + let impl, proxy - if (await prompt(promptMessageBase('Continuing to TornadoStakingRewards deployment.'))) { - staking = await stakingDeployer.deploy(config.governance, config.TORN, config.registry) - console.log(deployedMessage('TornadoStakingRewards', 1, staking.address)) + if (await prompt(promptMessageBase('Continuing to TornadoStakingRewards (Implementation) deployment.'))) { + impl = await stakingDeployer.deploy(config.governance, config.TORN, config.registry) + console.log(deployedMessage('TornadoStakingRewards (Implementation)', 1, impl.address)) } else { - return '\nDecided to stop at TornadoStakingRewards deployment.\n' + return '\nDecided to stop at TornadoStakingRewards (Implementation) deployment.\n' + } + + if (await prompt(promptMessageBase('Continuing to Staking Proxy deployment.'))) { + proxy = await proxyDeployer.deploy(impl.address, governance.address, []) + console.log(deployedMessage('Staking Proxy', 1, proxy.address)) + } else { + return '\nDecided to stop at Staking Proxy deployment.\n' } if (await prompt(promptMessageBase('Continuing to contract verification.'))) { await hre.run('verify:verify', { - address: staking.address, + address: impl.address, constructorArguments: [config.governance, config.TORN, config.registry], }) - console.log(verifiedMessage('TornadoStakingRewards')) + + console.log(verifiedMessage('TornadoStakingRewards (Implementation)')) + console.log('\nWaiting 5 seconds.\n') + await timeout(5) + + await hre.run('verify:verify', { + address: proxy.address, + constructorArguments: [impl.address, governance.address, []], + }) + + console.log(verifiedMessage('Staking Proxy')) } else { return '\nDecided to stop at contract verification.\n' } diff --git a/test/patch/patch.test.js b/test/patch/patch.test.js index a0fb8f8..a8b3bab 100644 --- a/test/patch/patch.test.js +++ b/test/patch/patch.test.js @@ -56,6 +56,7 @@ describe('Gov Exploit Patch Upgrade Tests', () => { let registryDeployer let stakingDeployer + let proxyDeployer let proposerBalanceInitial @@ -141,6 +142,7 @@ describe('Gov Exploit Patch Upgrade Tests', () => { maliciousProposalDeployer = await ethers.getContractFactory('MaliciousProposal') stakingDeployer = await ethers.getContractFactory('TornadoStakingRewards') + proxyDeployer = await ethers.getContractFactory('AdminUpgradeableProxy') registryDeployer = await ethers.getContractFactory('RelayerRegistry') proposalDeployer = await ethers.getContractFactory('PatchProposal') @@ -156,11 +158,13 @@ describe('Gov Exploit Patch Upgrade Tests', () => { staking = await stakingDeployer.deploy(config.governance, config.TORN, config.registry) + staking = await proxyDeployer.deploy(staking.address, governance.address, []) + registryImplementation = await registryDeployer.deploy( config.TORN, config.governance, config.ens, - config.staking, + staking.address, config.feeManager, )