Compare commits

...

3 Commits

6 changed files with 101 additions and 90 deletions

2
.gitignore vendored

@ -4,7 +4,7 @@ out/
node_modules/
# Ignores development broadcast logs
!/broadcast
/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

@ -1,4 +1,4 @@
@proprietary/=test/proprietary/
@proprietary/=src/proprietary/
@interfaces/=test/interfaces/
@root/=src/
@forge-std/=lib/forge-std/src/

34
script/DeployScript.sol Normal file

@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
import "@forge-std/Script.sol";
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
import { TornadoStakingRewards } from "@root/v4-patch/TornadoStakingRewards.sol";
import { AdminUpgradeableProxy } from "@root/v4-patch/AdminUpgradeableProxy.sol";
import { PatchProposal } from "@root/v4-patch/PatchProposal.sol";
import { Parameters } from "@proprietary/Parameters.sol";
contract DeployScript is Script, Parameters {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
TornadoStakingRewards governanceStakingImplementation =
new TornadoStakingRewards(_governanceAddress, _tokenAddress, _relayerRegistryAddress);
// We don't need initialization parameters to deploy Governance Staking Proxy contract
bytes memory empty;
AdminUpgradeableProxy governanceStakingProxy =
new AdminUpgradeableProxy(address(governanceStakingImplementation), _governanceAddress, empty);
// Deploy new relayer registry implementation after staking, because we need refer to staking proxy in registry contract
RelayerRegistry relayerRegistryImplementation =
new RelayerRegistry(_tokenAddress, _governanceAddress, _ensAddress, address(governanceStakingProxy), _feeManagerAddress);
PatchProposal patchProposal =
new PatchProposal(address(governanceStakingProxy), address(relayerRegistryImplementation));
vm.stopBroadcast();
}
}

@ -7,6 +7,9 @@ contract Parameters {
address constant _governanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
address constant _governanceVaultAddress = 0x2F50508a8a3D323B91336FA3eA6ae50E55f32185;
address constant _tokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
address constant _feeManagerAddress = 0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7;
address constant _ensAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
address constant _relayerRegistryAddress = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
// Information about token
uint256 constant _tornMaximumSupply = 10_000_000;

@ -3,115 +3,76 @@
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { LoopbackProxy } from "../v1/LoopbackProxy.sol";
import { AdminUpgradeableProxy } from "./AdminUpgradeableProxy.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { GovernancePatchUpgrade } from "./GovernancePatchUpgrade.sol";
import { TornadoStakingRewards } from "./TornadoStakingRewards.sol";
import { RelayerRegistry } from "./RelayerRegistry.sol";
/**
* @notice Contract which should help the proposal deploy the necessary contracts.
*/
contract PatchProposalContractsFactory {
/**
* @notice Create a new TornadoStakingRewards contract.
* @param governance The address of Tornado Cash Goveranance.
* @param torn The torn token address.
* @param registry The address of the relayer registry.
* @return The address of the new staking contract.
*/
function createStakingRewards(address governance, address torn, address registry)
external
returns (address)
{
return address(new TornadoStakingRewards(governance, torn, registry));
}
/**
* @notice Create a new RelayerRegistry contract.
* @param torn The torn token address.
* @param governance The address of Tornado Cash Goveranance.
* @param ens The ens registrar address.
* @param staking The TornadoStakingRewards contract address.
* @return The address of the new registry contract.
*/
function createRegistryContract(
address torn,
address governance,
address ens,
address staking,
address feeManager
) external returns (address) {
return address(new RelayerRegistry(torn, governance, ens, staking, feeManager));
}
}
/**
* @notice Proposal which should patch governance against the metamorphic contract replacement vulnerability.
* @notice Proposal which should patch governance against the metamorphic contract replacement vulnerability and also fix several issues which have appeared as a result of the attack.
*/
contract PatchProposal {
using SafeMath for uint256;
using Address for address;
// Address of the old staking proxy
address public constant oldStakingProxyAddress = 0x2FC93484614a34f26F7970CBB94615bA109BB4bf;
address public immutable feeManagerProxyAddress = 0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7;
address public immutable registryProxyAddress = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
address public immutable ensAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
// Address of the registry proxy
address public constant registryProxyAddress = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
// Address of the gas compensation vault
address public constant gasCompensationVaultAddress = 0xFA4C1f3f7D5dd7c12a9Adb82Cd7dDA542E3d59ef;
// Address of the user vault
address public constant userVaultAddress = 0x2F50508a8a3D323B91336FA3eA6ae50E55f32185;
// Address of the governance proxy
address payable public constant governanceProxyAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
// Torn token
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
PatchProposalContractsFactory public immutable patchProposalContractsFactory;
// The staking proxy (pointing to a new implementation (with same code)) that we've deployed
address public immutable deployedStakingProxyContractAddress;
constructor(address _patchProposalContractsFactory) public {
patchProposalContractsFactory = PatchProposalContractsFactory(_patchProposalContractsFactory);
// The registry implementation (with same code) that we've deployed
address public immutable deployedRelayerRegistryImplementationAddress;
constructor(
address _deployedStakingProxyContractAddress,
address _deployedRelayerRegistryImplementationAddress
) public {
deployedStakingProxyContractAddress = _deployedStakingProxyContractAddress;
deployedRelayerRegistryImplementationAddress = _deployedRelayerRegistryImplementationAddress;
}
/// @notice Function to execute the proposal.
function executeProposal() external {
// address(this) has to be governance
address payable governance = payable(address(this));
// Get the two contracts gov depends on
address gasComp = address(GovernancePatchUpgrade(governance).gasCompensationVault());
address vault = address(GovernancePatchUpgrade(governance).userVault());
// Get the old staking contract
TornadoStakingRewards oldStaking =
TornadoStakingRewards(address(GovernancePatchUpgrade(governance).Staking()));
TornadoStakingRewards oldStaking = TornadoStakingRewards(oldStakingProxyAddress);
// Get the small amount of TORN left
oldStaking.withdrawTorn(TORN.balanceOf(address(oldStaking)));
// And create a new staking logic contract
TornadoStakingRewards newStakingImplementation = TornadoStakingRewards(
patchProposalContractsFactory.createStakingRewards(
address(governance), address(TORN), registryProxyAddress
// Upgrade the registry proxy
AdminUpgradeableProxy(payable(registryProxyAddress)).upgradeTo(
deployedRelayerRegistryImplementationAddress
);
// Now upgrade the governance implementation to the vulnerability resistant one
LoopbackProxy(governanceProxyAddress).upgradeTo(
address(
new GovernancePatchUpgrade(
deployedStakingProxyContractAddress,
gasCompensationVaultAddress,
userVaultAddress
)
)
);
// Create new staking proxy contract (without initialization value)
bytes memory empty;
address newStaking =
address(new AdminUpgradeableProxy(address(newStakingImplementation), address(governance), empty));
// And a new registry implementation
address newRegistryImplementationAddress = patchProposalContractsFactory.createRegistryContract(
address(TORN), address(governance), ensAddress, newStaking, feeManagerProxyAddress
);
// Upgrade the registry proxy
AdminUpgradeableProxy(payable(registryProxyAddress)).upgradeTo(newRegistryImplementationAddress);
// Now upgrade the governance to the latest stuff
LoopbackProxy(payable(governance)).upgradeTo(
address(new GovernancePatchUpgrade(newStaking, gasComp, vault))
);
// Compensate TORN for staking
TORN.transfer(newStaking, 94_092 ether);
// Transfer TORN in compensation to the staking proxy
TORN.transfer(deployedStakingProxyContractAddress, 94_092 ether);
}
}

@ -2,15 +2,16 @@
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import { Parameters } from "@proprietary/Parameters.sol";
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol";
import { PatchProposal, PatchProposalContractsFactory } from "@root/v4-patch/PatchProposal.sol";
import { PatchProposal } from "@root/v4-patch/PatchProposal.sol";
import { TornadoStakingRewards } from "@root/v4-patch/TornadoStakingRewards.sol";
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
import { AdminUpgradeableProxy } from "@root/v4-patch/AdminUpgradeableProxy.sol";
import { ProposalUtils } from "./ProposalUtils.sol";
import { Test } from "@forge-std/Test.sol";
contract MockProposal is Parameters, Test, ProposalUtils {
contract MockProposal is Test, ProposalUtils {
modifier executeCurrentProposalBefore() {
createAndExecuteProposal();
_;
@ -23,8 +24,20 @@ contract MockProposal is Parameters, Test, ProposalUtils {
}
function createAndExecuteProposal() public {
address patchProposalFactoryAddress = address(new PatchProposalContractsFactory());
address proposalAddress = address(new PatchProposal(patchProposalFactoryAddress));
TornadoStakingRewards governanceStakingImplementation =
new TornadoStakingRewards(_governanceAddress, _tokenAddress, _relayerRegistryAddress);
// We don't need initialization parameters to deploy Governance Staking Proxy contract
bytes memory empty;
AdminUpgradeableProxy governanceStakingProxy =
new AdminUpgradeableProxy(address(governanceStakingImplementation), _governanceAddress, empty);
RelayerRegistry relayerRegistryImplementation =
new RelayerRegistry(_tokenAddress, _governanceAddress, _ensAddress, address(governanceStakingProxy), _feeManagerAddress);
address proposalAddress = address(
new PatchProposal(address(governanceStakingProxy), address(relayerRegistryImplementation))
);
proposeAndExecute(proposalAddress);
}