# Relayer Registry V2 **[Repository](https://github.com/h-ivor/tornado-relayer-registry)** --------- ### **Hot topics** - How to handle updateFees, specifically: - Should we compensate both relayers and stakers? - Should we only compensate stakers? - Time period between updateFees for compensations? - Checking security of StakingContract and its influence on the gov upgrade. - Note that DataManager contract is deployed as a Contract due to original idea to have it deployed as one. - should I keep it deployed as proxy to keep logic modular? (price logic) - i can also think about deploying other contracts behind proxies, for example the TornadoProxy, so: - Potentially think about deploying tornadoproxy behind proxy this time to keep it modular? It is a core contract and might be better of immutable although we will have to always keep disabling instances and alike. - Increasing the cardinality (storage space) of uniswap v3 price oracles. Should we increase and how much? I found 5400 seconds to be a safe bet for taking price data. I will try increasing them myself soon. - Look to get discussion started on the topic of tokenomics with the community. #### **Distinctions from Synthetix StakingRewards and risk** - Synthetix staking issues ERC20 shares which are not necessary for our usecase. - If used, would have to be either modified or we would lose functionality of being able to let a person either lock and harvest their reward (by locking the extra into gov). - Logic used to calculate rewards is similar to Synthetix: - The contract keeps store of the **accumulated** amount of torn per locked torn staked in governance. - When relayer stakes governance notes down how much relayer staked and timestamp, updates above like with unlock / lock, keeps track to reduce rewards once the period is over and credits in the meantime - ```amount``` for any un/lock functions is not referenced until after canon logic of former upgrade executes, if an amount is specified which would overflow, it overflows in canon logic and reverts - when adding stake function reverts immediately to check on transferFrom - no external functions of non-trusted contracts can be called from staking contract ### **RelayerRegistry Contract** - has mapping from relayer node (bytes32) to balance and other metadata - anyone can stake to a registered relayer, registration ahs min torn amount set by governance - burn function only callable by proxy, auto reverts on insufficient balance due to safemath - has getters for fee and registration boolean - nullify balance of relayer by governance possible ### **RelayerRegistryData Contract** - holds mappings from poolId (uint256) to all pool data necessary (uni identifier, instance address, torn fee) - updateFees() -> update fees according to below specified logic - having a couple of problems when running tests repeatedly from latest block, in ~20% of tests despite low globally specified time period throwing stating that the oldest record is younger than the period -> will have to work around hopefully increasing cardinality will help - example: ETH 10 pool. poolAmount = 10e18 | price = ETH/TORN ~ 0.02 | protocolFee = 0.1 | result = poolAmount / price * protocolFee - governance can set global period to use and protocol fee - contract is not upgradeable - also holds mapping from pool addresses to ids ### **RegistryDataManager Contract** - Upgradeable contract which has logic to update fees per tornado instance (called pool in code); - Hardcoded: torn address + 1% fee of pool (aka pool identifier) from which to take price - Uniswap logic is linked from UniswapV3OracleHelper library, this is externally linked right now, but I can also write this as internal functions (change vis) ### **TornadoStakingRewards contract** - should distribute relayer-staked TORN to owners of governance-locked TORN - main concern are flashloan attacks (next to others such as reentrancy etc.) - needs some kind of time keeping to protect against these attacks - best option: take time locked dt by upgrading governance and record for each user, automatically distribute torn on lock and unlock, so: - user locks: start recording timexamount locked, check if time has already been started recording (if user locks, then locks (lock 0 as harvest)) if so compensate for dt and add it to user time locked in total and add harvested to locked balance - user unlocks: update recording and add TORN to withdrawn - also claim function in staking rewards contract - above logic should be all delegated to staking rewards contract and only called from governance on unlock and lock - should not interfere with vault - track amount of total locked and use this for calculation of shares (comes hand in hand with vault for a couple of reasons) ### Examples ![](https://i.imgur.com/AyicWKi.png) # OLD OLD #### Relayer registry 1. Deploy new Token: TornadoCash Withdrawal Ticket(TCWT) as ERC20 token. - Supply dependent on TORN, total supply dynamic, total supply lower than TORN most likely (unless very cheap). 2. Swap Contract. Accepts TORN, mints TCWT. Price is set by governance. TORN is transferred to governance (pls check bottom where questions are) 3. RelayerRegistry contract: - Accepts TCWT Token. Relayer has to stake that token in order to register. - Has to have timelock on withdraw. - For every new relayer it deploys a withdrawal splitter contract thru a factory where relayer specifies where to receive payouts. - On every relayer withdraw, it should burn TCWT owned by a relayer (check withdraw function, make relayer prove to registry withdraw succeeded). - - Anyone can stake for a relayer. - ~~Option: Instead of revert, make 100% fee go to governance if no TCWT?~~ 4. SplitReward contract: Simple. It basically has 1 function to split fee reward. One part goes to relayer, second part goes to governance. The ratio by default is set 100% to relayer, 0% to governance. - The fee should be set by governance and readable in contract if governance decides to take protocol fee. ## Q Zone / If anyone has questions (mostly ivor) post here Q/A * 1./2. Contracts are pretty alike, example: WETH Contract handles deposits/withdrawals by itself, possibly combine 1/2 into same contract? ok # Pricing Protocol fee should be around 0.1% in dollar equivalent. So we need to make a table how much torn the fee will be for each pool.