diff --git a/README.md b/README.md index 850fe8493..de4a279bd 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,3 @@ This repository contains smart contracts for Synapse Protocol. The repository us ## What is Synapse? Synapse is a cross-chain layer ∞ protocol powering frictionless interoperability between blockchains. By providing decentralized, permissionless transactions between any L1, sidechain, or L2 ecosystem, Synapse powers integral blockchain activities such as asset transfers, swaps, and generalized messaging with cross-chain functionality - and in so doing enables new primitives based off of its cross-chain architecture. - - - - -Contains synapse contracts - -- [![Coverage Status](https://coveralls.io/repos/github/synapsecns/synapse-contracts/badge.svg?branch=master)](https://coveralls.io/github/synapsecns/synapse-contracts?branch=master) \ No newline at end of file diff --git a/contracts/bridge/BridgeConfig.sol b/contracts/bridge/BridgeConfig.sol deleted file mode 100644 index 2801db0c3..000000000 --- a/contracts/bridge/BridgeConfig.sol +++ /dev/null @@ -1,284 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.6.12; -pragma experimental ABIEncoderV2; - -import "@openzeppelin/contracts/access/AccessControl.sol"; -import "@openzeppelin/contracts/math/SafeMath.sol"; - -/** - * @title BridgeConfig contract - * @notice This token is used for configuring different tokens on the bridge and mapping them across chains. - **/ - -contract BridgeConfig is AccessControl { - using SafeMath for uint256; - bytes32 public constant BRIDGEMANAGER_ROLE = - keccak256("BRIDGEMANAGER_ROLE"); - bytes32[] private _allTokenIDs; - mapping(bytes32 => Token[]) private _allTokens; // key is tokenID - mapping(uint256 => mapping(address => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress - mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID - - // the denominator used to calculate fees. For example, an - // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR) - uint256 private constant FEE_DENOMINATOR = 10**10; - - // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge - struct Token { - uint256 chainId; - address tokenAddress; - uint8 tokenDecimals; - uint256 maxSwap; - uint256 minSwap; - uint256 swapFee; - uint256 maxSwapFee; - uint256 minSwapFee; - bool hasUnderlying; - bool isUnderlying; - } - - constructor() public { - _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); - } - - /** - * @notice Returns a list of all existing token IDs converted to strings - */ - function getAllTokenIDs() public view returns (string[] memory result) { - uint256 length = _allTokenIDs.length; - result = new string[](length); - for (uint256 i = 0; i < length; ++i) { - result[i] = bytes32ToString(_allTokenIDs[i]); - } - } - - /** - * @notice Returns the token ID (string) of the cross-chain token inputted - * @param tokenAddress address of token to get ID for - * @param chainID chainID of which to get token ID for - */ - function getTokenID(address tokenAddress, uint256 chainID) - public - view - returns (string memory) - { - return bytes32ToString(_tokenIDMap[chainID][tokenAddress]); - } - - /** - * @notice Returns the full token config struct - * @param tokenID String input of the token ID for the token - * @param chainID Chain ID of which token address + config to get - */ - function getToken(string calldata tokenID, uint256 chainID) - public - view - returns (Token memory token) - { - return _tokens[stringToBytes32(tokenID)][chainID]; - } - - /** - * @notice Returns token config struct, given an address and chainID - * @param tokenAddress Matches the token ID by using a combo of address + chain ID - * @param chainID Chain ID of which token to get config for - */ - function getToken(address tokenAddress, uint256 chainID) - public - view - returns (Token memory token) - { - string memory tokenID = getTokenID(tokenAddress, chainID); - return _tokens[stringToBytes32(tokenID)][chainID]; - } - - /** - * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge - * @param tokenID String to check if it is a withdraw/underlying token - */ - function hasUnderlyingToken(string calldata tokenID) - public - view - returns (bool) - { - bytes32 bytesTokenID = stringToBytes32(tokenID); - Token[] memory _mcTokens = _allTokens[bytesTokenID]; - for (uint256 i = 0; i < _mcTokens.length; ++i) { - if (_mcTokens[i].hasUnderlying) { - return true; - } - } - return false; - } - - /** - * @notice Returns which token is the underlying token to withdraw - * @param tokenID string token ID - */ - function getUnderlyingToken(string calldata tokenID) - public - view - returns (Token memory token) - { - bytes32 bytesTokenID = stringToBytes32(tokenID); - Token[] memory _mcTokens = _allTokens[bytesTokenID]; - for (uint256 i = 0; i < _mcTokens.length; ++i) { - if (_mcTokens[i].isUnderlying) { - return _mcTokens[i]; - } - } - } - - /** - @notice Public function returning if token ID exists given a string - */ - function isTokenIDExist(string calldata tokenID) - public - view - returns (bool) - { - return _isTokenIDExist(stringToBytes32(tokenID)); - } - - /** - @notice Internal function returning if token ID exists given bytes32 version of the ID - */ - function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) { - for (uint256 i = 0; i < _allTokenIDs.length; ++i) { - if (_allTokenIDs[i] == tokenID) { - return true; - } - } - return false; - } - - /** - * @notice Internal function which handles logic of setting token ID and dealing with mappings - * @param tokenID bytes32 version of ID - * @param chainID which chain to set the token config for - * @param tokenToAdd Token object to set the mapping to - */ - function _setTokenConfig( - bytes32 tokenID, - uint256 chainID, - Token memory tokenToAdd - ) internal returns (bool) { - _tokens[tokenID][chainID] = tokenToAdd; - if (!_isTokenIDExist(tokenID)) { - _allTokenIDs.push(tokenID); - } - - Token[] storage _mcTokens = _allTokens[tokenID]; - for (uint256 i = 0; i < _mcTokens.length; ++i) { - if (_mcTokens[i].chainId == chainID) { - address oldToken = _mcTokens[i].tokenAddress; - if (tokenToAdd.tokenAddress != oldToken) { - _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress; - _tokenIDMap[chainID][oldToken] = keccak256(""); - _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID; - } - } - } - _mcTokens.push(tokenToAdd); - _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID; - return true; - } - - /** - * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function - * @param tokenID string ID to set the token config object form - * @param chainID chain ID to use for the token config object - * @param tokenAddress token address of the token on the given chain - * @param tokenDecimals decimals of token - * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals - * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals - * @param swapFee percent based swap fee -- 10e6 == 10bps - * @param maxSwapFee max swap fee to be charged - in native token decimals - * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH - * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw() - * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain - */ - function setTokenConfig( - string calldata tokenID, - uint256 chainID, - address tokenAddress, - uint8 tokenDecimals, - uint256 maxSwap, - uint256 minSwap, - uint256 swapFee, - uint256 maxSwapFee, - uint256 minSwapFee, - bool hasUnderlying, - bool isUnderlying - ) public returns (bool) { - require(hasRole(BRIDGEMANAGER_ROLE, msg.sender)); - Token memory tokenToAdd; - tokenToAdd.tokenAddress = tokenAddress; - tokenToAdd.tokenDecimals = tokenDecimals; - tokenToAdd.maxSwap = maxSwap; - tokenToAdd.minSwap = minSwap; - tokenToAdd.swapFee = swapFee; - tokenToAdd.maxSwapFee = maxSwapFee; - tokenToAdd.minSwapFee = minSwapFee; - tokenToAdd.hasUnderlying = hasUnderlying; - tokenToAdd.isUnderlying = isUnderlying; - - return _setTokenConfig(stringToBytes32(tokenID), chainID, tokenToAdd); - } - - /** - * @notice Calculates bridge swap fee based on the destination chain's token transfer. - * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on - * @param tokenAddress address of the destination token to query token config for - * @param chainID destination chain ID to query the token config for - * @param amount in native token decimals - * @return Fee calculated in token decimals - */ - function calculateSwapFee( - address tokenAddress, - uint256 chainID, - uint256 amount - ) external view returns (uint256) { - Token memory token = getToken(tokenAddress, chainID); - uint256 calculatedSwapFee = amount.mul(token.swapFee).div( - FEE_DENOMINATOR - ); - if ( - calculatedSwapFee > token.minSwapFee && - calculatedSwapFee < token.maxSwapFee - ) { - return calculatedSwapFee; - } else if (calculatedSwapFee > token.maxSwapFee) { - return token.maxSwapFee; - } else { - return token.minSwapFee; - } - } - - function stringToBytes32(string memory str) - internal - pure - returns (bytes32 result) - { - assembly { - result := mload(add(str, 32)) - } - } - - function bytes32ToString(bytes32 data) - internal - pure - returns (string memory) - { - uint8 i = 0; - while (i < 32 && data[i] != 0) { - ++i; - } - bytes memory bs = new bytes(i); - for (uint8 j = 0; j < i; ++j) { - bs[j] = data[j]; - } - return string(bs); - } -} diff --git a/contracts/bridge/BridgeConfigv2.sol b/contracts/bridge/BridgeConfigv2.sol deleted file mode 100644 index 3922a98d3..000000000 --- a/contracts/bridge/BridgeConfigv2.sol +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.6.12; -pragma experimental ABIEncoderV2; - -import {BridgeConfig} from "./BridgeConfig.sol"; -import {AccessControl} from "./BridgeConfig.sol"; -import {SafeMath} from "./BridgeConfig.sol"; -import {PoolConfig} from "./PoolConfig.sol"; - -/** - * @title BridgeConfigV2 contract - * @notice This token is used for configuring different tokens on the bridge and mapping them across chains. - * It wraps bridge config for data storage - **/ - -contract BridgeConfigV2 is AccessControl { - using SafeMath for uint256; - bytes32 public constant BRIDGEMANAGER_ROLE = - keccak256("BRIDGEMANAGER_ROLE"); - BridgeConfig public BRIDGECONFIG_V1; - PoolConfig public POOLCONFIG_V1; - mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID - - constructor() public { - _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); - } - - function setBridgeConfig(BridgeConfig bridgeconfig, PoolConfig poolconfig) - public - { - require(hasRole(BRIDGEMANAGER_ROLE, msg.sender)); - BRIDGECONFIG_V1 = bridgeconfig; - POOLCONFIG_V1 = poolconfig; - } - - /** - * @notice Returns a list of all existing token IDs converted to strings - */ - function getAllTokenIDs() public view returns (string[] memory result) { - return BRIDGECONFIG_V1.getAllTokenIDs(); - } - - /** - * @notice Returns the token ID (string) of the cross-chain token inputted - * @param tokenAddress address of token to get ID for - * @param chainID chainID of which to get token ID for - */ - function getTokenID(address tokenAddress, uint256 chainID) - public - view - returns (string memory) - { - return BRIDGECONFIG_V1.getTokenID(tokenAddress, chainID); - } - - /** - * @notice Returns the full token config struct - * @param tokenID String input of the token ID for the token - * @param chainID Chain ID of which token address + config to get - */ - function getToken(string calldata tokenID, uint256 chainID) - public - view - returns (BridgeConfig.Token memory token) - { - return BRIDGECONFIG_V1.getToken(tokenID, chainID); - } - - /** - * @notice Returns token config struct, given an address and chainID - * @param tokenAddress Matches the token ID by using a combo of address + chain ID - * @param chainID Chain ID of which token to get config for - */ - function getToken(address tokenAddress, uint256 chainID) - public - view - returns (BridgeConfig.Token memory token) - { - return BRIDGECONFIG_V1.getToken(tokenAddress, chainID); - } - - /** - * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge - * @param tokenID String to check if it is a withdraw/underlying token - */ - function hasUnderlyingToken(string calldata tokenID) - public - view - returns (bool) - { - return BRIDGECONFIG_V1.hasUnderlyingToken(tokenID); - } - - /** - * @notice Returns which token is the underlying token to withdraw - * @param tokenID string token ID - */ - function getUnderlyingToken(string calldata tokenID) - public - view - returns (BridgeConfig.Token memory token) - { - return BRIDGECONFIG_V1.getUnderlyingToken(tokenID); - } - - /** - @notice Public function returning if token ID exists given a string - */ - function isTokenIDExist(string calldata tokenID) - public - view - returns (bool) - { - return BRIDGECONFIG_V1.isTokenIDExist(tokenID); - } - - /** - * @notice Calculates bridge swap fee based on the destination chain's token transfer. - * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on - * @param tokenAddress address of the destination token to query token config for - * @param chainID destination chain ID to query the token config for - * @param amount in native token decimals - * @return Fee calculated in token decimals - */ - function calculateSwapFee( - address tokenAddress, - uint256 chainID, - uint256 amount - ) external view returns (uint256) { - return BRIDGECONFIG_V1.calculateSwapFee(tokenAddress, chainID, amount); - } - - function getPoolConfig(address tokenAddress, uint256 chainID) - external - view - returns (PoolConfig.Pool memory) - { - return POOLCONFIG_V1.getPoolConfig(tokenAddress, chainID); - } - - /** - * @notice sets the max gas price for a chain - */ - function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public { - require(hasRole(BRIDGEMANAGER_ROLE, msg.sender)); - _maxGasPrice[chainID] = maxPrice; - } - - /** - * @notice gets the max gas price for a chain - */ - function getMaxGasPrice(uint256 chainID) public view returns (uint256) { - return _maxGasPrice[chainID]; - } -}