Contract Name:
ConverterRegistry
Contract Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IConverterRegistry } from "./IConverterRegistry.sol";
import { ITokenConverter } from "./ITokenConverter.sol";
contract ConverterRegistry is Ownable, IConverterRegistry {
/*************
* Variables *
*************/
/// @dev Mapping from pool type to the address of converter.
mapping(uint256 => address) private converters;
/// @dev Mapping from tokenIn to tokenOut to routes.
/// @dev See {ITokenConverter-convert} for the meaning.
mapping(address => mapping(address => uint256[])) private routes;
/*************************
* Public View Functions *
*************************/
/// @inheritdoc IConverterRegistry
function getRoutes(address src, address dst) external view override returns (uint256[] memory) {
return routes[src][dst];
}
/// @inheritdoc IConverterRegistry
function getTokenPair(uint256 _route) external view override returns (address, address) {
uint256 _poolType = _route & 255;
return ITokenConverter(converters[_poolType]).getTokenPair(_route);
}
/// @inheritdoc IConverterRegistry
function getConverter(uint256 _poolType) external view override returns (address) {
return converters[_poolType];
}
/*******************************
* Public Restricted Functions *
*******************************/
/// @notice Register a converter or update the converter.
///
/// @param _poolType The pool type to update.
/// @param _newConverter The address of converter to update.
function register(uint256 _poolType, address _newConverter) external onlyOwner {
address _oldConverter = converters[_poolType];
converters[_poolType] = _newConverter;
emit UpdateConverter(_poolType, _oldConverter, _newConverter);
}
/// @notice Update the routes for converting from source token to destination token.
///
/// @param _src The address of source token.
/// @param _dst The address of destination token.
/// @param _routes The list of route encodings.
function updateRoute(
address _src,
address _dst,
uint256[] memory _routes
) external onlyOwner {
delete routes[_src][_dst];
routes[_src][_dst] = _routes;
emit UpdateRoute(_src, _dst, _routes);
}
/// @notice Withdraw dust assets from a converter contract.
/// @param _converter The address of converter contract.
/// @param _token The address of token to withdraw.
/// @param _recipient The address of token receiver.
function withdrawFund(
address _converter,
address _token,
address _recipient
) external onlyOwner {
ITokenConverter(_converter).withdrawFund(_token, _recipient);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0 || ^0.8.0;
interface IConverterRegistry {
/**********
* Events *
**********/
/// @notice Emitted when the converter route is updated.
/// @param src The address of source token.
/// @param dst The address of destination token.
/// @param routes The list of route encodings.
event UpdateRoute(address indexed src, address indexed dst, uint256[] routes);
/// @notice Emitted when the token converter is updated for some pool type.
/// @param poolType The pool type updated.
/// @param oldConverter The address of previous converter.
/// @param newConverter The address of current converter.
event UpdateConverter(uint256 indexed poolType, address indexed oldConverter, address indexed newConverter);
/*************************
* Public View Functions *
*************************/
/// @notice Return the routes used to convert source token to destination token.
/// @param src The address of source token.
/// @param dst The address of destination token.
/// @return routes The list of route encodings.
function getRoutes(address src, address dst) external view returns (uint256[] memory routes);
/// @notice Return the input token and output token for the route.
/// @param route The encoding of the route.
/// @return tokenIn The address of input token.
/// @return tokenOut The address of output token.
function getTokenPair(uint256 route) external view returns (address tokenIn, address tokenOut);
/// @notice Return the address of converter for a specific pool type.
/// @param poolType The type of converter.
/// @return converter The address of converter.
function getConverter(uint256 poolType) external view returns (address converter);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0 || ^0.8.0;
interface ITokenConverter {
/*************************
* Public View Functions *
*************************/
/// @notice The address of Converter Registry.
function registry() external view returns (address);
/// @notice Return the input token and output token for the route.
/// @param route The encoding of the route.
/// @return tokenIn The address of input token.
/// @return tokenOut The address of output token.
function getTokenPair(uint256 route) external view returns (address tokenIn, address tokenOut);
/// @notice Query the output token amount according to the encoding.
///
/// @dev See the comments in `convert` for the meaning of encoding.
///
/// @param encoding The encoding used to convert.
/// @param amountIn The amount of input token.
/// @param amountOut The amount of output token received.
function queryConvert(uint256 encoding, uint256 amountIn) external returns (uint256 amountOut);
/****************************
* Public Mutated Functions *
****************************/
/// @notice Convert input token to output token according to the encoding.
/// Assuming that the input token is already in the contract.
///
/// @dev encoding for single route
/// | 8 bits | 2 bits | 246 bits |
/// | pool_type | action | customized |
///
/// + pool_type = 0: UniswapV2, only action = 0
/// customized = | 160 bits | 24 bits | 1 bit | 1 bit | ... |
/// | pool address | fee_num | zero_for_one | twamm | ... |
/// + pool_type = 1: UniswapV3, only action = 0
/// customized = | 160 bits | 24 bits | 1 bit | ... |
/// | pool address | fee_num | zero_for_one | ... |
/// + pool_type = 2: BalancerV1, only action = 0
/// customized = | 160 bits | 3 bits | 3 bits | 3 bits | ... |
/// | pool address | tokens | index in | index out | ... |
/// + pool_type = 3: BalancerV2, only action = 0
/// customized = | 160 bits | 3 bits | 3 bits | 3 bits | ... |
/// | pool address | tokens | index in | index out | ... |
/// + pool_type = 4: CurvePlainPool or CurveFactoryPlainPool
/// customized = | 160 bits | 3 bits | 3 bits | 3 bits | 1 bit | ... |
/// | pool address | tokens | index in | index out | use_eth | ... |
/// + pool_type = 5: CurveAPool
/// customized = | 160 bits | 3 bits | 3 bits | 3 bits | 1 bits | ... |
/// | pool address | tokens | index in | index out | use_underlying | ... |
/// + pool_type = 6: CurveYPool
/// customized = | 160 bits | 3 bits | 3 bits | 3 bits | 1 bits | ... |
/// | pool address | tokens | index in | index out | use_underlying | ... |
/// + pool_type = 7: CurveMetaPool or CurveFactoryMetaPool
/// customized = | 160 bits | 3 bits | 3 bits | 3 bits | ... |
/// | pool address | tokens | index in | index out | ... |
/// + pool_type = 8: CurveCryptoPool or CurveFactoryCryptoPool
/// customized = | 160 bits | 3 bits | 3 bits | 3 bits | 1 bit | ... |
/// | pool address | tokens | index in | index out | use_eth | ... |
/// + pool_type = 9: ERC4626, no action 0
/// customized = | 160 bits | ... |
/// | pool address | ... |
/// + pool_type = 10: Lido, no action 0
/// customized = | 160 bits | ... |
/// | pool address | ... |
///
/// Note: tokens + 1 is the number of tokens of the pool
///
/// + action = 0: swap
/// + action = 1: add liquidity / wrap / stake
/// + action = 2: remove liquidity / unwrap / unstake
///
/// @param encoding The encoding used to convert.
/// @param amountIn The amount of input token.
/// @param recipient The address of token receiver.
/// @return amountOut The amount of output token received.
function convert(
uint256 encoding,
uint256 amountIn,
address recipient
) external payable returns (uint256 amountOut);
/// @notice Withdraw dust assets in this contract.
/// @param token The address of token to withdraw.
/// @param recipient The address of token receiver.
function withdrawFund(address token, address recipient) external;
}