Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- ERC20HandlerUpgradeable
- Optimization enabled
- true
- Compiler version
- v0.8.2+commit.661d1103
- Optimization runs
- 50
- Verified at
- 2022-07-14T11:52:30.902359Z
contracts/handlers/ERC20HandlerUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../interfaces/IDepositExecute.sol"; import "../interfaces/ILiquidityPool.sol"; import "../interfaces/IOneSplitWrap.sol"; import "../interfaces/IWETH.sol"; import "../interfaces/IERC20Upgradeable.sol"; import "./HandlerHelpersUpgradeable.sol"; /** @title Handles ERC20 deposits and deposit executions. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract ERC20HandlerUpgradeable is Initializable, ContextUpgradeable, IDepositExecute, HandlerHelpersUpgradeable, ILiquidityPool { using SafeMathUpgradeable for uint256; struct DepositRecord { uint8 _destinationChainID; address _srcTokenAddress; address _stableTokenAddress; uint256 _stableTokenAmount; address _destStableTokenAddress; uint256 _destStableTokenAmount; address _destinationTokenAdress; uint256 _destinationTokenAmount; bytes32 _resourceID; address _destinationRecipientAddress; address _depositer; uint256 _srcTokenAmount; address _feeTokenAddress; uint256 _feeAmount; uint256 _isDestNative; } // destId => depositNonce => Deposit Record mapping(uint8 => mapping(uint64 => DepositRecord)) private _depositRecords; // token contract address => chainId => decimals mapping(address => mapping(uint8 => uint8)) public tokenDecimals; mapping(uint256 => mapping(uint64 => uint256)) public executeRecord; function __ERC20HandlerUpgradeable_init( address bridgeAddress, address ETH, address WETH, bytes32[] memory initialResourceIDs, address[] memory initialContractAddresses, address[] memory burnableContractAddresses ) internal initializer { __Context_init_unchained(); __HandlerHelpersUpgradeable_init(); require( initialResourceIDs.length == initialContractAddresses.length, "initialResourceIDs & initialContractAddresses len mismatch" ); _bridgeAddress = bridgeAddress; _ETH = ETH; _WETH = WETH; uint256 initialResourceCount = initialResourceIDs.length; for (uint256 i = 0; i < initialResourceCount; i++) { _setResource(initialResourceIDs[i], initialContractAddresses[i]); } uint256 burnableCount = burnableContractAddresses.length; for (uint256 i = 0; i < burnableCount; i++) { _setBurnable(burnableContractAddresses[i], true); } } function __ERC20HandlerUpgradeable_init_unchained() internal initializer {} /** @param bridgeAddress Contract address of previously deployed Bridge. // Resource IDs are used to identify a specific contract address. // These are the Resource IDs this contract will initially support. // These are the addresses the {initialResourceIDs} will point to, // and are the contracts that will be called to perform various deposit calls. @param burnableContractAddresses These addresses will be set as burnable and when {deposit} is called, the deposited token will be burned. When {executeProposal} is called, new tokens will be minted. @dev {initialResourceIDs} and {initialContractAddresses} must have the same length (one resourceID for every address). Also, these arrays must be ordered in the way that {initialResourceIDs}[0] is the intended resourceID for {initialContractAddresses}[0]. */ function initialize( address bridgeAddress, address ETH, address WETH, bytes32[] memory initialResourceIDs, address[] memory initialContractAddresses, address[] memory burnableContractAddresses ) external initializer { __ERC20HandlerUpgradeable_init( bridgeAddress, ETH, WETH, initialResourceIDs, initialContractAddresses, burnableContractAddresses ); } receive() external payable {} function setTokenDecimals( address tokenAddress, uint8 destinationChainID, uint8 decimals ) public onlyRole(BRIDGE_ROLE) { require(_contractWhitelist[tokenAddress], "provided contract is not whitelisted"); tokenDecimals[tokenAddress][destinationChainID] = decimals; } function changePrecision( address token, uint8 chainId, uint256 tokenAmount ) public view returns (uint256) { IERC20Upgradeable srcToken = IERC20Upgradeable(token); require(tokenDecimals[token][chainId] > 0, "Decimals not set for token and chain id"); uint8 srcDecimal = srcToken.decimals(); uint8 destDecimal = tokenDecimals[token][chainId]; if (srcDecimal == destDecimal) return tokenAmount; if (srcDecimal > destDecimal) { uint256 factor = (10**(srcDecimal - destDecimal)); return tokenAmount / factor; } else { uint256 factor = (10**(destDecimal - srcDecimal)); return tokenAmount * factor; } } function setExecuteRecord(uint256 chainId, uint64 nonce) internal { executeRecord[chainId][nonce] = block.number; } /** @param depositNonce This ID will have been generated by the Bridge contract. @param destId ID of chain deposit will be bridged to. @return DepositRecord */ function getDepositRecord(uint64 depositNonce, uint8 destId) public view virtual returns (DepositRecord memory) { return _depositRecords[destId][depositNonce]; } function setReserve(IHandlerReserve reserve) external onlyRole(DEFAULT_ADMIN_ROLE) { _reserve = reserve; } /** @notice A deposit is initiatied by making a deposit in the Bridge contract. @param destinationChainID Chain ID of chain tokens are expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @dev Depending if the corresponding {tokenAddress} for the parsed {resourceID} is marked true in {_burnList}, deposited tokens will be burned, if not, they will be locked. */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo memory swapDetails ) public virtual override onlyRole(BRIDGE_ROLE) { uint256 feeAmount; swapDetails.srcStableTokenAddress = _resourceIDToTokenContractAddress[resourceID]; require(_contractWhitelist[swapDetails.srcStableTokenAddress], "provided tokenAddress is not whitelisted"); if (address(swapDetails.srcTokenAddress) == swapDetails.srcStableTokenAddress) { require(swapDetails.srcStableTokenAmount == swapDetails.srcTokenAmount, "Invalid token amount"); if (swapDetails.feeTokenAddress == address(0)) { swapDetails.feeTokenAddress = swapDetails.srcStableTokenAddress; } (uint256 transferFee, ) = getBridgeFee(destinationChainID, swapDetails.feeTokenAddress); feeAmount = transferFee; // Fees of stable token address _reserve.deductFee( swapDetails.feeTokenAddress, swapDetails.depositer, // swapDetails.providedFee, transferFee, // _ETH, _isFeeEnabled, address(feeManager) ); // just deposit handleDepositForReserveToken(swapDetails); } else if (_reserve._contractToLP(swapDetails.srcStableTokenAddress) == address(swapDetails.srcTokenAddress)) { require(swapDetails.srcStableTokenAmount == swapDetails.srcTokenAmount, "Invalid token amount"); feeAmount = deductFeeAndHandleDepositForLPToken(swapDetails, destinationChainID); } else { if (swapDetails.feeTokenAddress != address(0)) { (, uint256 exchangeFee) = getBridgeFee(destinationChainID, swapDetails.feeTokenAddress); feeAmount = exchangeFee; // Fees of stable token address _reserve.deductFee( swapDetails.feeTokenAddress, swapDetails.depositer, // swapDetails.providedFee, exchangeFee, // _ETH, _isFeeEnabled, address(feeManager) ); } _reserve.lockERC20( address(swapDetails.srcTokenAddress), swapDetails.depositer, _oneSplitAddress, swapDetails.srcTokenAmount ); handleDepositForNonReserveToken(swapDetails); if (swapDetails.feeTokenAddress == address(0)) { (, uint256 exchangeFee) = getBridgeFee(destinationChainID, swapDetails.srcStableTokenAddress); feeAmount = exchangeFee; swapDetails.feeTokenAddress = swapDetails.srcStableTokenAddress; require( swapDetails.srcStableTokenAmount >= exchangeFee, "ERC20handler : provided fee is less than the amount" ); swapDetails.srcStableTokenAmount = swapDetails.srcStableTokenAmount - exchangeFee; _reserve.releaseERC20(swapDetails.feeTokenAddress, address(feeManager), exchangeFee); } if (_burnList[address(swapDetails.srcStableTokenAddress)]) { _reserve.burnERC20( address(swapDetails.srcStableTokenAddress), address(_reserve), swapDetails.srcStableTokenAmount ); } } uint256 destStableTokenAmount = changePrecision( address(swapDetails.srcStableTokenAddress), destinationChainID, swapDetails.srcStableTokenAmount ); require(destStableTokenAmount > 0, "Transfer amount too low"); _depositRecords[destinationChainID][depositNonce] = DepositRecord( destinationChainID, address(swapDetails.srcTokenAddress), swapDetails.srcStableTokenAddress, swapDetails.srcStableTokenAmount, address(swapDetails.destStableTokenAddress), destStableTokenAmount, address(swapDetails.destTokenAddress), swapDetails.destTokenAmount, resourceID, swapDetails.recipient, swapDetails.depositer, swapDetails.srcTokenAmount, swapDetails.feeTokenAddress, feeAmount, swapDetails.isDestNative ? 1 : 0 ); } /** @notice Proposal execution should be initiated when a proposal is finalized in the Bridge contract. by a relayer on the deposit's destination chain. @notice Data passed into the function should be constructed as follows: amount uint256 bytes 0 - 32 destinationRecipientAddress length uint256 bytes 32 - 64 destinationRecipientAddress bytes bytes 64 - END */ function executeProposal(SwapInfo memory swapDetails, bytes32 resourceID) public virtual override onlyRole(BRIDGE_ROLE) returns (address settlementToken, uint256 settlementAmount) { swapDetails.destStableTokenAddress = _resourceIDToTokenContractAddress[resourceID]; require(_contractWhitelist[swapDetails.destStableTokenAddress], "provided tokenAddress is not whitelisted"); if (address(swapDetails.destTokenAddress) == swapDetails.destStableTokenAddress) { // just release destStable tokens (settlementToken, settlementAmount) = handleExecuteForReserveToken(swapDetails); setExecuteRecord(swapDetails.index, swapDetails.depositNonce); } else if ( _reserve._contractToLP(swapDetails.destStableTokenAddress) == address(swapDetails.destTokenAddress) ) { // release LP is destToken is LP of destStableToken handleExecuteForLPToken(swapDetails); settlementToken = address(swapDetails.destTokenAddress); settlementAmount = swapDetails.destStableTokenAmount; setExecuteRecord(swapDetails.index, swapDetails.depositNonce); } else { // exchange destStable to destToken and release tokens (settlementToken, settlementAmount) = handleExecuteForNonReserveToken(swapDetails); setExecuteRecord(swapDetails.index, swapDetails.depositNonce); } } /** @notice Used to manually release ERC20 tokens from ERC20Safe. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount The amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve.releaseERC20(tokenAddress, recipient, amount); } /** @notice Used to manually release ERC20 tokens from FeeManager. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount The amount of ERC20 tokens to release. */ function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.withdrawFee(tokenAddress, recipient, amount); } function stake( address depositor, address tokenAddress, uint256 amount ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve.stake(depositor, tokenAddress, amount); } function stakeETH( address depositor, address tokenAddress, uint256 amount ) public virtual override onlyRole(BRIDGE_ROLE) { assert(IWETH(_WETH).transfer(address(_reserve), amount)); _reserve.stakeETH(depositor, tokenAddress, amount); } /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve.unstake(unstaker, tokenAddress, amount); } function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve.unstakeETH(unstaker, tokenAddress, amount, _WETH); } function getStakedRecord(address account, address tokenAddress) public view virtual returns (uint256) { return _reserve.getStakedRecord(account, tokenAddress); } function handleDepositForReserveToken(SwapInfo memory swapDetails) internal { if (_burnList[address(swapDetails.srcTokenAddress)]) { _reserve.burnERC20(address(swapDetails.srcTokenAddress), swapDetails.depositer, swapDetails.srcTokenAmount); } else { _reserve.lockERC20( address(swapDetails.srcTokenAddress), swapDetails.depositer, address(_reserve), swapDetails.srcTokenAmount ); } } function deductFeeAndHandleDepositForLPToken(SwapInfo memory swapDetails, uint8 destinationChainID) internal returns (uint256 transferFee) { if (swapDetails.feeTokenAddress == address(0)) { swapDetails.feeTokenAddress = address(swapDetails.srcTokenAddress); (transferFee, ) = getBridgeFee(destinationChainID, swapDetails.srcStableTokenAddress); } else { (transferFee, ) = getBridgeFee(destinationChainID, swapDetails.feeTokenAddress); } // Fees of stable token address _reserve.deductFee( swapDetails.feeTokenAddress, swapDetails.depositer, // swapDetails.providedFee, transferFee, // _ETH, _isFeeEnabled, address(feeManager) ); _reserve.burnERC20(address(swapDetails.srcTokenAddress), swapDetails.depositer, swapDetails.srcTokenAmount); } function handleDepositForNonReserveToken(SwapInfo memory swapDetails) internal { uint256 pathLength = swapDetails.path.length; if (pathLength > 2) { //swapMulti require(swapDetails.path[pathLength - 1] == swapDetails.srcStableTokenAddress); swapDetails.srcStableTokenAmount = _reserve.swapMulti( _oneSplitAddress, swapDetails.path, swapDetails.srcTokenAmount, swapDetails.srcStableTokenAmount, swapDetails.flags, swapDetails.dataTx ); } else { swapDetails.srcStableTokenAmount = _reserve.swap( _oneSplitAddress, address(swapDetails.srcTokenAddress), swapDetails.srcStableTokenAddress, swapDetails.srcTokenAmount, swapDetails.srcStableTokenAmount, swapDetails.flags[0], swapDetails.dataTx[0] ); } } function handleExecuteForReserveToken(SwapInfo memory swapDetails) internal returns (address, uint256) { if (_burnList[address(swapDetails.destTokenAddress)]) { _reserve.mintERC20( address(swapDetails.destTokenAddress), swapDetails.recipient, swapDetails.destStableTokenAmount ); } else { uint256 reserveBalance = IERC20(address(swapDetails.destStableTokenAddress)).balanceOf(address(_reserve)); if (reserveBalance < swapDetails.destStableTokenAmount) { _reserve.mintWrappedERC20( address(swapDetails.destStableTokenAddress), swapDetails.recipient, swapDetails.destStableTokenAmount ); return ( _reserve._contractToLP(address(swapDetails.destStableTokenAddress)), swapDetails.destStableTokenAmount ); } else { if (address(swapDetails.destStableTokenAddress) == _WETH && swapDetails.isDestNative) { _reserve.withdrawWETH(_WETH, swapDetails.destStableTokenAmount); _reserve.safeTransferETH(swapDetails.recipient, swapDetails.destStableTokenAmount); } else { _reserve.releaseERC20( address(swapDetails.destStableTokenAddress), swapDetails.recipient, swapDetails.destStableTokenAmount ); } } } return (address(swapDetails.destStableTokenAddress), swapDetails.destStableTokenAmount); } function handleExecuteForLPToken(SwapInfo memory swapDetails) internal { _reserve.mintWrappedERC20( address(swapDetails.destStableTokenAddress), swapDetails.recipient, swapDetails.destStableTokenAmount ); } function handleExecuteForNonReserveToken(SwapInfo memory swapDetails) internal returns (address, uint256) { if (_burnList[swapDetails.destStableTokenAddress]) { if ( (swapDetails.path.length > 2) && (swapDetails.path[swapDetails.path.length - 1] != address(swapDetails.destTokenAddress)) ) { _reserve.mintERC20( swapDetails.destStableTokenAddress, swapDetails.recipient, swapDetails.destStableTokenAmount ); return (swapDetails.destStableTokenAddress, swapDetails.destStableTokenAmount); } _reserve.mintERC20(swapDetails.destStableTokenAddress, _oneSplitAddress, swapDetails.destStableTokenAmount); } else { uint256 reserveBalance = IERC20(address(swapDetails.destStableTokenAddress)).balanceOf(address(_reserve)); if (reserveBalance < swapDetails.destStableTokenAmount) { _reserve.mintWrappedERC20( address(swapDetails.destStableTokenAddress), swapDetails.recipient, swapDetails.destStableTokenAmount ); return ( _reserve._contractToLP(address(swapDetails.destStableTokenAddress)), swapDetails.destStableTokenAmount ); } else { if ( (swapDetails.path.length > 2) && (swapDetails.path[swapDetails.path.length - 1] != address(swapDetails.destTokenAddress)) ) { _reserve.releaseERC20( swapDetails.destStableTokenAddress, swapDetails.recipient, swapDetails.destStableTokenAmount ); return (swapDetails.destStableTokenAddress, swapDetails.destStableTokenAmount); } _reserve.releaseERC20( swapDetails.destStableTokenAddress, _oneSplitAddress, swapDetails.destStableTokenAmount ); } } if (swapDetails.path.length > 2) { //solhint-disable avoid-low-level-calls (bool success, bytes memory returnData) = address(_reserve).call( abi.encodeWithSelector( 0x2214e13b, // swapMulti(address,address[],uint256,uint256,uint256[],bytes[]) _oneSplitAddress, swapDetails.path, swapDetails.destStableTokenAmount, swapDetails.destTokenAmount, swapDetails.flags, swapDetails.dataTx ) ); if (success) { swapDetails.returnAmount = abi.decode(returnData, (uint256)); } else { require( IOneSplitWrap(_oneSplitAddress).withdraw( swapDetails.destStableTokenAddress, swapDetails.recipient, swapDetails.destStableTokenAmount ) ); return (address(swapDetails.destStableTokenAddress), swapDetails.destStableTokenAmount); } } else { (bool success, bytes memory returnData) = address(_reserve).call( abi.encodeWithSelector( 0xda041a85, //swap(address,address,address,uint256,uint256,uint256,bytes) _oneSplitAddress, swapDetails.destStableTokenAddress, address(swapDetails.destTokenAddress), swapDetails.destStableTokenAmount, swapDetails.destTokenAmount, swapDetails.flags[0], swapDetails.dataTx[0] ) ); if (success) { swapDetails.returnAmount = abi.decode(returnData, (uint256)); } else { require( IOneSplitWrap(_oneSplitAddress).withdraw( swapDetails.destStableTokenAddress, swapDetails.recipient, swapDetails.destStableTokenAmount ) ); return (address(swapDetails.destStableTokenAddress), swapDetails.destStableTokenAmount); } } if (address(swapDetails.destTokenAddress) == _WETH && swapDetails.isDestNative) { _reserve.withdrawWETH(_WETH, swapDetails.returnAmount); _reserve.safeTransferETH(swapDetails.recipient, swapDetails.returnAmount); } else { _reserve.releaseERC20( address(swapDetails.destTokenAddress), swapDetails.recipient, swapDetails.returnAmount ); } return (address(swapDetails.destTokenAddress), swapDetails.returnAmount); } }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { __Context_init_unchained(); __ERC165_init_unchained(); __AccessControl_init_unchained(); } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(uint160(account), 20), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { __ERC165_init_unchained(); } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } uint256[50] private __gap; }
contracts/interfaces/IFeeManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IFeeManagerUpgradeable { function setFees( uint8 destinationChainID, address[] calldata feeTokenAddrs, uint256[] calldata transferFees, uint256[] calldata exchangeFees, bool[] calldata accepted ) external; function withdrawFee(address tokenAddress, address recipient, uint256 amount) external; function setFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function getFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); }
@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/handlers/HandlerHelpersUpgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IFeeManager.sol"; import "../interfaces/IHandlerReserve.sol"; /** @title Function used across handler contracts. @author Router Protocol. @notice This contract is intended to be used with the Bridge contract. */ contract HandlerHelpersUpgradeable is Initializable, ContextUpgradeable, AccessControlUpgradeable, IERCHandler { address public _bridgeAddress; address public _oneSplitAddress; address public override _ETH; address public override _WETH; bool public _isFeeEnabled; bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); IFeeManagerUpgradeable public feeManager; IHandlerReserve public _reserve; // resourceID => token contract address mapping(bytes32 => address) internal _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; // bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE"); function __HandlerHelpersUpgradeable_init() internal initializer { __Context_init_unchained(); __AccessControl_init(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(BRIDGE_ROLE, _msgSender()); _isFeeEnabled = false; } function __HandlerHelpersUpgradeable_init_unchained() internal initializer {} // function grantFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // grantRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters + 1; // } // function revokeFeeRole(address account) public virtual override onlyRole(BRIDGE_ROLE) { // revokeRole(FEE_SETTER_ROLE, account); // totalFeeSetters = totalFeeSetters - 1; // } function setFeeManager(IFeeManagerUpgradeable _feeManager) public onlyRole(DEFAULT_ADMIN_ROLE) { feeManager = _feeManager; } function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) public view virtual override returns (uint256, uint256) { return feeManager.getFee(destinationChainID, feeTokenAddress); } function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) public virtual override onlyRole(BRIDGE_ROLE) { feeManager.setFee(destinationChainID, feeTokenAddress, transferFee, exchangeFee, accepted); } function toggleFeeStatus(bool status) public virtual override onlyRole(BRIDGE_ROLE) { _isFeeEnabled = status; } function getFeeStatus() public view virtual override returns (bool) { return _isFeeEnabled; } function resourceIDToTokenContractAddress(bytes32 resourceID) public view virtual override returns (address) { return _resourceIDToTokenContractAddress[resourceID]; } /** @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and {_contractAddressToResourceID}[{contractAddress}] are not already set, then sets {_resourceIDToContractAddress} with {contractAddress}, {_contractAddressToResourceID} with {resourceID}, and {_contractWhitelist} to true for {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setResource(resourceID, contractAddress); } /** @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] to true. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag to change burnable status. */ function setBurnable(address contractAddress, bool status) public virtual override onlyRole(BRIDGE_ROLE) { _setBurnable(contractAddress, status); } /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amount the amount of ERC20 tokens to release. */ function withdraw( address tokenAddress, address recipient, uint256 amount ) public virtual override {} function withdrawFees( address tokenAddress, address recipient, uint256 amount ) public virtual override {} /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) public virtual override onlyRole(BRIDGE_ROLE) { _setOneSplitAddress(contractAddress); } /** @notice Sets liquidity pool for given ERC20 address. These pools will be used to stake and unstake liqudity. @param contractAddress Address of contract for which LP contract should be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { address newLPAddress = _reserve._setLiquidityPool(name, symbol, decimals, contractAddress, lpAddress); _contractWhitelist[newLPAddress] = true; _setBurnable(newLPAddress, true); } function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) public virtual override onlyRole(BRIDGE_ROLE) { _reserve._setLiquidityPoolOwner(newOwner, tokenAddress, lpAddress); } function _setResource(bytes32 resourceID, address contractAddress) internal virtual { require(contractAddress != address(0), "contract address can't be zero"); _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress, bool status) internal virtual { require(_contractWhitelist[contractAddress], "provided contract is not whitelisted"); _burnList[contractAddress] = status; } function _setOneSplitAddress(address contractAddress) internal virtual { require(contractAddress != address(0), "ERC20Handler: contractAddress cannot be null"); _oneSplitAddress = address(contractAddress); } }
contracts/interfaces/IDepositExecute.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface IDepositExecute { struct SwapInfo { address feeTokenAddress; uint64 depositNonce; uint256 index; uint256 returnAmount; address recipient; address stableTokenAddress; address handler; uint256 srcTokenAmount; uint256 srcStableTokenAmount; uint256 destStableTokenAmount; uint256 destTokenAmount; uint256 lenRecipientAddress; uint256 lenSrcTokenAddress; uint256 lenDestTokenAddress; bytes20 srcTokenAddress; address srcStableTokenAddress; bytes20 destTokenAddress; address destStableTokenAddress; bytes[] dataTx; uint256[] flags; address[] path; address depositer; bool isDestNative; uint256 widgetID; } /** @notice It is intended that deposit are made using the Bridge contract. @param destinationChainID Chain ID deposit is expected to be bridged to. @param depositNonce This value is generated as an ID by the Bridge contract. @param swapDetails Swap details */ function deposit( bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, SwapInfo calldata swapDetails ) external; /** @notice It is intended that proposals are executed by the Bridge contract. */ function executeProposal(SwapInfo calldata swapDetails, bytes32 resourceID) external returns (address, uint256); }
contracts/interfaces/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERC20Upgradeable { function transfer( address, uint256) external; function decimals() external view returns (uint8); }
contracts/interfaces/IERCHandler.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.2; /** @title Interface to be used with handlers that support ERC20s and ERC721s. @author Router Protocol. */ interface IERCHandler { function withdrawFees( address tokenAddress, address recipient, uint256 amount ) external; function getBridgeFee(uint8 destinationChainID, address feeTokenAddress) external view returns (uint256, uint256); function setBridgeFee( uint8 destinationChainID, address feeTokenAddress, uint256 transferFee, uint256 exchangeFee, bool accepted ) external; function toggleFeeStatus(bool status) external; function getFeeStatus() external view returns (bool); function _ETH() external view returns (address); function _WETH() external view returns (address); function resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); /** @notice Correlates {resourceID} with {contractAddress}. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. */ function setResource(bytes32 resourceID, address contractAddress) external; // function setTokenDecimals(address tokenAddress, uint8 destinationChainID, uint8 decimals) external; /** @notice Sets oneSplitAddress for the handler @param contractAddress Address of oneSplit contract */ function setOneSplitAddress(address contractAddress) external; /** @notice Correlates {resourceID} with {contractAddress}. @param contractAddress Address of contract for qhich liquidity pool needs to be created. */ function setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external; function setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; /** @notice Marks {contractAddress} as mintable/burnable. @param contractAddress Address of contract to be used when making or executing deposits. @param status Boolean flag for burnanble status. */ function setBurnable(address contractAddress, bool status) external; /** @notice Used to manually release funds from ERC safes. @param tokenAddress Address of token contract to release. @param recipient Address to release tokens to. @param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release. */ function withdraw( address tokenAddress, address recipient, uint256 amountOrTokenID ) external; }
contracts/interfaces/IHandlerReserve.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IHandlerReserve { function fundERC20( address tokenAddress, address owner, uint256 amount ) external; function lockERC20( address tokenAddress, address owner, address recipient, uint256 amount ) external; function releaseERC20( address tokenAddress, address recipient, uint256 amount ) external; function mintERC20( address tokenAddress, address recipient, uint256 amount ) external; function burnERC20( address tokenAddress, address owner, uint256 amount ) external; function safeTransferETH(address to, uint256 value) external; function deductFee( address feeTokenAddress, address depositor, // uint256 providedFee, uint256 requiredFee, // address _ETH, bool _isFeeEnabled, address _feeManager ) external; function mintWrappedERC20( address tokenAddress, address recipient, uint256 amount ) external; function stake( address depositor, address tokenAddress, uint256 amount ) external; function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; function unstake( address unstaker, address tokenAddress, uint256 amount ) external; function unstakeETH( address unstaker, address tokenAddress, uint256 amount, address WETH ) external; function getStakedRecord(address account, address tokenAddress) external view returns (uint256); function withdrawWETH(address WETH, uint256 amount) external; function _setLiquidityPoolOwner( address newOwner, address tokenAddress, address lpAddress ) external; function _setLiquidityPool( string memory name, string memory symbol, uint8 decimals, address contractAddress, address lpAddress ) external returns (address); function swapMulti( address oneSplitAddress, address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx ) external returns (uint256 returnAmount); function swap( address oneSplitAddress, address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx ) external returns (uint256 returnAmount); function feeManager() external returns (address); function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); }
contracts/interfaces/ILiquidityPool.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; /** @title Interface for handler contracts that support deposits and deposit executions. @author Router Protocol. */ interface ILiquidityPool { /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stake( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param depositor stakes liquidity in the pool . @param tokenAddress staking token for which liquidity needs to be added. @param amount Amount that needs to be staked. */ function stakeETH( address depositor, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstake( address unstaker, address tokenAddress, uint256 amount ) external; /** @notice Staking should be done by using bridge contract. @param unstaker removes liquidity from the pool. @param tokenAddress staking token of which liquidity needs to be removed. @param amount Amount that needs to be unstaked. */ function unstakeETH( address unstaker, address tokenAddress, uint256 amount ) external; }
contracts/interfaces/IOneSplitWrap.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IOneSplitWrap { function withdraw( address tokenAddress, address recipient, uint256 amount ) external returns (bool); function getExpectedReturn( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags ) external view returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( address fromToken, address destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) external view returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGasMulti( address[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) external view returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function swap( address fromToken, address destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); function swapMulti( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) external payable returns (uint256 returnAmount); }
contracts/interfaces/IWETH.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.2; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function approve(address guy, uint256 wad) external returns (bool); }
Contract ABI
[{"type":"event","name":"RoleAdminChanged","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"previousAdminRole","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"newAdminRole","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"BRIDGE_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DEFAULT_ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_ETH","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_WETH","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_bridgeAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"_burnList","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"_contractWhitelist","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"_isFeeEnabled","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_oneSplitAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IHandlerReserve"}],"name":"_reserve","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"_tokenContractAddressToResourceID","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"changePrecision","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint8","name":"chainId","internalType":"uint8"},{"type":"uint256","name":"tokenAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deposit","inputs":[{"type":"bytes32","name":"resourceID","internalType":"bytes32"},{"type":"uint8","name":"destinationChainID","internalType":"uint8"},{"type":"uint64","name":"depositNonce","internalType":"uint64"},{"type":"tuple","name":"swapDetails","internalType":"struct IDepositExecute.SwapInfo","components":[{"type":"address","name":"feeTokenAddress","internalType":"address"},{"type":"uint64","name":"depositNonce","internalType":"uint64"},{"type":"uint256","name":"index","internalType":"uint256"},{"type":"uint256","name":"returnAmount","internalType":"uint256"},{"type":"address","name":"recipient","internalType":"address"},{"type":"address","name":"stableTokenAddress","internalType":"address"},{"type":"address","name":"handler","internalType":"address"},{"type":"uint256","name":"srcTokenAmount","internalType":"uint256"},{"type":"uint256","name":"srcStableTokenAmount","internalType":"uint256"},{"type":"uint256","name":"destStableTokenAmount","internalType":"uint256"},{"type":"uint256","name":"destTokenAmount","internalType":"uint256"},{"type":"uint256","name":"lenRecipientAddress","internalType":"uint256"},{"type":"uint256","name":"lenSrcTokenAddress","internalType":"uint256"},{"type":"uint256","name":"lenDestTokenAddress","internalType":"uint256"},{"type":"bytes20","name":"srcTokenAddress","internalType":"bytes20"},{"type":"address","name":"srcStableTokenAddress","internalType":"address"},{"type":"bytes20","name":"destTokenAddress","internalType":"bytes20"},{"type":"address","name":"destStableTokenAddress","internalType":"address"},{"type":"bytes[]","name":"dataTx","internalType":"bytes[]"},{"type":"uint256[]","name":"flags","internalType":"uint256[]"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"depositer","internalType":"address"},{"type":"bool","name":"isDestNative","internalType":"bool"},{"type":"uint256","name":"widgetID","internalType":"uint256"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"settlementToken","internalType":"address"},{"type":"uint256","name":"settlementAmount","internalType":"uint256"}],"name":"executeProposal","inputs":[{"type":"tuple","name":"swapDetails","internalType":"struct IDepositExecute.SwapInfo","components":[{"type":"address","name":"feeTokenAddress","internalType":"address"},{"type":"uint64","name":"depositNonce","internalType":"uint64"},{"type":"uint256","name":"index","internalType":"uint256"},{"type":"uint256","name":"returnAmount","internalType":"uint256"},{"type":"address","name":"recipient","internalType":"address"},{"type":"address","name":"stableTokenAddress","internalType":"address"},{"type":"address","name":"handler","internalType":"address"},{"type":"uint256","name":"srcTokenAmount","internalType":"uint256"},{"type":"uint256","name":"srcStableTokenAmount","internalType":"uint256"},{"type":"uint256","name":"destStableTokenAmount","internalType":"uint256"},{"type":"uint256","name":"destTokenAmount","internalType":"uint256"},{"type":"uint256","name":"lenRecipientAddress","internalType":"uint256"},{"type":"uint256","name":"lenSrcTokenAddress","internalType":"uint256"},{"type":"uint256","name":"lenDestTokenAddress","internalType":"uint256"},{"type":"bytes20","name":"srcTokenAddress","internalType":"bytes20"},{"type":"address","name":"srcStableTokenAddress","internalType":"address"},{"type":"bytes20","name":"destTokenAddress","internalType":"bytes20"},{"type":"address","name":"destStableTokenAddress","internalType":"address"},{"type":"bytes[]","name":"dataTx","internalType":"bytes[]"},{"type":"uint256[]","name":"flags","internalType":"uint256[]"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"depositer","internalType":"address"},{"type":"bool","name":"isDestNative","internalType":"bool"},{"type":"uint256","name":"widgetID","internalType":"uint256"}]},{"type":"bytes32","name":"resourceID","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"executeRecord","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint64","name":"","internalType":"uint64"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFeeManagerUpgradeable"}],"name":"feeManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBridgeFee","inputs":[{"type":"uint8","name":"destinationChainID","internalType":"uint8"},{"type":"address","name":"feeTokenAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ERC20HandlerUpgradeable.DepositRecord","components":[{"type":"uint8","name":"_destinationChainID","internalType":"uint8"},{"type":"address","name":"_srcTokenAddress","internalType":"address"},{"type":"address","name":"_stableTokenAddress","internalType":"address"},{"type":"uint256","name":"_stableTokenAmount","internalType":"uint256"},{"type":"address","name":"_destStableTokenAddress","internalType":"address"},{"type":"uint256","name":"_destStableTokenAmount","internalType":"uint256"},{"type":"address","name":"_destinationTokenAdress","internalType":"address"},{"type":"uint256","name":"_destinationTokenAmount","internalType":"uint256"},{"type":"bytes32","name":"_resourceID","internalType":"bytes32"},{"type":"address","name":"_destinationRecipientAddress","internalType":"address"},{"type":"address","name":"_depositer","internalType":"address"},{"type":"uint256","name":"_srcTokenAmount","internalType":"uint256"},{"type":"address","name":"_feeTokenAddress","internalType":"address"},{"type":"uint256","name":"_feeAmount","internalType":"uint256"},{"type":"uint256","name":"_isDestNative","internalType":"uint256"}]}],"name":"getDepositRecord","inputs":[{"type":"uint64","name":"depositNonce","internalType":"uint64"},{"type":"uint8","name":"destId","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"getFeeStatus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRoleAdmin","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getStakedRecord","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"bridgeAddress","internalType":"address"},{"type":"address","name":"ETH","internalType":"address"},{"type":"address","name":"WETH","internalType":"address"},{"type":"bytes32[]","name":"initialResourceIDs","internalType":"bytes32[]"},{"type":"address[]","name":"initialContractAddresses","internalType":"address[]"},{"type":"address[]","name":"burnableContractAddresses","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"resourceIDToTokenContractAddress","inputs":[{"type":"bytes32","name":"resourceID","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBridgeFee","inputs":[{"type":"uint8","name":"destinationChainID","internalType":"uint8"},{"type":"address","name":"feeTokenAddress","internalType":"address"},{"type":"uint256","name":"transferFee","internalType":"uint256"},{"type":"uint256","name":"exchangeFee","internalType":"uint256"},{"type":"bool","name":"accepted","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBurnable","inputs":[{"type":"address","name":"contractAddress","internalType":"address"},{"type":"bool","name":"status","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFeeManager","inputs":[{"type":"address","name":"_feeManager","internalType":"contract IFeeManagerUpgradeable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLiquidityPool","inputs":[{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"symbol","internalType":"string"},{"type":"uint8","name":"decimals","internalType":"uint8"},{"type":"address","name":"contractAddress","internalType":"address"},{"type":"address","name":"lpAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLiquidityPoolOwner","inputs":[{"type":"address","name":"newOwner","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"lpAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOneSplitAddress","inputs":[{"type":"address","name":"contractAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setReserve","inputs":[{"type":"address","name":"reserve","internalType":"contract IHandlerReserve"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setResource","inputs":[{"type":"bytes32","name":"resourceID","internalType":"bytes32"},{"type":"address","name":"contractAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setTokenDecimals","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint8","name":"destinationChainID","internalType":"uint8"},{"type":"uint8","name":"decimals","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stake","inputs":[{"type":"address","name":"depositor","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stakeETH","inputs":[{"type":"address","name":"depositor","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"toggleFeeStatus","inputs":[{"type":"bool","name":"status","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"tokenDecimals","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint8","name":"","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unstake","inputs":[{"type":"address","name":"unstaker","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unstakeETH","inputs":[{"type":"address","name":"unstaker","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawFees","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x608060405234801561001057600080fd5b506149c0806100206000396000f3fe6080604052600436106102365760003560e01c80639680504c1161012f578063c8ba6c87116100b1578063c8ba6c87146108a8578063d0fb0203146108d5578063d3fad208146108f5578063d3ff209d14610915578063d547741f14610936578063d755c34914610956578063d9caed1214610976578063e0af361614610996578063e55dc4e6146109b6578063e7c308fd146109d6578063eae9befc146109f6578063f4e480e114610a165761023d565b80639680504c1461058857806397e76aab146105a85780639cecc80a146105e05780639e601b3114610600578063a217fddf14610635578063a6fd91ee1461064a578063ad527b2114610697578063b5bfddea146106b7578063b8fa3736146106d9578063ba484c09146106f9578063bf6eac2f146108885761023d565b80634a266160116101b85780634a266160146103fa578063536187d61461041a5780635d92c1ac1461043a5780635db99af21461045a5780635f624fbd1461047a57806360829f8a146104a85780636a70d081146104c85780636be1dc2b146104f85780637f79bea8146105185780637ffb45fa1461054857806391d14854146105685761023d565b806301ffc9a7146102425780630ab75d3e146102775780631487001b146102a4578063248a9ca3146102c65780632f2ff15d14610304578063318c136e14610324578063359d86011461034457806335d0d5dc1461036457806336568abe1461039a578063413ab4a8146103ba578063472d35b9146103da5761023d565b3661023d57005b600080fd5b34801561024e57600080fd5b5061026261025d366004613f56565b610a36565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b50609854610297906001600160a01b031681565b60405161026e91906142b5565b3480156102b057600080fd5b506102c46102bf366004614114565b610a6f565b005b3480156102d257600080fd5b506102f66102e1366004613eb3565b60009081526065602052604090206001015490565b60405190815260200161026e565b34801561031057600080fd5b506102c461031f366004613ecb565b610b0f565b34801561033057600080fd5b50609754610297906001600160a01b031681565b34801561035057600080fd5b506102c461035f366004613e3c565b610b3a565b34801561037057600080fd5b5061029761037f366004613eb3565b6000908152609d60205260409020546001600160a01b031690565b3480156103a657600080fd5b506102c46103b5366004613ecb565b610bcd565b3480156103c657600080fd5b50609c54610297906001600160a01b031681565b3480156103e657600080fd5b506102c46103f5366004613ba7565b610c4b565b34801561040657600080fd5b506102c4610415366004613eef565b610c7a565b34801561042657600080fd5b506102f6610435366004613e0d565b611458565b34801561044657600080fd5b506102c4610455366004613db3565b6115fa565b34801561046657600080fd5b50609954610297906001600160a01b031681565b34801561048657600080fd5b5061049a610495366004614018565b61161d565b60405161026e929190614420565b3480156104b457600080fd5b506102c46104c3366004613d73565b6117cd565b3480156104d457600080fd5b506102626104e3366004613ba7565b60a06020526000908152604090205460ff1681565b34801561050457600080fd5b506102c4610513366004613e7b565b611852565b34801561052457600080fd5b50610262610533366004613ba7565b609f6020526000908152604090205460ff1681565b34801561055457600080fd5b506102c4610563366004613c17565b61188a565b34801561057457600080fd5b50610262610583366004613ecb565b6118e5565b34801561059457600080fd5b506102c46105a3366004613f7e565b611910565b3480156105b457600080fd5b506102f66105c3366004614095565b60a360209081526000928352604080842090915290825290205481565b3480156105ec57600080fd5b506102c46105fb366004613ba7565b6119f1565b34801561060c57600080fd5b5061062061061b3660046140f7565b611a20565b6040805192835260208301919091520161026e565b34801561064157600080fd5b506102f6600081565b34801561065657600080fd5b50610685610665366004613de0565b60a260209081526000928352604080842090915290825290205460ff1681565b60405160ff909116815260200161026e565b3480156106a357600080fd5b506102f66106b2366004613bdf565b611ab4565b3480156106c357600080fd5b506102f660008051602061499483398151915281565b3480156106e557600080fd5b506102c46106f4366004613ecb565b611b3a565b34801561070557600080fd5b5061087b6107143660046140c0565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c08101919091525060ff908116600090815260a1602090815260408083206001600160401b039590951683529381529083902083516101e08101855281549384168152610100938490046001600160a01b0390811693820193909352600182015483169481019490945260028101546060850152600381015482166080850152600481015460a08501526005810154821660c0850152600681015460e08501526007810154928401929092526008820154811661012084015260098201548116610140840152600a820154610160840152600b82015416610180830152600c8101546101a0830152600d01546101c082015290565b60405161026e91906145ef565b34801561089457600080fd5b506102c46108a3366004613d73565b611b5d565b3480156108b457600080fd5b506102f66108c3366004613ba7565b609e6020526000908152604090205481565b3480156108e157600080fd5b50609b54610297906001600160a01b031681565b34801561090157600080fd5b506102c4610910366004613d73565b611baa565b34801561092157600080fd5b50609a5461026290600160a01b900460ff1681565b34801561094257600080fd5b506102c4610951366004613ecb565b611c0e565b34801561096257600080fd5b50610262609a54600160a01b900460ff1690565b34801561098257600080fd5b506102c4610991366004613d73565b611c34565b3480156109a257600080fd5b50609a54610297906001600160a01b031681565b3480156109c257600080fd5b506102c46109d1366004613d73565b611c81565b3480156109e257600080fd5b506102c46109f1366004613ba7565b611cce565b348015610a0257600080fd5b506102c4610a11366004613c61565b611cf0565b348015610a2257600080fd5b506102c4610a31366004613d73565b611d7e565b60006001600160e01b03198216637965db0b60e01b1480610a6757506301ffc9a760e01b6001600160e01b03198316145b90505b919050565b600080516020614994833981519152610a8981335b611e6d565b609b54604051630fa857f560e31b815260ff881660048201526001600160a01b0387811660248301526044820187905260648201869052841515608483015290911690637d42bfa89060a401600060405180830381600087803b158015610aef57600080fd5b505af1158015610b03573d6000803e3d6000fd5b50505050505050505050565b600082815260656020526040902060010154610b2b8133610a84565b610b358383611ed1565b505050565b600080516020614994833981519152610b538133610a84565b6001600160a01b0384166000908152609f602052604090205460ff16610b945760405162461bcd60e51b8152600401610b8b9061449c565b60405180910390fd5b506001600160a01b0392909216600090815260a26020908152604080832060ff94851684529091529020805460ff191691909216179055565b6001600160a01b0381163314610c3d5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610b8b565b610c478282611f57565b5050565b6000610c578133610a84565b50609b80546001600160a01b0319166001600160a01b0392909216919091179055565b600080516020614994833981519152610c938133610a84565b6000858152609d60209081526040808320546001600160a01b03166101e086018190528352609f90915281205460ff16610cdf5760405162461bcd60e51b8152600401610b8b906145a7565b826101e001516001600160a01b0316836101c0015160601c6001600160a01b03161415610df6578260e0015183610100015114610d2e5760405162461bcd60e51b8152600401610b8b906144e0565b82516001600160a01b0316610d4f576101e08301516001600160a01b031683525b6000610d5f868560000151611a20565b50609c5485516102a0870151609a54609b546040516304a1d7f960e01b81529597508796506001600160a01b03948516956304a1d7f995610db59594938993600160a01b90910460ff1692911690600401614369565b600060405180830381600087803b158015610dcf57600080fd5b505af1158015610de3573d6000803e3d6000fd5b50505050610df084611fbe565b506111c7565b6101c0830151609c546101e0850151604051635fae924560e01b815260609390931c926001600160a01b0390921691635fae924591610e37916004016142b5565b602060405180830381600087803b158015610e5157600080fd5b505af1158015610e65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e899190613bc3565b6001600160a01b03161415610ed1578260e0015183610100015114610ec05760405162461bcd60e51b8152600401610b8b906144e0565b610eca83866120de565b90506111c7565b82516001600160a01b031615610f77576000610ef1868560000151611a20565b609c5486516102a0880151609a54609b546040516304a1d7f960e01b81529598508897506001600160a01b0394851696506304a1d7f995610f43958993600160a01b900460ff16921690600401614369565b600060405180830381600087803b158015610f5d57600080fd5b505af1158015610f71573d6000803e3d6000fd5b50505050505b609c546101c08401516102a085015160985460e0870151604051634c62b25760e01b81526001600160a01b0395861695634c62b25795610fc59560609190911c9490939116916004016142c9565b600060405180830381600087803b158015610fdf57600080fd5b505af1158015610ff3573d6000803e3d6000fd5b5050505061100083612226565b82516001600160a01b031661112f57600061102086856101e00151611a20565b6101e08601516001600160a01b0316865261010086015190935083925082111590506110aa5760405162461bcd60e51b815260206004820152603360248201527f455243323068616e646c6572203a2070726f766964656420666565206973206c604482015272195cdcc81d1a185b881d1a1948185b5bdd5b9d606a1b6064820152608401610b8b565b808461010001516110bb9190614899565b610100850152609c548451609b54604051630d9aa67b60e31b81526001600160a01b0393841693636cd533d8936110fb9390929116908690600401614345565b600060405180830381600087803b15801561111557600080fd5b505af1158015611129573d6000803e3d6000fd5b50505050505b6101e08301516001600160a01b0316600090815260a0602052604090205460ff16156111c757609c546101e08401516101008501516040516303a4f5ed60e31b81526001600160a01b0390931692631d27af6892611194929091859190600401614345565b600060405180830381600087803b1580156111ae57600080fd5b505af11580156111c2573d6000803e3d6000fd5b505050505b60006111de846101e0015187866101000151611458565b90506000811161122a5760405162461bcd60e51b81526020600482015260176024820152765472616e7366657220616d6f756e7420746f6f206c6f7760481b6044820152606401610b8b565b604051806101e001604052808760ff168152602001856101c0015160601c6001600160a01b03168152602001856101e001516001600160a01b0316815260200185610100015181526020018561022001516001600160a01b0316815260200182815260200185610200015160601c6001600160a01b03168152602001856101400151815260200188815260200185608001516001600160a01b03168152602001856102a001516001600160a01b031681526020018560e00151815260200185600001516001600160a01b03168152602001838152602001856102c00151611312576000611315565b60015b60ff908116909152968716600090815260a1602090815260408083206001600160401b0399909916835297815290879020825181549284015160ff19909316991698909817610100600160a81b0319166101006001600160a01b039283168102919091178955968201516001890180546001600160a01b0319908116928416929092179055606083015160028a0155608083015160038a018054831691841691909117905560a083015160048a015560c083015160058a018054831691841691909117905560e083015160068a015596820151600789015561012082015160088901805489169183169190911790556101408201516009890180548916918316919091179055610160820151600a890155610180820151600b890180549098169116179095555050506101a0820151600c840155506101c00151600d9091015550565b6001600160a01b038316600090815260a26020908152604080832060ff808716855292528220548591166114de5760405162461bcd60e51b815260206004820152602760248201527f446563696d616c73206e6f742073657420666f7220746f6b656e20616e6420636044820152661a185a5b881a5960ca1b6064820152608401610b8b565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561151957600080fd5b505afa15801561152d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155191906140db565b6001600160a01b038716600090815260a26020908152604080832060ff808b168552925290912054919250908116908216811415611594578493505050506115f3565b8060ff168260ff1611156115d05760006115ae82846148b0565b6115b990600a6147a9565b90506115c58187614743565b9450505050506115f3565b60006115dc83836148b0565b6115e790600a6147a9565b90506115c5818761487a565b9392505050565b6000805160206149948339815191526116138133610a84565b610b358383612459565b6000806000805160206149948339815191526116398133610a84565b6000848152609d60209081526040808320546001600160a01b031661022089018190528352609f90915290205460ff166116855760405162461bcd60e51b8152600401610b8b906145a7565b8461022001516001600160a01b031685610200015160601c6001600160a01b031614156116d3576116b5856124bc565b604087015160208801519295509093506116ce91612894565b6117c5565b610200850151609c54610220870151604051635fae924560e01b815260609390931c926001600160a01b0390921691635fae924591611714916004016142b5565b602060405180830381600087803b15801561172e57600080fd5b505af1158015611742573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117669190613bc3565b6001600160a01b031614156117a35761177e856128bc565b84610200015160601c925084610120015191506116ce85604001518660200151612894565b6117ac856128ff565b604087015160208801519295509093506117c591612894565b509250929050565b6000805160206149948339815191526117e68133610a84565b609c546040516330414fc560e11b81526001600160a01b03909116906360829f8a9061181a90879087908790600401614345565b600060405180830381600087803b15801561183457600080fd5b505af1158015611848573d6000803e3d6000fd5b5050505050505050565b60008051602061499483398151915261186b8133610a84565b50609a8054911515600160a01b0260ff60a01b19909216919091179055565b6000805160206149948339815191526118a38133610a84565b609c546040516316e9aed760e11b81526001600160a01b0386811660048301528581166024830152848116604483015290911690632dd35dae9060640161181a565b60009182526065602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6000805160206149948339815191526119298133610a84565b609c54604051631e4a68cf60e11b81526000916001600160a01b031690633c94d19e90611962908a908a908a908a908a9060040161444c565b602060405180830381600087803b15801561197c57600080fd5b505af1158015611990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b49190613bc3565b6001600160a01b0381166000908152609f60205260409020805460ff191660019081179091559091506119e8908290612459565b50505050505050565b60006119fd8133610a84565b50609c80546001600160a01b0319166001600160a01b0392909216919091179055565b609b54604051631eeb344360e21b815260ff841660048201526001600160a01b0383811660248301526000928392911690637bacd10c90604401604080518083038186803b158015611a7157600080fd5b505afa158015611a85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa99190614072565b915091509250929050565b609c5460405163ad527b2160e01b81526001600160a01b0384811660048301528381166024830152600092169063ad527b219060440160206040518083038186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f3919061405a565b600080516020614994833981519152611b538133610a84565b610b35838361319a565b600080516020614994833981519152611b768133610a84565b609c5460405163bf6eac2f60e01b81526001600160a01b039091169063bf6eac2f9061181a90879087908790600401614345565b600080516020614994833981519152611bc38133610a84565b609c54609a54604051636e4b2ac160e11b81526001600160a01b038781166004830152868116602483015260448201869052918216606482015291169063dc9655829060840161181a565b600082815260656020526040902060010154611c2a8133610a84565b610b358383611f57565b600080516020614994833981519152611c4d8133610a84565b609c54604051630d9aa67b60e31b81526001600160a01b0390911690636cd533d89061181a90879087908790600401614345565b600080516020614994833981519152611c9a8133610a84565b609b54604051631095b6d760e01b81526001600160a01b0390911690631095b6d79061181a90879087908790600401614345565b600080516020614994833981519152611ce78133610a84565b610c4782613240565b600054610100900460ff16611d0b5760005460ff1615611d0f565b303b155b611d2b5760405162461bcd60e51b8152600401610b8b9061450e565b600054610100900460ff16158015611d56576000805460ff1961ff0019909116610100171660011790555b611d648787878787876132cd565b80156119e8576000805461ff001916905550505050505050565b600080516020614994833981519152611d978133610a84565b609a54609c5460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92611dcd929116908690600401614420565b602060405180830381600087803b158015611de757600080fd5b505af1158015611dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1f9190613e97565b611e3957634e487b7160e01b600052600160045260246000fd5b609c5460405163f4e480e160e01b81526001600160a01b039091169063f4e480e19061181a90879087908790600401614345565b611e7782826118e5565b610c4757611e8f816001600160a01b031660146134da565b611e9a8360206134da565b604051602001611eab929190614246565b60408051601f198184030181529082905262461bcd60e51b8252610b8b91600401614439565b611edb82826118e5565b610c475760008281526065602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611f133390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b611f6182826118e5565b15610c475760008281526065602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6101c081015160601c600090815260a0602052604090205460ff161561205d57609c546101c08201516102a083015160e08401516040516303a4f5ed60e31b81526001600160a01b0390941693631d27af68936120269360609190911c929091600401614345565b600060405180830381600087803b15801561204057600080fd5b505af1158015612054573d6000803e3d6000fd5b505050506120db565b609c546101c08201516102a083015160e0840151604051634c62b25760e01b81526001600160a01b0390941693634c62b257936120a89360609190911c9290918691906004016142c9565b600060405180830381600087803b1580156120c257600080fd5b505af11580156120d6573d6000803e3d6000fd5b505050505b50565b81516000906001600160a01b0316612114576101c083015160601c83526101e083015161210c908390611a20565b509050612126565b612122828460000151611a20565b5090505b609c5483516102a0850151609a54609b546040516304a1d7f960e01b81526001600160a01b03958616956304a1d7f99561217695909490938993600160a01b90920460ff16921690600401614369565b600060405180830381600087803b15801561219057600080fd5b505af11580156121a4573d6000803e3d6000fd5b5050609c546101c08601516102a087015160e08801516040516303a4f5ed60e31b81526001600160a01b039094169550631d27af6894506121ee9360609390931c92600401614345565b600060405180830381600087803b15801561220857600080fd5b505af115801561221c573d6000803e3d6000fd5b5050505092915050565b61028081015151600281111561234757816101e001516001600160a01b03168261028001516001836122589190614899565b8151811061227657634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161461229157600080fd5b609c5460985461028084015160e0850151610100860151610260870151610240880151604051632214e13b60e01b81526001600160a01b0397881697632214e13b976122ea97911695909490939092909160040161439b565b602060405180830381600087803b15801561230457600080fd5b505af1158015612318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233c919061405a565b610100830152610c47565b609c546098546101c08401516101e085015160e086015161010087015161026088015180516001600160a01b039788169763da041a8597169560601c94939291906000906123a557634e487b7160e01b600052603260045260246000fd5b60200260200101518961024001516000815181106123d357634e487b7160e01b600052603260045260246000fd5b60200260200101516040518863ffffffff1660e01b81526004016123fd97969594939291906142f3565b602060405180830381600087803b15801561241757600080fd5b505af115801561242b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244f919061405a565b6101008301525050565b6001600160a01b0382166000908152609f602052604090205460ff166124915760405162461bcd60e51b8152600401610b8b9061449c565b6001600160a01b0391909116600090815260a060205260409020805460ff1916911515919091179055565b61020081015160601c600090815260a06020526040812054819060ff161561255d57609c5461020084015160808501516101208601516040516308f80fd160e31b81526001600160a01b03909416936347c07e88936125269360609190911c929091600401614345565b600060405180830381600087803b15801561254057600080fd5b505af1158015612554573d6000803e3d6000fd5b50505050612880565b610220830151609c546040516370a0823160e01b81526000926001600160a01b03908116926370a082319261259892909116906004016142b5565b60206040518083038186803b1580156125b057600080fd5b505afa1580156125c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e8919061405a565b905083610120015181101561270257609c546102208501516080860151610120870151604051632b9cd63d60e11b81526001600160a01b0390941693635739ac7a9361263a9390929091600401614345565b600060405180830381600087803b15801561265457600080fd5b505af1158015612668573d6000803e3d6000fd5b5050609c54610220870151604051635fae924560e01b81526001600160a01b039092169350635fae924592506126a0916004016142b5565b602060405180830381600087803b1580156126ba57600080fd5b505af11580156126ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f29190613bc3565b846101200151925092505061288f565b609a546102208501516001600160a01b0390811691161480156127275750836102c001515b1561280857609c54609a546101208601516040516324c44ed760e21b81526001600160a01b03938416936393113b5c9361276693911691600401614420565b600060405180830381600087803b15801561278057600080fd5b505af1158015612794573d6000803e3d6000fd5b5050609c546080870151610120880151604051637c4368c160e01b81526001600160a01b039093169450637c4368c193506127d192600401614420565b600060405180830381600087803b1580156127eb57600080fd5b505af11580156127ff573d6000803e3d6000fd5b5050505061287e565b609c546102208501516080860151610120870151604051630d9aa67b60e31b81526001600160a01b0390941693636cd533d89361284b9390929091600401614345565b600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b505050505b505b50506102208101516101208201515b915091565b600091825260a3602090815260408084206001600160401b0390931684529190529020439055565b609c546102208201516080830151610120840151604051632b9cd63d60e11b81526001600160a01b0390941693635739ac7a936120a89390929091600401614345565b6102208101516001600160a01b0316600090815260a06020526040812054819060ff1615612a935760028361028001515111801561298b5750610200830151610280840151805160609290921c9161295990600190614899565b8151811061297757634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614155b15612a1a57609c5461022084015160808501516101208601516040516308f80fd160e31b81526001600160a01b03909416936347c07e88936129d39390929091600401614345565b600060405180830381600087803b1580156129ed57600080fd5b505af1158015612a01573d6000803e3d6000fd5b505050508261022001518361012001519150915061288f565b609c546102208401516098546101208601516040516308f80fd160e31b81526001600160a01b03948516946347c07e8894612a5c949093911691600401614345565b600060405180830381600087803b158015612a7657600080fd5b505af1158015612a8a573d6000803e3d6000fd5b50505050612cda565b610220830151609c546040516370a0823160e01b81526000926001600160a01b03908116926370a0823192612ace92909116906004016142b5565b60206040518083038186803b158015612ae657600080fd5b505afa158015612afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b1e919061405a565b9050836101200151811015612b7057609c546102208501516080860151610120870151604051632b9cd63d60e11b81526001600160a01b0390941693635739ac7a9361263a9390929091600401614345565b600284610280015151118015612bd45750610200840151610280850151805160609290921c91612ba290600190614899565b81518110612bc057634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614155b15612c6457609c546102208501516080860151610120870151604051630d9aa67b60e31b81526001600160a01b0390941693636cd533d893612c1c9390929091600401614345565b600060405180830381600087803b158015612c3657600080fd5b505af1158015612c4a573d6000803e3d6000fd5b50505050836102200151846101200151925092505061288f565b609c54610220850151609854610120870151604051630d9aa67b60e31b81526001600160a01b0394851694636cd533d894612ca6949093911691600401614345565b600060405180830381600087803b158015612cc057600080fd5b505af1158015612cd4573d6000803e3d6000fd5b50505050505b6002836102800151511115612e9f57609c5460985461028085015161012086015161014087015161026088015161024089015160405160009788976001600160a01b0391821697632214e13b97612d3f9793909216959094919390919060240161439b565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051612d78919061422a565b6000604051808303816000865af19150503d8060008114612db5576040519150601f19603f3d011682016040523d82523d6000602084013e612dba565b606091505b50915091508115612de35780806020019051810190612dd9919061405a565b6060860152612e98565b6098546102208601516080870151610120880151604051636ce5768960e11b81526001600160a01b039094169363d9caed1293612e269390929091600401614345565b602060405180830381600087803b158015612e4057600080fd5b505af1158015612e54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e789190613e97565b612e8157600080fd5b84610220015185610120015193509350505061288f565b505061300b565b600080609c60009054906101000a90046001600160a01b03166001600160a01b031663da041a85609860009054906101000a90046001600160a01b031687610220015188610200015160601c8961012001518a61014001518b6102600151600081518110612f1d57634e487b7160e01b600052603260045260246000fd5b60200260200101518c6102400151600081518110612f4b57634e487b7160e01b600052603260045260246000fd5b6020026020010151604051602401612f6997969594939291906142f3565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051612fa2919061422a565b6000604051808303816000865af19150503d8060008114612fdf576040519150601f19603f3d011682016040523d82523d6000602084013e612fe4565b606091505b50915091508115612de35780806020019051810190613003919061405a565b606086015250505b609a5461020084015160601c6001600160a01b039091161480156130315750826102c001515b1561311057609c54609a5460608501516040516324c44ed760e21b81526001600160a01b03938416936393113b5c9361306f93911691600401614420565b600060405180830381600087803b15801561308957600080fd5b505af115801561309d573d6000803e3d6000fd5b5050609c5460808601516060870151604051637c4368c160e01b81526001600160a01b039093169450637c4368c193506130d992600401614420565b600060405180830381600087803b1580156130f357600080fd5b505af1158015613107573d6000803e3d6000fd5b50505050613187565b609c546102008401516080850151606080870151604051630d9aa67b60e31b81526001600160a01b0390951694636cd533d89461315494931c929190600401614345565b600060405180830381600087803b15801561316e57600080fd5b505af1158015613182573d6000803e3d6000fd5b505050505b5050610200810151606091820151911c91565b6001600160a01b0381166131f05760405162461bcd60e51b815260206004820152601e60248201527f636f6e747261637420616464726573732063616e2774206265207a65726f00006044820152606401610b8b565b6000828152609d6020908152604080832080546001600160a01b039095166001600160a01b031990951685179055928252609e815282822093909355609f9092529020805460ff19166001179055565b6001600160a01b0381166132ab5760405162461bcd60e51b815260206004820152602c60248201527f455243323048616e646c65723a20636f6e74726163744164647265737320636160448201526b1b9b9bdd081899481b9d5b1b60a21b6064820152608401610b8b565b609880546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166132e85760005460ff16156132ec565b303b155b6133085760405162461bcd60e51b8152600401610b8b9061450e565b600054610100900460ff16158015613333576000805460ff1961ff0019909116610100171660011790555b61333b6136bb565b6133436136e4565b82518451146133b75760405162461bcd60e51b815260206004820152603a60248201527f696e697469616c5265736f75726365494473202620696e697469616c436f6e746044820152790e4c2c6e882c8c8e4cae6e6cae640d8cadc40dad2e6dac2e8c6d60331b6064820152608401610b8b565b609780546001600160a01b03808a166001600160a01b03199283161790925560998054898416908316179055609a805492881692909116919091179055835160005b8181101561346b5761345986828151811061342457634e487b7160e01b600052603260045260246000fd5b602002602001015186838151811061344c57634e487b7160e01b600052603260045260246000fd5b602002602001015161319a565b806134638161491a565b9150506133f9565b50825160005b818110156134bd576134ab85828151811061349c57634e487b7160e01b600052603260045260246000fd5b60200260200101516001612459565b806134b58161491a565b915050613471565b50505080156119e8576000805461ff001916905550505050505050565b606060006134e983600261487a565b6134f490600261472b565b6001600160401b0381111561351957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613543576020820181803683370190505b509050600360fc1b8160008151811061356c57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106135a957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060006135cd84600261487a565b6135d890600161472b565b90505b600181111561366c576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061361a57634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061363e57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361366581614903565b90506135db565b5083156115f35760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610b8b565b600054610100900460ff166136e25760405162461bcd60e51b8152600401610b8b9061455c565b565b600054610100900460ff166136ff5760005460ff1615613703565b303b155b61371f5760405162461bcd60e51b8152600401610b8b9061450e565b600054610100900460ff1615801561374a576000805460ff1961ff0019909116610100171660011790555b6137526136bb565b61375a61379e565b6137656000336137dd565b61377d600080516020614994833981519152336137dd565b609a805460ff60a01b1916905580156120db576000805461ff001916905550565b600054610100900460ff166137c55760405162461bcd60e51b8152600401610b8b9061455c565b6137cd6136bb565b6137d56136bb565b6136e26136bb565b610c478282611ed1565b60006001600160401b038311156138005761380061494b565b613813601f8401601f19166020016146d8565b905082815283838301111561382757600080fd5b828260208301376000602084830101529392505050565b8035610a6a81614961565b600082601f830112613859578081fd5b8135602061386e61386983614708565b6146d8565b828152818101908583018385028701840188101561388a578586fd5b855b858110156138b157813561389f81614961565b8452928401929084019060010161388c565b5090979650505050505050565b600082601f8301126138ce578081fd5b813560206138de61386983614708565b82815281810190858301855b858110156138b1578135880189603f820112613904578788fd5b6139158a87830135604084016137e7565b85525092840192908401906001016138ea565b600082601f830112613938578081fd5b8135602061394861386983614708565b8281528181019085830183850287018401881015613964578586fd5b855b858110156138b157813584529284019290840190600101613966565b8035610a6a81614976565b80356001600160601b031981168114610a6a57600080fd5b600082601f8301126139b5578081fd5b6115f3838335602085016137e7565b60006103008083850312156139d7578182fd5b6139e0816146d8565b9150506139ec8261383e565b81526139fa60208301613b90565b60208201526040820135604082015260608201356060820152613a1f6080830161383e565b6080820152613a3060a0830161383e565b60a0820152613a4160c0830161383e565b60c082015260e08281013590820152610100808301359082015261012080830135908201526101408083013590820152610160808301359082015261018080830135908201526101a080830135908201526101c0613aa081840161398d565b908201526101e0613ab283820161383e565b90820152610200613ac483820161398d565b90820152610220613ad683820161383e565b90820152610240828101356001600160401b0380821115613af657600080fd5b613b02868387016138be565b83850152610260925082850135915080821115613b1e57600080fd5b613b2a86838701613928565b83850152610280925082850135915080821115613b4657600080fd5b50613b5385828601613849565b8284015250506102a0613b6781840161383e565b908201526102c0613b79838201613982565b81830152506102e080830135818301525092915050565b80356001600160401b0381168114610a6a57600080fd5b600060208284031215613bb8578081fd5b81356115f381614961565b600060208284031215613bd4578081fd5b81516115f381614961565b60008060408385031215613bf1578081fd5b8235613bfc81614961565b91506020830135613c0c81614961565b809150509250929050565b600080600060608486031215613c2b578081fd5b8335613c3681614961565b92506020840135613c4681614961565b91506040840135613c5681614961565b809150509250925092565b60008060008060008060c08789031215613c79578384fd5b8635613c8481614961565b9550602087810135613c9581614961565b95506040880135613ca581614961565b945060608801356001600160401b0380821115613cc0578485fd5b818a0191508a601f830112613cd3578485fd5b8135613ce161386982614708565b81815284810190848601868402860187018f1015613cfd578889fd5b8895505b83861015613d1f578035835260019590950194918601918601613d01565b509750505060808a0135925080831115613d37578485fd5b613d438b848c01613849565b945060a08a0135925080831115613d58578384fd5b5050613d6689828a01613849565b9150509295509295509295565b600080600060608486031215613d87578081fd5b8335613d9281614961565b92506020840135613da281614961565b929592945050506040919091013590565b60008060408385031215613dc5578182fd5b8235613dd081614961565b91506020830135613c0c81614976565b60008060408385031215613df2578182fd5b8235613dfd81614961565b91506020830135613c0c81614984565b600080600060608486031215613e21578081fd5b8335613e2c81614961565b92506020840135613da281614984565b600080600060608486031215613e50578081fd5b8335613e5b81614961565b92506020840135613e6b81614984565b91506040840135613c5681614984565b600060208284031215613e8c578081fd5b81356115f381614976565b600060208284031215613ea8578081fd5b81516115f381614976565b600060208284031215613ec4578081fd5b5035919050565b60008060408385031215613edd578182fd5b823591506020830135613c0c81614961565b60008060008060808587031215613f04578182fd5b843593506020850135613f1681614984565b9250613f2460408601613b90565b915060608501356001600160401b03811115613f3e578182fd5b613f4a878288016139c4565b91505092959194509250565b600060208284031215613f67578081fd5b81356001600160e01b0319811681146115f3578182fd5b600080600080600060a08688031215613f95578283fd5b85356001600160401b0380821115613fab578485fd5b613fb789838a016139a5565b96506020880135915080821115613fcc578485fd5b50613fd9888289016139a5565b9450506040860135613fea81614984565b92506060860135613ffa81614961565b9150608086013561400a81614961565b809150509295509295909350565b6000806040838503121561402a578182fd5b82356001600160401b0381111561403f578283fd5b61404b858286016139c4565b95602094909401359450505050565b60006020828403121561406b578081fd5b5051919050565b60008060408385031215614084578182fd5b505080516020909101519092909150565b600080604083850312156140a7578182fd5b823591506140b760208401613b90565b90509250929050565b600080604083850312156140d2578182fd5b613dfd83613b90565b6000602082840312156140ec578081fd5b81516115f381614984565b60008060408385031215614109578182fd5b8235613bfc81614984565b600080600080600060a0868803121561412b578283fd5b853561413681614984565b9450602086013561414681614961565b93506040860135925060608601359150608086013561400a81614976565b6001600160a01b03169052565b6000815180845260208085018081965082840281019150828601855b858110156141b75782840389526141a58483516141fe565b9885019893509084019060010161418d565b5091979650505050505050565b6000815180845260208085019450808401835b838110156141f3578151875295820195908201906001016141d7565b509495945050505050565b600081518084526142168160208601602086016148d3565b601f01601f19169290920160200192915050565b6000825161423c8184602087016148d3565b9190910192915050565b600076020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b825283516142788160178501602088016148d3565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516142a98160288401602088016148d3565b01602801949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b600060018060a01b03808a16835280891660208401528088166040840152508560608301528460808301528360a083015260e060c083015261433860e08301846141fe565b9998505050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0395861681529385166020850152604084019290925215156060830152909116608082015260a00190565b6001600160a01b03878116825260c0602080840182905288519184018290526000928982019290919060e0860190855b818110156143e95785518516835294830194918301916001016143cb565b5050896040870152886060870152858103608087015261440981896141c4565b935050505082810360a08401526143388185614171565b6001600160a01b03929092168252602082015260400190565b6000602082526115f360208301846141fe565b600060a0825261445f60a08301886141fe565b828103602084015261447181886141fe565b60ff96909616604084015250506001600160a01b039283166060820152911660809091015292915050565b60208082526024908201527f70726f766964656420636f6e7472616374206973206e6f742077686974656c696040820152631cdd195960e21b606082015260800190565b602080825260149082015273125b9d985b1a59081d1bdad95b88185b5bdd5b9d60621b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526028908201527f70726f766964656420746f6b656e41646472657373206973206e6f74207768696040820152671d195b1a5cdd195960c21b606082015260800190565b815160ff1681526101e08101602083015161460d6020840182614164565b5060408301516146206040840182614164565b5060608301516060830152608083015161463d6080840182614164565b5060a083015160a083015260c083015161465a60c0840182614164565b5060e083015160e08301526101008084015181840152506101208084015161468482850182614164565b50506101408084015161469982850182614164565b50506101608381015190830152610180808401516146b982850182614164565b50506101a083810151908301526101c092830151929091019190915290565b604051601f8201601f191681016001600160401b03811182821017156147005761470061494b565b604052919050565b60006001600160401b038211156147215761472161494b565b5060209081020190565b6000821982111561473e5761473e614935565b500190565b60008261475e57634e487b7160e01b81526012600452602481fd5b500490565b80825b600180861161477557506147a0565b81870482111561478757614787614935565b8086161561479457918102915b9490941c938002614766565b94509492505050565b60006115f360001960ff8516846000826147c5575060016115f3565b816147d2575060006115f3565b81600181146147e857600281146147f25761481f565b60019150506115f3565b60ff84111561480357614803614935565b6001841b91508482111561481957614819614935565b506115f3565b5060208310610133831016604e8410600b8410161715614852575081810a8381111561484d5761484d614935565b6115f3565b61485f8484846001614763565b80860482111561487157614871614935565b02949350505050565b600081600019048311821515161561489457614894614935565b500290565b6000828210156148ab576148ab614935565b500390565b600060ff821660ff8416808210156148ca576148ca614935565b90039392505050565b60005b838110156148ee5781810151838201526020016148d6565b838111156148fd576000848401525b50505050565b60008161491257614912614935565b506000190190565b600060001982141561492e5761492e614935565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146120db57600080fd5b80151581146120db57600080fd5b60ff811681146120db57600080fdfe52ba824bfabc2bcfcdf7f0edbb486ebb05e1836c90e78047efeb949990f72e5fa164736f6c6343000802000a
Deployed ByteCode
0x6080604052600436106102365760003560e01c80639680504c1161012f578063c8ba6c87116100b1578063c8ba6c87146108a8578063d0fb0203146108d5578063d3fad208146108f5578063d3ff209d14610915578063d547741f14610936578063d755c34914610956578063d9caed1214610976578063e0af361614610996578063e55dc4e6146109b6578063e7c308fd146109d6578063eae9befc146109f6578063f4e480e114610a165761023d565b80639680504c1461058857806397e76aab146105a85780639cecc80a146105e05780639e601b3114610600578063a217fddf14610635578063a6fd91ee1461064a578063ad527b2114610697578063b5bfddea146106b7578063b8fa3736146106d9578063ba484c09146106f9578063bf6eac2f146108885761023d565b80634a266160116101b85780634a266160146103fa578063536187d61461041a5780635d92c1ac1461043a5780635db99af21461045a5780635f624fbd1461047a57806360829f8a146104a85780636a70d081146104c85780636be1dc2b146104f85780637f79bea8146105185780637ffb45fa1461054857806391d14854146105685761023d565b806301ffc9a7146102425780630ab75d3e146102775780631487001b146102a4578063248a9ca3146102c65780632f2ff15d14610304578063318c136e14610324578063359d86011461034457806335d0d5dc1461036457806336568abe1461039a578063413ab4a8146103ba578063472d35b9146103da5761023d565b3661023d57005b600080fd5b34801561024e57600080fd5b5061026261025d366004613f56565b610a36565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b50609854610297906001600160a01b031681565b60405161026e91906142b5565b3480156102b057600080fd5b506102c46102bf366004614114565b610a6f565b005b3480156102d257600080fd5b506102f66102e1366004613eb3565b60009081526065602052604090206001015490565b60405190815260200161026e565b34801561031057600080fd5b506102c461031f366004613ecb565b610b0f565b34801561033057600080fd5b50609754610297906001600160a01b031681565b34801561035057600080fd5b506102c461035f366004613e3c565b610b3a565b34801561037057600080fd5b5061029761037f366004613eb3565b6000908152609d60205260409020546001600160a01b031690565b3480156103a657600080fd5b506102c46103b5366004613ecb565b610bcd565b3480156103c657600080fd5b50609c54610297906001600160a01b031681565b3480156103e657600080fd5b506102c46103f5366004613ba7565b610c4b565b34801561040657600080fd5b506102c4610415366004613eef565b610c7a565b34801561042657600080fd5b506102f6610435366004613e0d565b611458565b34801561044657600080fd5b506102c4610455366004613db3565b6115fa565b34801561046657600080fd5b50609954610297906001600160a01b031681565b34801561048657600080fd5b5061049a610495366004614018565b61161d565b60405161026e929190614420565b3480156104b457600080fd5b506102c46104c3366004613d73565b6117cd565b3480156104d457600080fd5b506102626104e3366004613ba7565b60a06020526000908152604090205460ff1681565b34801561050457600080fd5b506102c4610513366004613e7b565b611852565b34801561052457600080fd5b50610262610533366004613ba7565b609f6020526000908152604090205460ff1681565b34801561055457600080fd5b506102c4610563366004613c17565b61188a565b34801561057457600080fd5b50610262610583366004613ecb565b6118e5565b34801561059457600080fd5b506102c46105a3366004613f7e565b611910565b3480156105b457600080fd5b506102f66105c3366004614095565b60a360209081526000928352604080842090915290825290205481565b3480156105ec57600080fd5b506102c46105fb366004613ba7565b6119f1565b34801561060c57600080fd5b5061062061061b3660046140f7565b611a20565b6040805192835260208301919091520161026e565b34801561064157600080fd5b506102f6600081565b34801561065657600080fd5b50610685610665366004613de0565b60a260209081526000928352604080842090915290825290205460ff1681565b60405160ff909116815260200161026e565b3480156106a357600080fd5b506102f66106b2366004613bdf565b611ab4565b3480156106c357600080fd5b506102f660008051602061499483398151915281565b3480156106e557600080fd5b506102c46106f4366004613ecb565b611b3a565b34801561070557600080fd5b5061087b6107143660046140c0565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c08101919091525060ff908116600090815260a1602090815260408083206001600160401b039590951683529381529083902083516101e08101855281549384168152610100938490046001600160a01b0390811693820193909352600182015483169481019490945260028101546060850152600381015482166080850152600481015460a08501526005810154821660c0850152600681015460e08501526007810154928401929092526008820154811661012084015260098201548116610140840152600a820154610160840152600b82015416610180830152600c8101546101a0830152600d01546101c082015290565b60405161026e91906145ef565b34801561089457600080fd5b506102c46108a3366004613d73565b611b5d565b3480156108b457600080fd5b506102f66108c3366004613ba7565b609e6020526000908152604090205481565b3480156108e157600080fd5b50609b54610297906001600160a01b031681565b34801561090157600080fd5b506102c4610910366004613d73565b611baa565b34801561092157600080fd5b50609a5461026290600160a01b900460ff1681565b34801561094257600080fd5b506102c4610951366004613ecb565b611c0e565b34801561096257600080fd5b50610262609a54600160a01b900460ff1690565b34801561098257600080fd5b506102c4610991366004613d73565b611c34565b3480156109a257600080fd5b50609a54610297906001600160a01b031681565b3480156109c257600080fd5b506102c46109d1366004613d73565b611c81565b3480156109e257600080fd5b506102c46109f1366004613ba7565b611cce565b348015610a0257600080fd5b506102c4610a11366004613c61565b611cf0565b348015610a2257600080fd5b506102c4610a31366004613d73565b611d7e565b60006001600160e01b03198216637965db0b60e01b1480610a6757506301ffc9a760e01b6001600160e01b03198316145b90505b919050565b600080516020614994833981519152610a8981335b611e6d565b609b54604051630fa857f560e31b815260ff881660048201526001600160a01b0387811660248301526044820187905260648201869052841515608483015290911690637d42bfa89060a401600060405180830381600087803b158015610aef57600080fd5b505af1158015610b03573d6000803e3d6000fd5b50505050505050505050565b600082815260656020526040902060010154610b2b8133610a84565b610b358383611ed1565b505050565b600080516020614994833981519152610b538133610a84565b6001600160a01b0384166000908152609f602052604090205460ff16610b945760405162461bcd60e51b8152600401610b8b9061449c565b60405180910390fd5b506001600160a01b0392909216600090815260a26020908152604080832060ff94851684529091529020805460ff191691909216179055565b6001600160a01b0381163314610c3d5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610b8b565b610c478282611f57565b5050565b6000610c578133610a84565b50609b80546001600160a01b0319166001600160a01b0392909216919091179055565b600080516020614994833981519152610c938133610a84565b6000858152609d60209081526040808320546001600160a01b03166101e086018190528352609f90915281205460ff16610cdf5760405162461bcd60e51b8152600401610b8b906145a7565b826101e001516001600160a01b0316836101c0015160601c6001600160a01b03161415610df6578260e0015183610100015114610d2e5760405162461bcd60e51b8152600401610b8b906144e0565b82516001600160a01b0316610d4f576101e08301516001600160a01b031683525b6000610d5f868560000151611a20565b50609c5485516102a0870151609a54609b546040516304a1d7f960e01b81529597508796506001600160a01b03948516956304a1d7f995610db59594938993600160a01b90910460ff1692911690600401614369565b600060405180830381600087803b158015610dcf57600080fd5b505af1158015610de3573d6000803e3d6000fd5b50505050610df084611fbe565b506111c7565b6101c0830151609c546101e0850151604051635fae924560e01b815260609390931c926001600160a01b0390921691635fae924591610e37916004016142b5565b602060405180830381600087803b158015610e5157600080fd5b505af1158015610e65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e899190613bc3565b6001600160a01b03161415610ed1578260e0015183610100015114610ec05760405162461bcd60e51b8152600401610b8b906144e0565b610eca83866120de565b90506111c7565b82516001600160a01b031615610f77576000610ef1868560000151611a20565b609c5486516102a0880151609a54609b546040516304a1d7f960e01b81529598508897506001600160a01b0394851696506304a1d7f995610f43958993600160a01b900460ff16921690600401614369565b600060405180830381600087803b158015610f5d57600080fd5b505af1158015610f71573d6000803e3d6000fd5b50505050505b609c546101c08401516102a085015160985460e0870151604051634c62b25760e01b81526001600160a01b0395861695634c62b25795610fc59560609190911c9490939116916004016142c9565b600060405180830381600087803b158015610fdf57600080fd5b505af1158015610ff3573d6000803e3d6000fd5b5050505061100083612226565b82516001600160a01b031661112f57600061102086856101e00151611a20565b6101e08601516001600160a01b0316865261010086015190935083925082111590506110aa5760405162461bcd60e51b815260206004820152603360248201527f455243323068616e646c6572203a2070726f766964656420666565206973206c604482015272195cdcc81d1a185b881d1a1948185b5bdd5b9d606a1b6064820152608401610b8b565b808461010001516110bb9190614899565b610100850152609c548451609b54604051630d9aa67b60e31b81526001600160a01b0393841693636cd533d8936110fb9390929116908690600401614345565b600060405180830381600087803b15801561111557600080fd5b505af1158015611129573d6000803e3d6000fd5b50505050505b6101e08301516001600160a01b0316600090815260a0602052604090205460ff16156111c757609c546101e08401516101008501516040516303a4f5ed60e31b81526001600160a01b0390931692631d27af6892611194929091859190600401614345565b600060405180830381600087803b1580156111ae57600080fd5b505af11580156111c2573d6000803e3d6000fd5b505050505b60006111de846101e0015187866101000151611458565b90506000811161122a5760405162461bcd60e51b81526020600482015260176024820152765472616e7366657220616d6f756e7420746f6f206c6f7760481b6044820152606401610b8b565b604051806101e001604052808760ff168152602001856101c0015160601c6001600160a01b03168152602001856101e001516001600160a01b0316815260200185610100015181526020018561022001516001600160a01b0316815260200182815260200185610200015160601c6001600160a01b03168152602001856101400151815260200188815260200185608001516001600160a01b03168152602001856102a001516001600160a01b031681526020018560e00151815260200185600001516001600160a01b03168152602001838152602001856102c00151611312576000611315565b60015b60ff908116909152968716600090815260a1602090815260408083206001600160401b0399909916835297815290879020825181549284015160ff19909316991698909817610100600160a81b0319166101006001600160a01b039283168102919091178955968201516001890180546001600160a01b0319908116928416929092179055606083015160028a0155608083015160038a018054831691841691909117905560a083015160048a015560c083015160058a018054831691841691909117905560e083015160068a015596820151600789015561012082015160088901805489169183169190911790556101408201516009890180548916918316919091179055610160820151600a890155610180820151600b890180549098169116179095555050506101a0820151600c840155506101c00151600d9091015550565b6001600160a01b038316600090815260a26020908152604080832060ff808716855292528220548591166114de5760405162461bcd60e51b815260206004820152602760248201527f446563696d616c73206e6f742073657420666f7220746f6b656e20616e6420636044820152661a185a5b881a5960ca1b6064820152608401610b8b565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561151957600080fd5b505afa15801561152d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155191906140db565b6001600160a01b038716600090815260a26020908152604080832060ff808b168552925290912054919250908116908216811415611594578493505050506115f3565b8060ff168260ff1611156115d05760006115ae82846148b0565b6115b990600a6147a9565b90506115c58187614743565b9450505050506115f3565b60006115dc83836148b0565b6115e790600a6147a9565b90506115c5818761487a565b9392505050565b6000805160206149948339815191526116138133610a84565b610b358383612459565b6000806000805160206149948339815191526116398133610a84565b6000848152609d60209081526040808320546001600160a01b031661022089018190528352609f90915290205460ff166116855760405162461bcd60e51b8152600401610b8b906145a7565b8461022001516001600160a01b031685610200015160601c6001600160a01b031614156116d3576116b5856124bc565b604087015160208801519295509093506116ce91612894565b6117c5565b610200850151609c54610220870151604051635fae924560e01b815260609390931c926001600160a01b0390921691635fae924591611714916004016142b5565b602060405180830381600087803b15801561172e57600080fd5b505af1158015611742573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117669190613bc3565b6001600160a01b031614156117a35761177e856128bc565b84610200015160601c925084610120015191506116ce85604001518660200151612894565b6117ac856128ff565b604087015160208801519295509093506117c591612894565b509250929050565b6000805160206149948339815191526117e68133610a84565b609c546040516330414fc560e11b81526001600160a01b03909116906360829f8a9061181a90879087908790600401614345565b600060405180830381600087803b15801561183457600080fd5b505af1158015611848573d6000803e3d6000fd5b5050505050505050565b60008051602061499483398151915261186b8133610a84565b50609a8054911515600160a01b0260ff60a01b19909216919091179055565b6000805160206149948339815191526118a38133610a84565b609c546040516316e9aed760e11b81526001600160a01b0386811660048301528581166024830152848116604483015290911690632dd35dae9060640161181a565b60009182526065602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6000805160206149948339815191526119298133610a84565b609c54604051631e4a68cf60e11b81526000916001600160a01b031690633c94d19e90611962908a908a908a908a908a9060040161444c565b602060405180830381600087803b15801561197c57600080fd5b505af1158015611990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b49190613bc3565b6001600160a01b0381166000908152609f60205260409020805460ff191660019081179091559091506119e8908290612459565b50505050505050565b60006119fd8133610a84565b50609c80546001600160a01b0319166001600160a01b0392909216919091179055565b609b54604051631eeb344360e21b815260ff841660048201526001600160a01b0383811660248301526000928392911690637bacd10c90604401604080518083038186803b158015611a7157600080fd5b505afa158015611a85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa99190614072565b915091509250929050565b609c5460405163ad527b2160e01b81526001600160a01b0384811660048301528381166024830152600092169063ad527b219060440160206040518083038186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f3919061405a565b600080516020614994833981519152611b538133610a84565b610b35838361319a565b600080516020614994833981519152611b768133610a84565b609c5460405163bf6eac2f60e01b81526001600160a01b039091169063bf6eac2f9061181a90879087908790600401614345565b600080516020614994833981519152611bc38133610a84565b609c54609a54604051636e4b2ac160e11b81526001600160a01b038781166004830152868116602483015260448201869052918216606482015291169063dc9655829060840161181a565b600082815260656020526040902060010154611c2a8133610a84565b610b358383611f57565b600080516020614994833981519152611c4d8133610a84565b609c54604051630d9aa67b60e31b81526001600160a01b0390911690636cd533d89061181a90879087908790600401614345565b600080516020614994833981519152611c9a8133610a84565b609b54604051631095b6d760e01b81526001600160a01b0390911690631095b6d79061181a90879087908790600401614345565b600080516020614994833981519152611ce78133610a84565b610c4782613240565b600054610100900460ff16611d0b5760005460ff1615611d0f565b303b155b611d2b5760405162461bcd60e51b8152600401610b8b9061450e565b600054610100900460ff16158015611d56576000805460ff1961ff0019909116610100171660011790555b611d648787878787876132cd565b80156119e8576000805461ff001916905550505050505050565b600080516020614994833981519152611d978133610a84565b609a54609c5460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92611dcd929116908690600401614420565b602060405180830381600087803b158015611de757600080fd5b505af1158015611dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1f9190613e97565b611e3957634e487b7160e01b600052600160045260246000fd5b609c5460405163f4e480e160e01b81526001600160a01b039091169063f4e480e19061181a90879087908790600401614345565b611e7782826118e5565b610c4757611e8f816001600160a01b031660146134da565b611e9a8360206134da565b604051602001611eab929190614246565b60408051601f198184030181529082905262461bcd60e51b8252610b8b91600401614439565b611edb82826118e5565b610c475760008281526065602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611f133390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b611f6182826118e5565b15610c475760008281526065602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6101c081015160601c600090815260a0602052604090205460ff161561205d57609c546101c08201516102a083015160e08401516040516303a4f5ed60e31b81526001600160a01b0390941693631d27af68936120269360609190911c929091600401614345565b600060405180830381600087803b15801561204057600080fd5b505af1158015612054573d6000803e3d6000fd5b505050506120db565b609c546101c08201516102a083015160e0840151604051634c62b25760e01b81526001600160a01b0390941693634c62b257936120a89360609190911c9290918691906004016142c9565b600060405180830381600087803b1580156120c257600080fd5b505af11580156120d6573d6000803e3d6000fd5b505050505b50565b81516000906001600160a01b0316612114576101c083015160601c83526101e083015161210c908390611a20565b509050612126565b612122828460000151611a20565b5090505b609c5483516102a0850151609a54609b546040516304a1d7f960e01b81526001600160a01b03958616956304a1d7f99561217695909490938993600160a01b90920460ff16921690600401614369565b600060405180830381600087803b15801561219057600080fd5b505af11580156121a4573d6000803e3d6000fd5b5050609c546101c08601516102a087015160e08801516040516303a4f5ed60e31b81526001600160a01b039094169550631d27af6894506121ee9360609390931c92600401614345565b600060405180830381600087803b15801561220857600080fd5b505af115801561221c573d6000803e3d6000fd5b5050505092915050565b61028081015151600281111561234757816101e001516001600160a01b03168261028001516001836122589190614899565b8151811061227657634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161461229157600080fd5b609c5460985461028084015160e0850151610100860151610260870151610240880151604051632214e13b60e01b81526001600160a01b0397881697632214e13b976122ea97911695909490939092909160040161439b565b602060405180830381600087803b15801561230457600080fd5b505af1158015612318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233c919061405a565b610100830152610c47565b609c546098546101c08401516101e085015160e086015161010087015161026088015180516001600160a01b039788169763da041a8597169560601c94939291906000906123a557634e487b7160e01b600052603260045260246000fd5b60200260200101518961024001516000815181106123d357634e487b7160e01b600052603260045260246000fd5b60200260200101516040518863ffffffff1660e01b81526004016123fd97969594939291906142f3565b602060405180830381600087803b15801561241757600080fd5b505af115801561242b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244f919061405a565b6101008301525050565b6001600160a01b0382166000908152609f602052604090205460ff166124915760405162461bcd60e51b8152600401610b8b9061449c565b6001600160a01b0391909116600090815260a060205260409020805460ff1916911515919091179055565b61020081015160601c600090815260a06020526040812054819060ff161561255d57609c5461020084015160808501516101208601516040516308f80fd160e31b81526001600160a01b03909416936347c07e88936125269360609190911c929091600401614345565b600060405180830381600087803b15801561254057600080fd5b505af1158015612554573d6000803e3d6000fd5b50505050612880565b610220830151609c546040516370a0823160e01b81526000926001600160a01b03908116926370a082319261259892909116906004016142b5565b60206040518083038186803b1580156125b057600080fd5b505afa1580156125c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e8919061405a565b905083610120015181101561270257609c546102208501516080860151610120870151604051632b9cd63d60e11b81526001600160a01b0390941693635739ac7a9361263a9390929091600401614345565b600060405180830381600087803b15801561265457600080fd5b505af1158015612668573d6000803e3d6000fd5b5050609c54610220870151604051635fae924560e01b81526001600160a01b039092169350635fae924592506126a0916004016142b5565b602060405180830381600087803b1580156126ba57600080fd5b505af11580156126ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f29190613bc3565b846101200151925092505061288f565b609a546102208501516001600160a01b0390811691161480156127275750836102c001515b1561280857609c54609a546101208601516040516324c44ed760e21b81526001600160a01b03938416936393113b5c9361276693911691600401614420565b600060405180830381600087803b15801561278057600080fd5b505af1158015612794573d6000803e3d6000fd5b5050609c546080870151610120880151604051637c4368c160e01b81526001600160a01b039093169450637c4368c193506127d192600401614420565b600060405180830381600087803b1580156127eb57600080fd5b505af11580156127ff573d6000803e3d6000fd5b5050505061287e565b609c546102208501516080860151610120870151604051630d9aa67b60e31b81526001600160a01b0390941693636cd533d89361284b9390929091600401614345565b600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b505050505b505b50506102208101516101208201515b915091565b600091825260a3602090815260408084206001600160401b0390931684529190529020439055565b609c546102208201516080830151610120840151604051632b9cd63d60e11b81526001600160a01b0390941693635739ac7a936120a89390929091600401614345565b6102208101516001600160a01b0316600090815260a06020526040812054819060ff1615612a935760028361028001515111801561298b5750610200830151610280840151805160609290921c9161295990600190614899565b8151811061297757634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614155b15612a1a57609c5461022084015160808501516101208601516040516308f80fd160e31b81526001600160a01b03909416936347c07e88936129d39390929091600401614345565b600060405180830381600087803b1580156129ed57600080fd5b505af1158015612a01573d6000803e3d6000fd5b505050508261022001518361012001519150915061288f565b609c546102208401516098546101208601516040516308f80fd160e31b81526001600160a01b03948516946347c07e8894612a5c949093911691600401614345565b600060405180830381600087803b158015612a7657600080fd5b505af1158015612a8a573d6000803e3d6000fd5b50505050612cda565b610220830151609c546040516370a0823160e01b81526000926001600160a01b03908116926370a0823192612ace92909116906004016142b5565b60206040518083038186803b158015612ae657600080fd5b505afa158015612afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b1e919061405a565b9050836101200151811015612b7057609c546102208501516080860151610120870151604051632b9cd63d60e11b81526001600160a01b0390941693635739ac7a9361263a9390929091600401614345565b600284610280015151118015612bd45750610200840151610280850151805160609290921c91612ba290600190614899565b81518110612bc057634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614155b15612c6457609c546102208501516080860151610120870151604051630d9aa67b60e31b81526001600160a01b0390941693636cd533d893612c1c9390929091600401614345565b600060405180830381600087803b158015612c3657600080fd5b505af1158015612c4a573d6000803e3d6000fd5b50505050836102200151846101200151925092505061288f565b609c54610220850151609854610120870151604051630d9aa67b60e31b81526001600160a01b0394851694636cd533d894612ca6949093911691600401614345565b600060405180830381600087803b158015612cc057600080fd5b505af1158015612cd4573d6000803e3d6000fd5b50505050505b6002836102800151511115612e9f57609c5460985461028085015161012086015161014087015161026088015161024089015160405160009788976001600160a01b0391821697632214e13b97612d3f9793909216959094919390919060240161439b565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051612d78919061422a565b6000604051808303816000865af19150503d8060008114612db5576040519150601f19603f3d011682016040523d82523d6000602084013e612dba565b606091505b50915091508115612de35780806020019051810190612dd9919061405a565b6060860152612e98565b6098546102208601516080870151610120880151604051636ce5768960e11b81526001600160a01b039094169363d9caed1293612e269390929091600401614345565b602060405180830381600087803b158015612e4057600080fd5b505af1158015612e54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e789190613e97565b612e8157600080fd5b84610220015185610120015193509350505061288f565b505061300b565b600080609c60009054906101000a90046001600160a01b03166001600160a01b031663da041a85609860009054906101000a90046001600160a01b031687610220015188610200015160601c8961012001518a61014001518b6102600151600081518110612f1d57634e487b7160e01b600052603260045260246000fd5b60200260200101518c6102400151600081518110612f4b57634e487b7160e01b600052603260045260246000fd5b6020026020010151604051602401612f6997969594939291906142f3565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051612fa2919061422a565b6000604051808303816000865af19150503d8060008114612fdf576040519150601f19603f3d011682016040523d82523d6000602084013e612fe4565b606091505b50915091508115612de35780806020019051810190613003919061405a565b606086015250505b609a5461020084015160601c6001600160a01b039091161480156130315750826102c001515b1561311057609c54609a5460608501516040516324c44ed760e21b81526001600160a01b03938416936393113b5c9361306f93911691600401614420565b600060405180830381600087803b15801561308957600080fd5b505af115801561309d573d6000803e3d6000fd5b5050609c5460808601516060870151604051637c4368c160e01b81526001600160a01b039093169450637c4368c193506130d992600401614420565b600060405180830381600087803b1580156130f357600080fd5b505af1158015613107573d6000803e3d6000fd5b50505050613187565b609c546102008401516080850151606080870151604051630d9aa67b60e31b81526001600160a01b0390951694636cd533d89461315494931c929190600401614345565b600060405180830381600087803b15801561316e57600080fd5b505af1158015613182573d6000803e3d6000fd5b505050505b5050610200810151606091820151911c91565b6001600160a01b0381166131f05760405162461bcd60e51b815260206004820152601e60248201527f636f6e747261637420616464726573732063616e2774206265207a65726f00006044820152606401610b8b565b6000828152609d6020908152604080832080546001600160a01b039095166001600160a01b031990951685179055928252609e815282822093909355609f9092529020805460ff19166001179055565b6001600160a01b0381166132ab5760405162461bcd60e51b815260206004820152602c60248201527f455243323048616e646c65723a20636f6e74726163744164647265737320636160448201526b1b9b9bdd081899481b9d5b1b60a21b6064820152608401610b8b565b609880546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166132e85760005460ff16156132ec565b303b155b6133085760405162461bcd60e51b8152600401610b8b9061450e565b600054610100900460ff16158015613333576000805460ff1961ff0019909116610100171660011790555b61333b6136bb565b6133436136e4565b82518451146133b75760405162461bcd60e51b815260206004820152603a60248201527f696e697469616c5265736f75726365494473202620696e697469616c436f6e746044820152790e4c2c6e882c8c8e4cae6e6cae640d8cadc40dad2e6dac2e8c6d60331b6064820152608401610b8b565b609780546001600160a01b03808a166001600160a01b03199283161790925560998054898416908316179055609a805492881692909116919091179055835160005b8181101561346b5761345986828151811061342457634e487b7160e01b600052603260045260246000fd5b602002602001015186838151811061344c57634e487b7160e01b600052603260045260246000fd5b602002602001015161319a565b806134638161491a565b9150506133f9565b50825160005b818110156134bd576134ab85828151811061349c57634e487b7160e01b600052603260045260246000fd5b60200260200101516001612459565b806134b58161491a565b915050613471565b50505080156119e8576000805461ff001916905550505050505050565b606060006134e983600261487a565b6134f490600261472b565b6001600160401b0381111561351957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613543576020820181803683370190505b509050600360fc1b8160008151811061356c57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106135a957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060006135cd84600261487a565b6135d890600161472b565b90505b600181111561366c576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061361a57634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061363e57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361366581614903565b90506135db565b5083156115f35760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610b8b565b600054610100900460ff166136e25760405162461bcd60e51b8152600401610b8b9061455c565b565b600054610100900460ff166136ff5760005460ff1615613703565b303b155b61371f5760405162461bcd60e51b8152600401610b8b9061450e565b600054610100900460ff1615801561374a576000805460ff1961ff0019909116610100171660011790555b6137526136bb565b61375a61379e565b6137656000336137dd565b61377d600080516020614994833981519152336137dd565b609a805460ff60a01b1916905580156120db576000805461ff001916905550565b600054610100900460ff166137c55760405162461bcd60e51b8152600401610b8b9061455c565b6137cd6136bb565b6137d56136bb565b6136e26136bb565b610c478282611ed1565b60006001600160401b038311156138005761380061494b565b613813601f8401601f19166020016146d8565b905082815283838301111561382757600080fd5b828260208301376000602084830101529392505050565b8035610a6a81614961565b600082601f830112613859578081fd5b8135602061386e61386983614708565b6146d8565b828152818101908583018385028701840188101561388a578586fd5b855b858110156138b157813561389f81614961565b8452928401929084019060010161388c565b5090979650505050505050565b600082601f8301126138ce578081fd5b813560206138de61386983614708565b82815281810190858301855b858110156138b1578135880189603f820112613904578788fd5b6139158a87830135604084016137e7565b85525092840192908401906001016138ea565b600082601f830112613938578081fd5b8135602061394861386983614708565b8281528181019085830183850287018401881015613964578586fd5b855b858110156138b157813584529284019290840190600101613966565b8035610a6a81614976565b80356001600160601b031981168114610a6a57600080fd5b600082601f8301126139b5578081fd5b6115f3838335602085016137e7565b60006103008083850312156139d7578182fd5b6139e0816146d8565b9150506139ec8261383e565b81526139fa60208301613b90565b60208201526040820135604082015260608201356060820152613a1f6080830161383e565b6080820152613a3060a0830161383e565b60a0820152613a4160c0830161383e565b60c082015260e08281013590820152610100808301359082015261012080830135908201526101408083013590820152610160808301359082015261018080830135908201526101a080830135908201526101c0613aa081840161398d565b908201526101e0613ab283820161383e565b90820152610200613ac483820161398d565b90820152610220613ad683820161383e565b90820152610240828101356001600160401b0380821115613af657600080fd5b613b02868387016138be565b83850152610260925082850135915080821115613b1e57600080fd5b613b2a86838701613928565b83850152610280925082850135915080821115613b4657600080fd5b50613b5385828601613849565b8284015250506102a0613b6781840161383e565b908201526102c0613b79838201613982565b81830152506102e080830135818301525092915050565b80356001600160401b0381168114610a6a57600080fd5b600060208284031215613bb8578081fd5b81356115f381614961565b600060208284031215613bd4578081fd5b81516115f381614961565b60008060408385031215613bf1578081fd5b8235613bfc81614961565b91506020830135613c0c81614961565b809150509250929050565b600080600060608486031215613c2b578081fd5b8335613c3681614961565b92506020840135613c4681614961565b91506040840135613c5681614961565b809150509250925092565b60008060008060008060c08789031215613c79578384fd5b8635613c8481614961565b9550602087810135613c9581614961565b95506040880135613ca581614961565b945060608801356001600160401b0380821115613cc0578485fd5b818a0191508a601f830112613cd3578485fd5b8135613ce161386982614708565b81815284810190848601868402860187018f1015613cfd578889fd5b8895505b83861015613d1f578035835260019590950194918601918601613d01565b509750505060808a0135925080831115613d37578485fd5b613d438b848c01613849565b945060a08a0135925080831115613d58578384fd5b5050613d6689828a01613849565b9150509295509295509295565b600080600060608486031215613d87578081fd5b8335613d9281614961565b92506020840135613da281614961565b929592945050506040919091013590565b60008060408385031215613dc5578182fd5b8235613dd081614961565b91506020830135613c0c81614976565b60008060408385031215613df2578182fd5b8235613dfd81614961565b91506020830135613c0c81614984565b600080600060608486031215613e21578081fd5b8335613e2c81614961565b92506020840135613da281614984565b600080600060608486031215613e50578081fd5b8335613e5b81614961565b92506020840135613e6b81614984565b91506040840135613c5681614984565b600060208284031215613e8c578081fd5b81356115f381614976565b600060208284031215613ea8578081fd5b81516115f381614976565b600060208284031215613ec4578081fd5b5035919050565b60008060408385031215613edd578182fd5b823591506020830135613c0c81614961565b60008060008060808587031215613f04578182fd5b843593506020850135613f1681614984565b9250613f2460408601613b90565b915060608501356001600160401b03811115613f3e578182fd5b613f4a878288016139c4565b91505092959194509250565b600060208284031215613f67578081fd5b81356001600160e01b0319811681146115f3578182fd5b600080600080600060a08688031215613f95578283fd5b85356001600160401b0380821115613fab578485fd5b613fb789838a016139a5565b96506020880135915080821115613fcc578485fd5b50613fd9888289016139a5565b9450506040860135613fea81614984565b92506060860135613ffa81614961565b9150608086013561400a81614961565b809150509295509295909350565b6000806040838503121561402a578182fd5b82356001600160401b0381111561403f578283fd5b61404b858286016139c4565b95602094909401359450505050565b60006020828403121561406b578081fd5b5051919050565b60008060408385031215614084578182fd5b505080516020909101519092909150565b600080604083850312156140a7578182fd5b823591506140b760208401613b90565b90509250929050565b600080604083850312156140d2578182fd5b613dfd83613b90565b6000602082840312156140ec578081fd5b81516115f381614984565b60008060408385031215614109578182fd5b8235613bfc81614984565b600080600080600060a0868803121561412b578283fd5b853561413681614984565b9450602086013561414681614961565b93506040860135925060608601359150608086013561400a81614976565b6001600160a01b03169052565b6000815180845260208085018081965082840281019150828601855b858110156141b75782840389526141a58483516141fe565b9885019893509084019060010161418d565b5091979650505050505050565b6000815180845260208085019450808401835b838110156141f3578151875295820195908201906001016141d7565b509495945050505050565b600081518084526142168160208601602086016148d3565b601f01601f19169290920160200192915050565b6000825161423c8184602087016148d3565b9190910192915050565b600076020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b825283516142788160178501602088016148d3565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516142a98160288401602088016148d3565b01602801949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b600060018060a01b03808a16835280891660208401528088166040840152508560608301528460808301528360a083015260e060c083015261433860e08301846141fe565b9998505050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0395861681529385166020850152604084019290925215156060830152909116608082015260a00190565b6001600160a01b03878116825260c0602080840182905288519184018290526000928982019290919060e0860190855b818110156143e95785518516835294830194918301916001016143cb565b5050896040870152886060870152858103608087015261440981896141c4565b935050505082810360a08401526143388185614171565b6001600160a01b03929092168252602082015260400190565b6000602082526115f360208301846141fe565b600060a0825261445f60a08301886141fe565b828103602084015261447181886141fe565b60ff96909616604084015250506001600160a01b039283166060820152911660809091015292915050565b60208082526024908201527f70726f766964656420636f6e7472616374206973206e6f742077686974656c696040820152631cdd195960e21b606082015260800190565b602080825260149082015273125b9d985b1a59081d1bdad95b88185b5bdd5b9d60621b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526028908201527f70726f766964656420746f6b656e41646472657373206973206e6f74207768696040820152671d195b1a5cdd195960c21b606082015260800190565b815160ff1681526101e08101602083015161460d6020840182614164565b5060408301516146206040840182614164565b5060608301516060830152608083015161463d6080840182614164565b5060a083015160a083015260c083015161465a60c0840182614164565b5060e083015160e08301526101008084015181840152506101208084015161468482850182614164565b50506101408084015161469982850182614164565b50506101608381015190830152610180808401516146b982850182614164565b50506101a083810151908301526101c092830151929091019190915290565b604051601f8201601f191681016001600160401b03811182821017156147005761470061494b565b604052919050565b60006001600160401b038211156147215761472161494b565b5060209081020190565b6000821982111561473e5761473e614935565b500190565b60008261475e57634e487b7160e01b81526012600452602481fd5b500490565b80825b600180861161477557506147a0565b81870482111561478757614787614935565b8086161561479457918102915b9490941c938002614766565b94509492505050565b60006115f360001960ff8516846000826147c5575060016115f3565b816147d2575060006115f3565b81600181146147e857600281146147f25761481f565b60019150506115f3565b60ff84111561480357614803614935565b6001841b91508482111561481957614819614935565b506115f3565b5060208310610133831016604e8410600b8410161715614852575081810a8381111561484d5761484d614935565b6115f3565b61485f8484846001614763565b80860482111561487157614871614935565b02949350505050565b600081600019048311821515161561489457614894614935565b500290565b6000828210156148ab576148ab614935565b500390565b600060ff821660ff8416808210156148ca576148ca614935565b90039392505050565b60005b838110156148ee5781810151838201526020016148d6565b838111156148fd576000848401525b50505050565b60008161491257614912614935565b506000190190565b600060001982141561492e5761492e614935565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146120db57600080fd5b80151581146120db57600080fd5b60ff811681146120db57600080fdfe52ba824bfabc2bcfcdf7f0edbb486ebb05e1836c90e78047efeb949990f72e5fa164736f6c6343000802000a