Mostly finalize design

Signed-off-by: AlienTornadosaurusHex <>
This commit is contained in:
AlienTornadosaurusHex 2023-06-20 12:47:48 +00:00
parent 7d6749a6f6
commit c11658265c
8 changed files with 118 additions and 205 deletions

@ -31,7 +31,7 @@ import { TornadoRouter } from "../v2/TornadoRouter.sol";
* registry such that multiple oracles can be used and so the DAO can add more instances.
*/
contract InfrastructureUpgradeProposal {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ADDRESSES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* @dev The address of the current FeeManager proxy, future FeeOracleManager */
address payable public constant feeManagerProxyAddress = 0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7;
@ -45,9 +45,6 @@ contract InfrastructureUpgradeProposal {
/* @dev The address of the current TornadoStakingRewards proxy, this will be upgraded */
address payable public constant stakingProxyAddress = 0x5B3f656C80E8ddb9ec01Dd9018815576E9238c29;
/* @dev The ENS resolver address */
address public constant ensAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
/* @dev This is the Uniswap Oracle which we will use for all of our traditional instances, but it will
also help the CurveFeeOracle, the former must have been deployed witht the address of this */
address public immutable deployedUniswapFeeOracleAddress;
@ -108,12 +105,7 @@ contract InfrastructureUpgradeProposal {
// Initialize V2
RelayerRegistry(relayerRegistryProxyAddress).initialize(
ensAddress,
deployedTornadoRouterAddress,
feeManagerProxyAddress,
stakingProxyAddress,
bytes20(uint160(2000 ether)),
5000
deployedTornadoRouterAddress, stakingProxyAddress, bytes20(_getMinimumStakeAmount())
);
// Upgrade TornadoStakingRewards (V1) Proxy to TornadoStakingRewards (V2)
@ -135,6 +127,7 @@ contract InfrastructureUpgradeProposal {
FeeOracleManager(feeManagerProxyAddress).initialize(
deployedUniswapFeeOracleAddress,
instanceRegistryProxyAddress,
_getTWAPUpdateInterval(),
_getAllInstances(),
_getAllInstanceFeePercents()
);
@ -217,6 +210,16 @@ contract InfrastructureUpgradeProposal {
_uniswapFeeOracle.setPoolFeeForToken(wbtc, uint24(0xbb8));
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PARAMETERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
function _getMinimumStakeAmount() internal pure returns (uint160) {
return 2000 ether;
}
function _getTWAPUpdateInterval() internal pure returns (uint32) {
return 6 hours;
}
function _getAllInstances() internal pure returns (ITornadoInstance[] memory _addresses) {
_addresses = new ITornadoInstance[](17);

@ -123,7 +123,7 @@ contract FeeOracleManager is FeeManagerLegacyStorage, Initializable {
}
function version() public pure virtual returns (string memory) {
return "v2-slashing-and-oracles";
return "v2-oracle-manager";
}
/**
@ -133,6 +133,7 @@ contract FeeOracleManager is FeeManagerLegacyStorage, Initializable {
function initialize(
address _uniswapFeeOracle,
address _instanceRegistryAddress,
uint32 _feeUpdateInterval,
ITornadoInstance[] memory _instances,
uint256[] memory _percents
) external onlyGovernance initializer {
@ -147,7 +148,7 @@ contract FeeOracleManager is FeeManagerLegacyStorage, Initializable {
feesByInstance[instance] = FeeData({
amount: _oldFeesForInstance[instance],
percent: uint32(_percents[i]),
updateInterval: 6 hours, // TODO: Bubble this up to proposal
updateInterval: _feeUpdateInterval,
lastUpdateTime: uint32(_oldFeesForInstanceUpdateTime[instance])
});

@ -130,7 +130,7 @@ contract InstanceRegistry is InstanceRegistryLegacyStorage, EnsResolve, Initiali
}
function version() public pure virtual returns (string memory) {
return "v2-slashing-and-oracles";
return "v2-oracle-manager";
}
function initialize(ITornadoInstance[] memory _instances, TornadoRouter _router)

@ -14,7 +14,6 @@ import { Initializable } from "@openzeppelin/contracts/proxy/Initializable.sol";
// Tornado imports
import { TORN } from "torn-token/contracts/TORN.sol";
import { EnsResolve } from "torn-token/contracts/ENS.sol";
// Local imports
@ -22,6 +21,8 @@ import { IENS } from "./interfaces/IENS.sol";
import { ENSNamehash } from "./libraries/ENSNamehash.sol";
import { EnsResolver } from "./libraries/ENSResolver.sol";
import { TornadoStakingRewards } from "./TornadoStakingRewards.sol";
import { FeeOracleManager } from "./FeeOracleManager.sol";
@ -71,7 +72,7 @@ struct RelayerMetadata {
bytes32 node;
}
contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
contract RelayerRegistry is RegistryLegacyStorage, EnsResolver, Initializable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
@ -92,16 +93,6 @@ contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
*/
TORN public immutable torn;
/**
* @notice The ENS Registry.
*/
IENS public ens;
/**
* @notice The Fee Oracle Manager contract.
*/
FeeOracleManager public feeOracleManager;
/**
* @notice The Staking Rewards contract.
*/
@ -118,30 +109,29 @@ contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
*/
bytes20 public minStakeAmountOracle;
/**
* @notice What the kickback to stakers is on a slash
*/
uint256 public stakerKickbackBips;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EVENTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
// Contract general
event ENSUpdated(address ens);
event RouterAddressUpdated(address routerAddress);
event StakingRewardsUpdated(address stakingRewards);
event FeeOracleManagerUpdated(address feeOracleManagerAddress);
event MinimumStakingAmountOracleUpdated(bytes20 oracle, bool isContract);
event WorkerRegistered(address relayer, address worker);
event WorkerUnregistered(address relayer, address worker);
event StakeAddedToRelayer(address relayer, uint256 amountStakeAdded);
event StakeBurned(address relayer, uint256 amountBurned);
// Relayer metadata
event RelayerRegistered(string ensName, bytes32 relayer, address relayerAddress, uint256 stakedAmount);
event RelayerSlashed(
address indexed relayer, address beneficiary, uint256 slashedAmount, uint256 stakerKickbackBips
);
// Relayer Stake
event StakeAddedToRelayer(address relayer, uint256 amountStakeAdded);
event StakeBurned(address relayer, uint256 amountBurned);
// Relayers workers
event WorkerRegistered(address relayer, address worker);
event WorkerUnregistered(address relayer, address worker);
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOGIC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
constructor(address _governanceProxyAddress, address _tornTokenAddress) public {
@ -160,33 +150,27 @@ contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
}
modifier onlyRelayer(address _possibleRelayer, address _possibleWorker) {
require(isRegisteredRelayer(_possibleRelayer, _possibleWorker), "RelayerRegistry: onlyRelayer");
require(isWorkerOfRelayer(_possibleRelayer, _possibleWorker), "RelayerRegistry: onlyRelayer");
_;
}
modifier onlyENSOwner(address _relayer, bytes32 _node) {
require(_relayer == ens.owner(_node), "RelayerRegistry: onlyENSOwner");
require(_relayer == owner(_node), "RelayerRegistry: onlyENSOwner");
_;
}
function version() public pure virtual returns (string memory) {
return "v2-slashing-and-oracles";
return "v2-oracle-manager";
}
function initialize(
address _ensAddress,
address _routerAddress,
address _feeOracleManagerAddress,
address _stakingRewardsAddress,
bytes20 _minStakeAmountOracle,
uint256 _stakerKickbackBips
) public virtual initializer {
feeOracleManager = FeeOracleManager(_feeOracleManagerAddress);
function initialize(address _routerAddress, address _stakingRewardsAddress, bytes20 _minStakeAmountOracle)
public
virtual
initializer
{
routerAddress = _routerAddress;
stakingRewards = TornadoStakingRewards(_stakingRewardsAddress);
minStakeAmountOracle = _minStakeAmountOracle;
stakerKickbackBips = _stakerKickbackBips;
routerAddress = _routerAddress;
ens = IENS(_ensAddress);
}
function register(string calldata _name, uint256 _staked, address[] calldata _workers) public virtual {
@ -221,10 +205,13 @@ contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
"RelayerRegistry: already registered"
);
// Check if a sufficient amount of TORN is to be staked
require(getMinimumStakingAmount() <= _staked, "RelayerRegistry: stake too low");
// Then transfer it here
IERC20(torn).safeTransferFrom(_relayer, address(stakingRewards), _staked);
// Then store metadata ("register")
metadata[_relayer] = RelayerMetadata({ balance: _staked, node: _node });
workers[_relayer] = _relayer;
@ -251,9 +238,10 @@ contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
}
function unregisterWorker(address _worker) public virtual {
if (msg.sender != _worker) {
require(workers[_worker] == msg.sender, "RelayerRegistry: sender must own worker");
}
require(
msg.sender == _worker || isWorkerOfRelayer(msg.sender, _worker),
"RelayerRegistry: sender must own worker"
);
require(workers[_worker] != _worker, "RelayerRegistry: cant remove owner");
@ -299,31 +287,8 @@ contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
emit StakeBurned(_relayer, _burned);
}
function slashRelayer(address _beneficiary, address _relayer) public virtual onlyRouter {
// Store to reward
uint256 balToSlash = metadata[_relayer].balance;
// Slash
metadata[_relayer].balance = 0;
// We can't give the slasher the full balance because in that case the relayer will just slash himself
stakingRewards.rewardSlasher(
_beneficiary, (balToSlash * (BIP_DIVISOR - stakerKickbackBips)) / BIP_DIVISOR
);
// Give rest to Gov stakers
stakingRewards.addBurnRewards((balToSlash * stakerKickbackBips) / BIP_DIVISOR);
emit RelayerSlashed(_relayer, _beneficiary, balToSlash, stakerKickbackBips);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SETTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
function setENS(address _newENSAddress) public virtual onlyGovernance {
ens = IENS(_newENSAddress);
emit ENSUpdated(_newENSAddress);
}
function setRouterAddress(address _newRouterAddress) public virtual onlyGovernance {
routerAddress = _newRouterAddress;
emit RouterAddressUpdated(_newRouterAddress);
@ -334,22 +299,13 @@ contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
emit StakingRewardsUpdated(_newStakingRewardsAddress);
}
function setFeeOracleManager(address _newFeeOracleManagerAddress) public virtual onlyGovernance {
feeOracleManager = FeeOracleManager(_newFeeOracleManagerAddress);
emit FeeOracleManagerUpdated(_newFeeOracleManagerAddress);
}
function setMinimumStakingAmountOracle(bytes20 _newOracle, bool _isContractOracle)
public
virtual
onlyGovernance
{
bool oracleIsContract = Address.isContract(address(_newOracle));
if (_isContractOracle) {
require(oracleIsContract, "RelayerRegistry: oracle is not contract");
} else {
require(!oracleIsContract, "RelayerRegistry: oracle is contract");
}
require(_isContractOracle == oracleIsContract, "RelayerRegistry: oracle not expected type");
minStakeAmountOracle = _newOracle;
emit MinimumStakingAmountOracleUpdated(_newOracle, oracleIsContract);
}
@ -360,7 +316,7 @@ contract RelayerRegistry is RegistryLegacyStorage, EnsResolve, Initializable {
return workers[_possibleWorker] != address(0);
}
function isRegisteredRelayer(address _possibleRelayer, address _possibleWorker)
function isWorkerOfRelayer(address _possibleRelayer, address _possibleWorker)
public
view
virtual

@ -52,11 +52,6 @@ contract TornadoRouter is Initializable {
*/
FeeOracleManager public feeOracleManager;
/**
* @notice Note down proofs for slashing relayers
*/
mapping(bytes32 => bool) public slashProofs;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EVENTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
event EncryptedNote(address indexed sender, bytes encryptedNote);
@ -87,7 +82,7 @@ contract TornadoRouter is Initializable {
}
function version() public pure virtual returns (string memory) {
return "v2-slashing-and-oracles";
return "v2-oracle-manager";
}
function initialize(
@ -127,83 +122,9 @@ contract TornadoRouter is Initializable {
}
/**
* @notice Withdrawal function for Governance relayers by which they can safely process a withdrawal
* without getting slashed (which kicks them off the frontend).
* @param _tornado The Tornado instance to withdraw from.
* @param _proof Bytes proof data.
* @param _root A current or historical bytes32 root of the Merkle Tree within the proofs context.
* @param _nullifierHash The bytes32 nullifierHash for the deposit.
* @param _recipient The address of recipient for withdrawn funds.
* @param _relayer The address of the relayer which will be making the withdrawal.
* @param _fee The fee in bips to pay the relayer.
* @param _refund If swapping into ETH on the other side, use this to specify how much should be paid for
*/
function processWithdrawAsGovernanceRelayer(
ITornadoInstance _tornado,
bytes calldata _proof,
bytes32 _root,
bytes32 _nullifierHash,
address payable _recipient,
address payable _relayer,
uint256 _fee,
uint256 _refund
) public payable virtual {
// Deduct balance immediately
relayerRegistry.deductBalance(msg.sender, _relayer, feeOracleManager.updateFee(_tornado, true));
// Then call the regular withdraw function which will make the relayer slashable
withdraw(_tornado, _proof, _root, _nullifierHash, _recipient, _relayer, _fee, _refund);
// But then undo this and get gas refund
slashProofs[keccak256(abi.encode(msg.sender, _tornado, _relayer, _nullifierHash))] = false;
}
/**
* @notice Slash a relayer by proving that there is a nullifier hash for which he has not been deducted,
* get tokens back for it.
* @dev Events are emitted when withdrawals are processed, that is how you can find hashes.
* @param _relayer The relayer to be slashed
* @param _instanceAddress The instance for which nullifier hash is valid for
* @param _nullifierHash The nullifier hash
*/
function slashRelayer(address _sender, address _relayer, address _instanceAddress, bytes32 _nullifierHash)
public
virtual
{
// Construct the proof, msg.sender can't lie about _sender, because proof will be invalid
// And _sender was withdraw msg.sender
bytes32 possibleSlashProof =
keccak256(abi.encode(_sender, _relayer, _instanceAddress, _nullifierHash));
// Proof must be valid
require(slashProofs[possibleSlashProof], "TornadoRouter: invalid proof");
// Since the proof is valid, we know the _sender is correct
// First step against multicall
require(msg.sender != _sender, "TornadoRouter: slasher is withdrawer");
// Also require the sender is not a contract, multicall could proxy over one
require(!Address.isContract(msg.sender), "TornadoRouter: sender is contract");
// Further it doesn't make sense then to really assert it's not a worker,
// since relayer could use a different account.
//
// In any case searchers and the balance not being returned in full should prevent relayers from not
// behaving well, if they are listed on the frontend
//
// Otherwise they are on their own
// Slash relayer first, it also logs the slash event
relayerRegistry.slashRelayer(msg.sender, _relayer);
// Then set this back false
slashProofs[possibleSlashProof] = false;
}
/**
* @notice Withdraw from a Tornado Instance. Note that the withdraw function is totally independent of any
* Governance contracts, that means, even if the instances demand that only Router is the caller, and the
* Governance contracts get fucked, depositors won't lose their money AND third-party relayers will still
* have the opportunity to operate. Relayers not affiliated with Governance, sorry for that one extra
* SSTORE and emit!
* @notice Withdraw from a Tornado Instance. The registry proxy will be set to 0, this will then
* guarantee that the contract is not upgradeable and thus that it will never be able to block
* withdrawals.
* @param _tornado The Tornado instance to withdraw from.
* @param _proof Bytes proof data.
* @param _root A current or historical bytes32 root of the Merkle Tree within the proofs context.
@ -224,9 +145,12 @@ contract TornadoRouter is Initializable {
uint256 _fee,
uint256 _refund
) public payable virtual {
if (_relayer != address(0)) {
slashProofs[keccak256(abi.encode(msg.sender, _relayer, address(_tornado), _nullifierHash))] = true;
emit WithdrawalWithRelayer(msg.sender, _relayer, address(_tornado), _nullifierHash);
// The registry proxy admin has been tossed meaning that below function can't be
// upgraded to break withdrawals from the instances
if (relayerRegistry.isWorker(_relayer)) {
require(relayerRegistry.isWorkerOfRelayer(_relayer, msg.sender), "TornadoRouter: invalid relayer");
require(instanceRegistry.isEnabledInstance(_tornado), "TornadoRouter: instance not enabled");
relayerRegistry.deductBalance(msg.sender, _relayer, feeOracleManager.updateFee(_tornado, true));
}
_tornado.withdraw{ value: msg.value }(
@ -279,11 +203,6 @@ contract TornadoRouter is Initializable {
emit InstanceRegistryUpdated(_newInstanceRegistryProxyAddress);
}
function setRelayerRegistry(address _newRelayerRegistryProxyAddress) external onlyGovernance {
relayerRegistry = RelayerRegistry(_newRelayerRegistryProxyAddress);
emit RelayerRegistryUpdated(_newRelayerRegistryProxyAddress);
}
function setFeeOracleManager(address _newFeeOracleManagerProxyAddress) external onlyGovernance {
feeOracleManager = FeeOracleManager(_newFeeOracleManagerProxyAddress);
emit FeeOracleManagerUpdated(_newFeeOracleManagerProxyAddress);

@ -31,11 +31,15 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
using SafeMath for uint256;
using SafeERC20 for IERC20;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IMMUTABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/// @notice 1e25
uint256 public immutable ratioConstant;
ITornadoGovernance public immutable Governance;
IERC20 public immutable torn;
address public immutable relayerRegistry;
address public immutable router;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MUTABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/// @notice the sum torn_burned_i/locked_amount_i*coefficient where i is incremented at each burn
uint256 public accumulatedRewardPerTorn;
@ -47,24 +51,26 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
event RewardsUpdated(address indexed account, uint256 rewards);
event RewardsClaimed(address indexed account, uint256 rewardsClaimed);
modifier onlyGovernance() {
require(msg.sender == address(Governance), "only governance");
_;
}
modifier onlyRelayerRegistry() {
require(msg.sender == relayerRegistry, "only relayer registry");
_;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOGIC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
// Minor code change here we won't resolve the registry by ENS
constructor(address governanceAddress, address tornAddress, address _relayerRegistry) public {
constructor(address governanceAddress, address tornAddress, address _router) public {
Governance = ITornadoGovernance(governanceAddress);
torn = IERC20(tornAddress);
relayerRegistry = _relayerRegistry;
router = _router;
ratioConstant = IERC20(tornAddress).totalSupply();
}
modifier onlyGovernance() {
require(msg.sender == address(Governance), "TornadoStakingRewards: onlyGovernance");
_;
}
modifier onlyRouter() {
require(msg.sender == router, "TornadoStakingRewards: onlyRouter");
_;
}
/**
* @notice This function should safely send a user his rewards.
* @dev IMPORTANT FUNCTION:
@ -89,7 +95,10 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
* @param amount amount to add to the rewards
*/
function addBurnRewards(uint256 amount) external {
require(msg.sender == address(Governance) || msg.sender == relayerRegistry, "unauthorized");
require(
msg.sender == address(Governance) || msg.sender == router,
"TornadoStakingRewards: only gov or router"
);
accumulatedRewardPerTorn = accumulatedRewardPerTorn.add(
amount.mul(ratioConstant).div(torn.balanceOf(address(Governance.userVault())))
);
@ -118,13 +127,6 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
torn.safeTransfer(address(Governance), amount);
}
/**
* @notice This function may be used to reward a slasher (since it is registry gated)
*/
function rewardSlasher(address _slasher, uint256 _amount) external onlyRelayerRegistry {
torn.safeTransfer(_slasher, _amount);
}
/**
* @notice This function should calculated the proper amount of rewards attributed to user since the last
* update
@ -150,6 +152,8 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
emit RewardsUpdated(account, claimed);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GETTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/**
* @notice This function should show a user his rewards.
* @param account address of account to calculate rewards for

@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
interface ENS {
function resolver(bytes32 node) external view returns (Resolver);
function owner(bytes32 node) external view returns (address);
}
interface Resolver {
function addr(bytes32 node) external view returns (address);
}
/**
* @dev The addresses below only work on Mainnet.
*/
contract EnsResolver {
address internal constant _ENS_ADDRESS = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
address internal constant _ENS_NAMEWRAPPER_ADDRESS = 0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401;
function owner(bytes32 node) public view virtual returns (address) {
ENS ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e);
address _owner = ens.owner(node);
return _owner == _ENS_NAMEWRAPPER_ADDRESS ? Resolver(_owner).addr(node) : _owner;
}
function resolve(bytes32 node) public view virtual returns (address) {
ENS ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e);
return ens.resolver(node).addr(node);
}
}

@ -140,16 +140,15 @@ contract ProposalTests is Instances, TornadoProposalTest {
curveFeeOracle.setUniswapFeeOracle(uniswapFeeOracle);
router = new TornadoRouter(address(governance));
implRegistry = new RelayerRegistry(address(governance), address(TORN));
implInstanceRegistry = new InstanceRegistry(address(governance));
implFeeOracleManager = new FeeOracleManager(address(TORN), address(governance));
implStaking =
new TornadoStakingRewards(address(governance), address(TORN), address(relayerRegistryProxyAddress));
router = new TornadoRouter(address(governance));
implStaking = new TornadoStakingRewards(address(governance), address(TORN), address(router));
_advanceTORNETHMarket();
}
@ -350,12 +349,12 @@ contract ProposalTests is Instances, TornadoProposalTest {
vm.expectRevert();
vm.prank(address(governance));
feeOracleManager.initialize(
address(uniswapFeeOracle), address(instanceRegistry), _toUpdate, feeArrayForTesting_1()
address(uniswapFeeOracle), address(instanceRegistry), 6 hours, _toUpdate, feeArrayForTesting_1()
);
vm.expectRevert();
feeOracleManager.initialize(
address(uniswapFeeOracle), address(instanceRegistry), _toUpdate, feeArrayForTesting_1()
address(uniswapFeeOracle), address(instanceRegistry), 6 hours, _toUpdate, feeArrayForTesting_1()
);
// Must not be able to re-initialize the router... the contract addresses are unimportant