Mostly finalize design
Signed-off-by: AlienTornadosaurusHex <>
This commit is contained in:
parent
7d6749a6f6
commit
c11658265c
@ -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
|
||||
|
31
src/v2/libraries/ENSResolver.sol
Normal file
31
src/v2/libraries/ENSResolver.sol
Normal file
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user