tornado-contracts/contracts/Governance/Testnet/TestnetFeeManager.sol
2024-03-29 21:52:45 +00:00

84 lines
3.0 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import { FeeManager, IERC20, ITornadoInstance, UniswapV3OracleHelper } from "../FeeManager.sol";
import { OwnableLibrary } from "../libraries/OwnableLibrary.sol";
/**
* @dev Stores and returns overrided TORN-Token price
Literally you don't need to do this unless you don't want to occupy another storage slot for the contract
*/
library TokenPriceLibrary {
struct PriceStorage {
mapping(address => uint256) _prices;
}
bytes32 private constant PriceStorageLocation = keccak256(abi.encode(uint256(keccak256("tornado.storage.price"))));
function _getPriceStorage() private pure returns (PriceStorage storage pointer) {
bytes32 slot = PriceStorageLocation;
assembly {
pointer_slot := slot
}
}
function setPrice(address _token, uint256 _price) internal {
PriceStorage storage priceStorage = _getPriceStorage();
priceStorage._prices[_token] = _price;
}
function getPrice(address _token) internal view returns (uint256 price) {
PriceStorage storage priceStorage = _getPriceStorage();
price = priceStorage._prices[_token];
}
}
/**
* @dev A testnet feeManager that the maintainer could override V3 oracles, assuming it has been deployed with TestnetProxy
*/
contract TestnetFeeManager is FeeManager {
constructor(
address _torn,
address _governance,
address _registry
) public FeeManager(_torn, _governance, _registry) {}
modifier onlyOwner {
require(OwnableLibrary.getOwner() == msg.sender, "Not an owner");
_;
}
function setTokenPrice(address _token, uint256 _price) external onlyOwner {
TokenPriceLibrary.setPrice(_token, _price);
}
function getTokenPriceRatio(address _token, uint24 _uniswapPoolSwappingFee) public view returns (uint256) {
return TokenPriceLibrary.getPrice(_token) != 0
? TokenPriceLibrary.getPrice(_token)
: UniswapV3OracleHelper.getPriceRatioOfTokens(
[torn, _token],
[uniswapTornPoolSwappingFee, _uniswapPoolSwappingFee],
uniswapTimePeriod
);
}
function calculatePoolFee(ITornadoInstance _instance) public override view returns (uint160) {
(bool isERC20, IERC20 token, , uint24 uniswapPoolSwappingFee, uint32 protocolFeePercentage) = registry.instances(_instance);
if (protocolFeePercentage == 0) {
return 0;
}
token = token == IERC20(0) && !isERC20 ? IERC20(UniswapV3OracleHelper.WETH) : token; // for eth instances
uint256 tokenPriceRatio = getTokenPriceRatio(address(token), uniswapPoolSwappingFee);
return uint160(
_instance
.denomination()
.mul(UniswapV3OracleHelper.RATIO_DIVIDER)
.div(tokenPriceRatio)
.mul(uint256(protocolFeePercentage))
.div(PROTOCOL_FEE_DIVIDER)
);
}
}