Compare commits
3 Commits
77b361d8a5
...
7f0433bd33
Author | SHA1 | Date | |
---|---|---|---|
7f0433bd33 | |||
2031afdbe8 | |||
195840d678 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,7 +4,7 @@ out/
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
# Ignores development broadcast logs
|
# Ignores development broadcast logs
|
||||||
!/broadcast
|
/broadcast
|
||||||
/broadcast/*/31337/
|
/broadcast/*/31337/
|
||||||
/broadcast/**/dry-run/
|
/broadcast/**/dry-run/
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@proprietary/=test/proprietary/
|
@proprietary/=src/proprietary/
|
||||||
@interfaces/=test/interfaces/
|
@interfaces/=test/interfaces/
|
||||||
@root/=src/
|
@root/=src/
|
||||||
@forge-std/=lib/forge-std/src/
|
@forge-std/=lib/forge-std/src/
|
||||||
|
34
script/DeployScript.sol
Normal file
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 _governanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
||||||
address constant _governanceVaultAddress = 0x2F50508a8a3D323B91336FA3eA6ae50E55f32185;
|
address constant _governanceVaultAddress = 0x2F50508a8a3D323B91336FA3eA6ae50E55f32185;
|
||||||
address constant _tokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
address constant _tokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
||||||
|
address constant _feeManagerAddress = 0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7;
|
||||||
|
address constant _ensAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
|
||||||
|
address constant _relayerRegistryAddress = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
|
||||||
|
|
||||||
// Information about token
|
// Information about token
|
||||||
uint256 constant _tornMaximumSupply = 10_000_000;
|
uint256 constant _tornMaximumSupply = 10_000_000;
|
@ -3,115 +3,76 @@
|
|||||||
pragma solidity ^0.6.12;
|
pragma solidity ^0.6.12;
|
||||||
pragma experimental ABIEncoderV2;
|
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 { LoopbackProxy } from "../v1/LoopbackProxy.sol";
|
||||||
import { AdminUpgradeableProxy } from "./AdminUpgradeableProxy.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 { GovernancePatchUpgrade } from "./GovernancePatchUpgrade.sol";
|
||||||
import { TornadoStakingRewards } from "./TornadoStakingRewards.sol";
|
import { TornadoStakingRewards } from "./TornadoStakingRewards.sol";
|
||||||
import { RelayerRegistry } from "./RelayerRegistry.sol";
|
import { RelayerRegistry } from "./RelayerRegistry.sol";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Contract which should help the proposal deploy the necessary contracts.
|
* @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 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.
|
|
||||||
*/
|
*/
|
||||||
contract PatchProposal {
|
contract PatchProposal {
|
||||||
using SafeMath for uint256;
|
// Address of the old staking proxy
|
||||||
using Address for address;
|
address public constant oldStakingProxyAddress = 0x2FC93484614a34f26F7970CBB94615bA109BB4bf;
|
||||||
|
|
||||||
address public immutable feeManagerProxyAddress = 0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7;
|
// Address of the registry proxy
|
||||||
address public immutable registryProxyAddress = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
|
address public constant registryProxyAddress = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
|
||||||
address public immutable ensAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
|
|
||||||
|
|
||||||
|
// 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);
|
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 {
|
// The registry implementation (with same code) that we've deployed
|
||||||
patchProposalContractsFactory = PatchProposalContractsFactory(_patchProposalContractsFactory);
|
address public immutable deployedRelayerRegistryImplementationAddress;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
address _deployedStakingProxyContractAddress,
|
||||||
|
address _deployedRelayerRegistryImplementationAddress
|
||||||
|
) public {
|
||||||
|
deployedStakingProxyContractAddress = _deployedStakingProxyContractAddress;
|
||||||
|
deployedRelayerRegistryImplementationAddress = _deployedRelayerRegistryImplementationAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Function to execute the proposal.
|
/// @notice Function to execute the proposal.
|
||||||
function executeProposal() external {
|
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
|
// Get the old staking contract
|
||||||
TornadoStakingRewards oldStaking =
|
TornadoStakingRewards oldStaking = TornadoStakingRewards(oldStakingProxyAddress);
|
||||||
TornadoStakingRewards(address(GovernancePatchUpgrade(governance).Staking()));
|
|
||||||
|
|
||||||
// Get the small amount of TORN left
|
// Get the small amount of TORN left
|
||||||
oldStaking.withdrawTorn(TORN.balanceOf(address(oldStaking)));
|
oldStaking.withdrawTorn(TORN.balanceOf(address(oldStaking)));
|
||||||
|
|
||||||
// And create a new staking logic contract
|
// Upgrade the registry proxy
|
||||||
TornadoStakingRewards newStakingImplementation = TornadoStakingRewards(
|
AdminUpgradeableProxy(payable(registryProxyAddress)).upgradeTo(
|
||||||
patchProposalContractsFactory.createStakingRewards(
|
deployedRelayerRegistryImplementationAddress
|
||||||
address(governance), address(TORN), registryProxyAddress
|
);
|
||||||
|
|
||||||
|
// 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)
|
// Transfer TORN in compensation to the staking proxy
|
||||||
bytes memory empty;
|
TORN.transfer(deployedStakingProxyContractAddress, 94_092 ether);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
pragma solidity ^0.6.12;
|
pragma solidity ^0.6.12;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import { Parameters } from "@proprietary/Parameters.sol";
|
|
||||||
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.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 { 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 { ProposalUtils } from "./ProposalUtils.sol";
|
||||||
|
|
||||||
import { Test } from "@forge-std/Test.sol";
|
import { Test } from "@forge-std/Test.sol";
|
||||||
|
|
||||||
contract MockProposal is Parameters, Test, ProposalUtils {
|
contract MockProposal is Test, ProposalUtils {
|
||||||
modifier executeCurrentProposalBefore() {
|
modifier executeCurrentProposalBefore() {
|
||||||
createAndExecuteProposal();
|
createAndExecuteProposal();
|
||||||
_;
|
_;
|
||||||
@ -23,8 +24,20 @@ contract MockProposal is Parameters, Test, ProposalUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createAndExecuteProposal() public {
|
function createAndExecuteProposal() public {
|
||||||
address patchProposalFactoryAddress = address(new PatchProposalContractsFactory());
|
TornadoStakingRewards governanceStakingImplementation =
|
||||||
address proposalAddress = address(new PatchProposal(patchProposalFactoryAddress));
|
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);
|
proposeAndExecute(proposalAddress);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user