c474952dec744e7c88dc7c3d2b8d163f.json 240 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. {
  2. "language": "Solidity",
  3. "sources": {
  4. "contracts/Bridge.sol": {
  5. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\n// imports\r\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\r\n\r\nimport \"./Pool.sol\";\r\nimport \"./Router.sol\";\r\n\r\n// libraries\r\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\r\nimport \"./interfaces/ILayerZeroReceiver.sol\";\r\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\r\nimport \"./interfaces/ILayerZeroUserApplicationConfig.sol\";\r\n\r\ncontract Bridge is Ownable, ILayerZeroReceiver, ILayerZeroUserApplicationConfig {\r\n using SafeMath for uint256;\r\n\r\n //---------------------------------------------------------------------------\r\n // CONSTANTS\r\n uint8 internal constant TYPE_SWAP_REMOTE = 1;\r\n uint8 internal constant TYPE_ADD_LIQUIDITY = 2;\r\n uint8 internal constant TYPE_REDEEM_LOCAL_CALL_BACK = 3;\r\n uint8 internal constant TYPE_WITHDRAW_REMOTE = 4;\r\n\r\n //---------------------------------------------------------------------------\r\n // VARIABLES\r\n ILayerZeroEndpoint public immutable layerZeroEndpoint;\r\n mapping(uint16 => bytes) public bridgeLookup;\r\n mapping(uint16 => mapping(uint8 => uint256)) public gasLookup;\r\n Router public immutable router;\r\n bool public useLayerZeroToken;\r\n\r\n //---------------------------------------------------------------------------\r\n // EVENTS\r\n event SendMsg(uint8 msgType, uint64 nonce);\r\n\r\n //---------------------------------------------------------------------------\r\n // MODIFIERS\r\n modifier onlyRouter() {\r\n require(msg.sender == address(router), \"Mirrorgate: caller must be Router.\");\r\n _;\r\n }\r\n\r\n constructor(address _layerZeroEndpoint, address _router) {\r\n require(_layerZeroEndpoint != address(0x0), \"Mirrorgate: _layerZeroEndpoint cannot be 0x0\");\r\n require(_router != address(0x0), \"Mirrorgate: _router cannot be 0x0\");\r\n layerZeroEndpoint = ILayerZeroEndpoint(_layerZeroEndpoint);\r\n router = Router(_router);\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // EXTERNAL functions\r\n\r\n function lzReceive(\r\n uint16 _srcChainId,\r\n bytes memory _srcAddress,\r\n uint64 _nonce,\r\n bytes memory _payload\r\n ) external override {\r\n require(msg.sender == address(layerZeroEndpoint), \"Mirrorgate: only LayerZero endpoint can call lzReceive\");\r\n require(\r\n _srcAddress.length == bridgeLookup[_srcChainId].length && keccak256(_srcAddress) == keccak256(bridgeLookup[_srcChainId]),\r\n \"Mirrorgate: bridge does not match\"\r\n );\r\n\r\n uint8 functionType;\r\n assembly {\r\n functionType := mload(add(_payload, 32))\r\n }\r\n\r\n if (functionType == TYPE_SWAP_REMOTE) {\r\n (\r\n ,\r\n uint256 srcPoolId,\r\n uint256 dstPoolId,\r\n uint256 dstGasForCall,\r\n Pool.CreditObj memory c,\r\n Pool.SwapObj memory s,\r\n bytes memory to,\r\n bytes memory payload\r\n ) = abi.decode(_payload, (uint8, uint256, uint256, uint256, Pool.CreditObj, Pool.SwapObj, bytes, bytes));\r\n address toAddress;\r\n assembly {\r\n toAddress := mload(add(to, 20))\r\n }\r\n router.creditChainPath(_srcChainId, srcPoolId, dstPoolId, c);\r\n router.swapRemote(_srcChainId, _srcAddress, _nonce, srcPoolId, dstPoolId, dstGasForCall, toAddress, s, payload);\r\n } else if (functionType == TYPE_ADD_LIQUIDITY) {\r\n (, uint256 srcPoolId, uint256 dstPoolId, Pool.CreditObj memory c) = abi.decode(_payload, (uint8, uint256, uint256, Pool.CreditObj));\r\n router.creditChainPath(_srcChainId, srcPoolId, dstPoolId, c);\r\n } else if (functionType == TYPE_REDEEM_LOCAL_CALL_BACK) {\r\n (, uint256 srcPoolId, uint256 dstPoolId, Pool.CreditObj memory c, uint256 amountSD, uint256 mintAmountSD, bytes memory to) = abi\r\n .decode(_payload, (uint8, uint256, uint256, Pool.CreditObj, uint256, uint256, bytes));\r\n address toAddress;\r\n assembly {\r\n toAddress := mload(add(to, 20))\r\n }\r\n router.creditChainPath(_srcChainId, srcPoolId, dstPoolId, c);\r\n router.redeemLocalCallback(_srcChainId, _srcAddress, _nonce, srcPoolId, dstPoolId, toAddress, amountSD, mintAmountSD);\r\n } else if (functionType == TYPE_WITHDRAW_REMOTE) {\r\n (, uint256 srcPoolId, uint256 dstPoolId, Pool.CreditObj memory c, uint256 amountSD, bytes memory to) = abi.decode(\r\n _payload,\r\n (uint8, uint256, uint256, Pool.CreditObj, uint256, bytes)\r\n );\r\n router.creditChainPath(_srcChainId, srcPoolId, dstPoolId, c);\r\n router.redeemLocalCheckOnRemote(_srcChainId, _srcAddress, _nonce, srcPoolId, dstPoolId, amountSD, to);\r\n }\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // LOCAL CHAIN FUNCTIONS\r\n function swap(\r\n uint16 _chainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n Pool.CreditObj memory _c,\r\n Pool.SwapObj memory _s,\r\n IMirrorgateRouter.lzTxObj memory _lzTxParams,\r\n bytes calldata _to,\r\n bytes calldata _payload\r\n ) external payable onlyRouter {\r\n bytes memory payload = abi.encode(TYPE_SWAP_REMOTE, _srcPoolId, _dstPoolId, _lzTxParams.dstGasForCall, _c, _s, _to, _payload);\r\n _call(_chainId, TYPE_SWAP_REMOTE, _refundAddress, _lzTxParams, payload);\r\n }\r\n\r\n function redeemLocalCallback(\r\n uint16 _chainId,\r\n address payable _refundAddress,\r\n Pool.CreditObj memory _c,\r\n IMirrorgateRouter.lzTxObj memory _lzTxParams,\r\n bytes memory _payload\r\n ) external payable onlyRouter {\r\n bytes memory payload;\r\n\r\n {\r\n (, uint256 srcPoolId, uint256 dstPoolId, uint256 amountSD, uint256 mintAmountSD, bytes memory to) = abi.decode(\r\n _payload,\r\n (uint8, uint256, uint256, uint256, uint256, bytes)\r\n );\r\n\r\n // swap dst and src because we are headed back\r\n payload = abi.encode(TYPE_REDEEM_LOCAL_CALL_BACK, dstPoolId, srcPoolId, _c, amountSD, mintAmountSD, to);\r\n }\r\n\r\n _call(_chainId, TYPE_REDEEM_LOCAL_CALL_BACK, _refundAddress, _lzTxParams, payload);\r\n }\r\n\r\n function redeemLocal(\r\n uint16 _chainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n Pool.CreditObj memory _c,\r\n uint256 _amountSD,\r\n bytes calldata _to,\r\n IMirrorgateRouter.lzTxObj memory _lzTxParams\r\n ) external payable onlyRouter {\r\n bytes memory payload = abi.encode(TYPE_WITHDRAW_REMOTE, _srcPoolId, _dstPoolId, _c, _amountSD, _to);\r\n _call(_chainId, TYPE_WITHDRAW_REMOTE, _refundAddress, _lzTxParams, payload);\r\n }\r\n\r\n function sendCredits(\r\n uint16 _chainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n Pool.CreditObj memory _c\r\n ) external payable onlyRouter {\r\n bytes memory payload = abi.encode(TYPE_ADD_LIQUIDITY, _srcPoolId, _dstPoolId, _c);\r\n IMirrorgateRouter.lzTxObj memory lzTxObj = IMirrorgateRouter.lzTxObj(0, 0, \"0x\");\r\n _call(_chainId, TYPE_ADD_LIQUIDITY, _refundAddress, lzTxObj, payload);\r\n }\r\n\r\n function quoteLayerZeroFee(\r\n uint16 _chainId,\r\n uint8 _functionType,\r\n bytes calldata _toAddress,\r\n bytes calldata _transferAndCallPayload,\r\n IMirrorgateRouter.lzTxObj memory _lzTxParams\r\n ) external view returns (uint256, uint256) {\r\n bytes memory payload = \"\";\r\n Pool.CreditObj memory c = Pool.CreditObj(1, 1);\r\n if (_functionType == TYPE_SWAP_REMOTE) {\r\n Pool.SwapObj memory s = Pool.SwapObj(1, 1, 1, 1, 1, 1);\r\n payload = abi.encode(TYPE_SWAP_REMOTE, 0, 0, 0, c, s, _toAddress, _transferAndCallPayload);\r\n } else if (_functionType == TYPE_ADD_LIQUIDITY) {\r\n payload = abi.encode(TYPE_ADD_LIQUIDITY, 0, 0, c);\r\n } else if (_functionType == TYPE_REDEEM_LOCAL_CALL_BACK) {\r\n payload = abi.encode(TYPE_REDEEM_LOCAL_CALL_BACK, 0, 0, c, 0, 0, _toAddress);\r\n } else if (_functionType == TYPE_WITHDRAW_REMOTE) {\r\n payload = abi.encode(TYPE_WITHDRAW_REMOTE, 0, 0, c, 0, _toAddress);\r\n } else {\r\n revert(\"Mirrorgate: unsupported function type\");\r\n }\r\n\r\n bytes memory lzTxParamBuilt = _txParamBuilder(_chainId, _functionType, _lzTxParams);\r\n return layerZeroEndpoint.estimateFees(_chainId, address(this), payload, useLayerZeroToken, lzTxParamBuilt);\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // dao functions\r\n function setBridge(uint16 _chainId, bytes calldata _bridgeAddress) external onlyOwner {\r\n require(bridgeLookup[_chainId].length == 0, \"Mirrorgate: Bridge already set!\");\r\n bridgeLookup[_chainId] = _bridgeAddress;\r\n }\r\n\r\n function setGasAmount(\r\n uint16 _chainId,\r\n uint8 _functionType,\r\n uint256 _gasAmount\r\n ) external onlyOwner {\r\n require(_functionType >= 1 && _functionType <= 4, \"Mirrorgate: invalid _functionType\");\r\n gasLookup[_chainId][_functionType] = _gasAmount;\r\n }\r\n\r\n function approveTokenSpender(\r\n address token,\r\n address spender,\r\n uint256 amount\r\n ) external onlyOwner {\r\n IERC20(token).approve(spender, amount);\r\n }\r\n\r\n function setUseLayerZeroToken(bool enable) external onlyOwner {\r\n useLayerZeroToken = enable;\r\n }\r\n\r\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner {\r\n layerZeroEndpoint.forceResumeReceive(_srcChainId, _srcAddress);\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // generic config for user Application\r\n function setConfig(\r\n uint16 _version,\r\n uint16 _chainId,\r\n uint256 _configType,\r\n bytes calldata _config\r\n ) external override onlyOwner {\r\n layerZeroEndpoint.setConfig(_version, _chainId, _configType, _config);\r\n }\r\n\r\n function setSendVersion(uint16 version) external override onlyOwner {\r\n layerZeroEndpoint.setSendVersion(version);\r\n }\r\n\r\n function setReceiveVersion(uint16 version) external override onlyOwner {\r\n layerZeroEndpoint.setReceiveVersion(version);\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // INTERNAL functions\r\n function txParamBuilderType1(uint256 _gasAmount) internal pure returns (bytes memory) {\r\n uint16 txType = 1;\r\n return abi.encodePacked(txType, _gasAmount);\r\n }\r\n\r\n function txParamBuilderType2(\r\n uint256 _gasAmount,\r\n uint256 _dstNativeAmount,\r\n bytes memory _dstNativeAddr\r\n ) internal pure returns (bytes memory) {\r\n uint16 txType = 2;\r\n return abi.encodePacked(txType, _gasAmount, _dstNativeAmount, _dstNativeAddr);\r\n }\r\n\r\n function _txParamBuilder(\r\n uint16 _chainId,\r\n uint8 _type,\r\n IMirrorgateRouter.lzTxObj memory _lzTxParams\r\n ) internal view returns (bytes memory) {\r\n bytes memory lzTxParam;\r\n address dstNativeAddr;\r\n {\r\n bytes memory dstNativeAddrBytes = _lzTxParams.dstNativeAddr;\r\n assembly {\r\n dstNativeAddr := mload(add(dstNativeAddrBytes, 20))\r\n }\r\n }\r\n\r\n uint256 totalGas = gasLookup[_chainId][_type].add(_lzTxParams.dstGasForCall);\r\n if (_lzTxParams.dstNativeAmount > 0 && dstNativeAddr != address(0x0)) {\r\n lzTxParam = txParamBuilderType2(totalGas, _lzTxParams.dstNativeAmount, _lzTxParams.dstNativeAddr);\r\n } else {\r\n lzTxParam = txParamBuilderType1(totalGas);\r\n }\r\n\r\n return lzTxParam;\r\n }\r\n\r\n function _call(\r\n uint16 _chainId,\r\n uint8 _type,\r\n address payable _refundAddress,\r\n IMirrorgateRouter.lzTxObj memory _lzTxParams,\r\n bytes memory _payload\r\n ) internal {\r\n bytes memory lzTxParamBuilt = _txParamBuilder(_chainId, _type, _lzTxParams);\r\n uint64 nextNonce = layerZeroEndpoint.getOutboundNonce(_chainId, address(this)) + 1;\r\n layerZeroEndpoint.send{value: msg.value}(_chainId, bridgeLookup[_chainId], _payload, _refundAddress, address(this), lzTxParamBuilt);\r\n emit SendMsg(_type, nextNonce);\r\n }\r\n\r\n function renounceOwnership() public override onlyOwner {}\r\n}\r\n"
  6. },
  7. "@openzeppelin/contracts/access/Ownable.sol": {
  8. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n"
  9. },
  10. "contracts/Pool.sol": {
  11. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\n// imports\r\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\r\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\r\nimport \"./LPTokenERC20.sol\";\r\nimport \"./interfaces/IMirrorgateFeeLibrary.sol\";\r\n\r\n// libraries\r\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\r\n\r\n/// Pool contracts on other chains and managed by the Stargate protocol.\r\ncontract Pool is LPTokenERC20, ReentrancyGuard {\r\n using SafeMath for uint256;\r\n\r\n //---------------------------------------------------------------------------\r\n // CONSTANTS\r\n bytes4 private constant SELECTOR = bytes4(keccak256(bytes(\"transfer(address,uint256)\")));\r\n uint256 public constant BP_DENOMINATOR = 10000;\r\n\r\n //---------------------------------------------------------------------------\r\n // STRUCTS\r\n struct ChainPath {\r\n bool ready; // indicate if the counter chainPath has been created.\r\n uint16 dstChainId;\r\n uint256 dstPoolId;\r\n uint256 weight;\r\n uint256 balance;\r\n uint256 lkb;\r\n uint256 credits;\r\n uint256 idealBalance;\r\n }\r\n\r\n struct SwapObj {\r\n uint256 amount;\r\n uint256 eqFee;\r\n uint256 eqReward;\r\n uint256 lpFee;\r\n uint256 protocolFee;\r\n uint256 lkbRemove;\r\n }\r\n\r\n struct CreditObj {\r\n uint256 credits;\r\n uint256 idealBalance;\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // VARIABLES\r\n\r\n // chainPath\r\n ChainPath[] public chainPaths; // list of connected chains with shared pools\r\n mapping(uint16 => mapping(uint256 => uint256)) public chainPathIndexLookup; // lookup for chainPath by chainId => poolId =>index\r\n\r\n // metadata\r\n uint256 public immutable poolId; // shared id between chains to represent same pool\r\n uint256 public sharedDecimals; // the shared decimals (lowest common decimals between chains)\r\n uint256 public localDecimals; // the decimals for the token\r\n uint256 public immutable convertRate; // the decimals for the token\r\n address public immutable token; // the token for the pool\r\n address public immutable router; // the token for the pool\r\n\r\n bool public stopSwap; // flag to stop swapping in extreme cases\r\n\r\n // Fee and Liquidity\r\n uint256 public totalLiquidity; // the total amount of tokens added on this side of the chain (fees + deposits - withdrawals)\r\n uint256 public totalWeight; // total weight for pool percentages\r\n uint256 public mintFeeBP; // fee basis points for the mint/deposit\r\n uint256 public protocolFeeBalance; // fee balance created from dao fee\r\n uint256 public mintFeeBalance; // fee balance created from mint fee\r\n uint256 public eqFeePool; // pool rewards in Shared Decimal format. indicate the total budget for reverse swap incentive\r\n address public feeLibrary; // address for retrieving fee params for swaps\r\n\r\n // Delta related\r\n uint256 public deltaCredit; // credits accumulated from txn\r\n bool public batched; // flag to indicate if we want batch processing.\r\n bool public defaultSwapMode; // flag for the default mode for swap\r\n bool public defaultLPMode; // flag for the default mode for lp\r\n uint256 public swapDeltaBP; // basis points of poolCredits to activate Delta in swap\r\n uint256 public lpDeltaBP; // basis points of poolCredits to activate Delta in liquidity events\r\n\r\n //---------------------------------------------------------------------------\r\n // EVENTS\r\n event Mint(address to, uint256 amountLP, uint256 amountSD, uint256 mintFeeAmountSD);\r\n event Burn(address from, uint256 amountLP, uint256 amountSD);\r\n event RedeemLocalCallback(address _to, uint256 _amountSD, uint256 _amountToMintSD);\r\n event Swap(\r\n uint16 chainId,\r\n uint256 dstPoolId,\r\n address from,\r\n uint256 amountSD,\r\n uint256 eqReward,\r\n uint256 eqFee,\r\n uint256 protocolFee,\r\n uint256 lpFee\r\n );\r\n event SendCredits(uint16 dstChainId, uint256 dstPoolId, uint256 credits, uint256 idealBalance);\r\n event RedeemRemote(uint16 chainId, uint256 dstPoolId, address from, uint256 amountLP, uint256 amountSD);\r\n event RedeemLocal(address from, uint256 amountLP, uint256 amountSD, uint16 chainId, uint256 dstPoolId, bytes to);\r\n event InstantRedeemLocal(address from, uint256 amountLP, uint256 amountSD, address to);\r\n event CreditChainPath(uint16 chainId, uint256 srcPoolId, uint256 amountSD, uint256 idealBalance);\r\n event SwapRemote(address to, uint256 amountSD, uint256 protocolFee, uint256 dstFee);\r\n event WithdrawRemote(uint16 srcChainId, uint256 srcPoolId, uint256 swapAmount, uint256 mintAmount);\r\n event ChainPathUpdate(uint16 dstChainId, uint256 dstPoolId, uint256 weight);\r\n event FeesUpdated(uint256 mintFeeBP);\r\n event FeeLibraryUpdated(address feeLibraryAddr);\r\n event StopSwapUpdated(bool swapStop);\r\n event WithdrawProtocolFeeBalance(address to, uint256 amountSD);\r\n event WithdrawMintFeeBalance(address to, uint256 amountSD);\r\n event DeltaParamUpdated(bool batched, uint256 swapDeltaBP, uint256 lpDeltaBP, bool defaultSwapMode, bool defaultLPMode);\r\n\r\n //---------------------------------------------------------------------------\r\n // MODIFIERS\r\n modifier onlyRouter() {\r\n require(msg.sender == router, \"Mirrorgate: only the router can call this method\");\r\n _;\r\n }\r\n\r\n constructor(\r\n uint256 _poolId,\r\n address _router,\r\n address _token,\r\n uint256 _sharedDecimals,\r\n uint256 _localDecimals,\r\n address _feeLibrary,\r\n string memory _name,\r\n string memory _symbol\r\n ) LPTokenERC20(_name, _symbol) {\r\n require(_token != address(0x0), \"Mirrorgate: _token cannot be 0x0\");\r\n require(_router != address(0x0), \"Mirrorgate: _router cannot be 0x0\");\r\n poolId = _poolId;\r\n router = _router;\r\n token = _token;\r\n sharedDecimals = _sharedDecimals;\r\n decimals = uint8(_sharedDecimals);\r\n localDecimals = _localDecimals;\r\n convertRate = 10**(uint256(localDecimals).sub(sharedDecimals));\r\n totalWeight = 0;\r\n feeLibrary = _feeLibrary;\r\n\r\n //delta algo related\r\n batched = false;\r\n defaultSwapMode = true;\r\n defaultLPMode = true;\r\n }\r\n\r\n function getChainPathsLength() public view returns (uint256) {\r\n return chainPaths.length;\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // LOCAL CHAIN FUNCTIONS\r\n\r\n function mint(address _to, uint256 _amountLD) external nonReentrant onlyRouter returns (uint256) {\r\n return _mintLocal(_to, _amountLD, true, true);\r\n }\r\n\r\n // Local Remote\r\n // ------- ---------\r\n // swap -> swapRemote\r\n function swap(\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n address _from,\r\n uint256 _amountLD,\r\n uint256 _minAmountLD,\r\n bool newLiquidity\r\n ) external nonReentrant onlyRouter returns (SwapObj memory) {\r\n require(!stopSwap, \"Mirrorgate: swap func stopped\");\r\n ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);\r\n require(cp.ready == true, \"Mirrorgate: counter chainPath is not ready\");\r\n\r\n uint256 amountSD = amountLDtoSD(_amountLD);\r\n uint256 minAmountSD = amountLDtoSD(_minAmountLD);\r\n\r\n // request fee params from library\r\n SwapObj memory s = IMirrorgateFeeLibrary(feeLibrary).getFees(poolId, _dstPoolId, _dstChainId, _from, amountSD);\r\n\r\n // equilibrium fee and reward. note eqFee/eqReward are separated from swap liquidity\r\n eqFeePool = eqFeePool.sub(s.eqReward);\r\n // update the new amount the user gets minus the fees\r\n s.amount = amountSD.sub(s.eqFee).sub(s.protocolFee).sub(s.lpFee);\r\n // users will also get the eqReward\r\n require(s.amount.add(s.eqReward) >= minAmountSD, \"Mirrorgate: slippage too high\");\r\n\r\n // behaviours\r\n // - protocolFee: booked, stayed and withdrawn at remote.\r\n // - eqFee: booked, stayed and withdrawn at remote.\r\n // - lpFee: booked and stayed at remote, can be withdrawn anywhere\r\n\r\n s.lkbRemove = amountSD.sub(s.lpFee).add(s.eqReward);\r\n // check for transfer solvency.\r\n require(cp.balance >= s.lkbRemove, \"Mirrorgate: dst balance too low\");\r\n cp.balance = cp.balance.sub(s.lkbRemove);\r\n\r\n if (newLiquidity) {\r\n deltaCredit = deltaCredit.add(amountSD).add(s.eqReward);\r\n } else if (s.eqReward > 0) {\r\n deltaCredit = deltaCredit.add(s.eqReward);\r\n }\r\n\r\n // distribute credits on condition.\r\n if (!batched || deltaCredit >= totalLiquidity.mul(swapDeltaBP).div(BP_DENOMINATOR)) {\r\n _delta(defaultSwapMode);\r\n }\r\n\r\n emit Swap(_dstChainId, _dstPoolId, _from, s.amount, s.eqReward, s.eqFee, s.protocolFee, s.lpFee);\r\n return s;\r\n }\r\n\r\n // Local Remote\r\n // ------- ---------\r\n // sendCredits -> creditChainPath\r\n function sendCredits(uint16 _dstChainId, uint256 _dstPoolId) external nonReentrant onlyRouter returns (CreditObj memory c) {\r\n ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);\r\n require(cp.ready == true, \"Mirrorgate: counter chainPath is not ready\");\r\n cp.lkb = cp.lkb.add(cp.credits);\r\n c.idealBalance = totalLiquidity.mul(cp.weight).div(totalWeight);\r\n c.credits = cp.credits;\r\n cp.credits = 0;\r\n emit SendCredits(_dstChainId, _dstPoolId, c.credits, c.idealBalance);\r\n }\r\n\r\n // Local Remote\r\n // ------- ---------\r\n // redeemRemote -> swapRemote\r\n function redeemRemote(\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n address _from,\r\n uint256 _amountLP\r\n ) external nonReentrant onlyRouter {\r\n require(_from != address(0x0), \"Mirrorgate: _from cannot be 0x0\");\r\n uint256 amountSD = _burnLocal(_from, _amountLP);\r\n //run Delta\r\n if (!batched || deltaCredit > totalLiquidity.mul(lpDeltaBP).div(BP_DENOMINATOR)) {\r\n _delta(defaultLPMode);\r\n }\r\n uint256 amountLD = amountSDtoLD(amountSD);\r\n emit RedeemRemote(_dstChainId, _dstPoolId, _from, _amountLP, amountLD);\r\n }\r\n\r\n function instantRedeemLocal(\r\n address _from,\r\n uint256 _amountLP,\r\n address _to\r\n ) external nonReentrant onlyRouter returns (uint256 amountSD) {\r\n require(_from != address(0x0), \"Mirrorgate: _from cannot be 0x0\");\r\n uint256 _deltaCredit = deltaCredit; // sload optimization.\r\n uint256 _capAmountLP = _amountSDtoLP(_deltaCredit);\r\n\r\n if (_amountLP > _capAmountLP) _amountLP = _capAmountLP;\r\n\r\n amountSD = _burnLocal(_from, _amountLP);\r\n deltaCredit = _deltaCredit.sub(amountSD);\r\n uint256 amountLD = amountSDtoLD(amountSD);\r\n _safeTransfer(token, _to, amountLD);\r\n emit InstantRedeemLocal(_from, _amountLP, amountSD, _to);\r\n }\r\n\r\n // Local Remote\r\n // ------- ---------\r\n // redeemLocal -> redeemLocalCheckOnRemote\r\n // redeemLocalCallback <-\r\n function redeemLocal(\r\n address _from,\r\n uint256 _amountLP,\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n bytes calldata _to\r\n ) external nonReentrant onlyRouter returns (uint256 amountSD) {\r\n require(_from != address(0x0), \"Mirrorgate: _from cannot be 0x0\");\r\n\r\n // safeguard.\r\n require(chainPaths[chainPathIndexLookup[_dstChainId][_dstPoolId]].ready == true, \"Mirrorgate: counter chainPath is not ready\");\r\n amountSD = _burnLocal(_from, _amountLP);\r\n\r\n // run Delta\r\n if (!batched || deltaCredit > totalLiquidity.mul(lpDeltaBP).div(BP_DENOMINATOR)) {\r\n _delta(false);\r\n }\r\n emit RedeemLocal(_from, _amountLP, amountSD, _dstChainId, _dstPoolId, _to);\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // REMOTE CHAIN FUNCTIONS\r\n\r\n // Local Remote\r\n // ------- ---------\r\n // sendCredits -> creditChainPath\r\n function creditChainPath(\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n CreditObj memory _c\r\n ) external nonReentrant onlyRouter {\r\n ChainPath storage cp = chainPaths[chainPathIndexLookup[_dstChainId][_dstPoolId]];\r\n cp.balance = cp.balance.add(_c.credits);\r\n if (cp.idealBalance != _c.idealBalance) {\r\n cp.idealBalance = _c.idealBalance;\r\n }\r\n emit CreditChainPath(_dstChainId, _dstPoolId, _c.credits, _c.idealBalance);\r\n }\r\n\r\n // Local Remote\r\n // ------- ---------\r\n // swap -> swapRemote\r\n function swapRemote(\r\n uint16 _srcChainId,\r\n uint256 _srcPoolId,\r\n address _to,\r\n SwapObj memory _s\r\n ) external nonReentrant onlyRouter returns (uint256 amountLD) {\r\n // booking lpFee\r\n totalLiquidity = totalLiquidity.add(_s.lpFee);\r\n // booking eqFee\r\n eqFeePool = eqFeePool.add(_s.eqFee);\r\n // booking stargateFee\r\n protocolFeeBalance = protocolFeeBalance.add(_s.protocolFee);\r\n\r\n // update LKB\r\n uint256 chainPathIndex = chainPathIndexLookup[_srcChainId][_srcPoolId];\r\n chainPaths[chainPathIndex].lkb = chainPaths[chainPathIndex].lkb.sub(_s.lkbRemove);\r\n\r\n // user receives the amount + the srcReward\r\n amountLD = amountSDtoLD(_s.amount.add(_s.eqReward));\r\n _safeTransfer(token, _to, amountLD);\r\n emit SwapRemote(_to, _s.amount.add(_s.eqReward), _s.protocolFee, _s.eqFee);\r\n }\r\n\r\n // Local Remote\r\n // ------- ---------\r\n // redeemLocal -> redeemLocalCheckOnRemote\r\n // redeemLocalCallback <-\r\n function redeemLocalCallback(\r\n uint16 _srcChainId,\r\n uint256 _srcPoolId,\r\n address _to,\r\n uint256 _amountSD,\r\n uint256 _amountToMintSD\r\n ) external nonReentrant onlyRouter {\r\n if (_amountToMintSD > 0) {\r\n _mintLocal(_to, amountSDtoLD(_amountToMintSD), false, false);\r\n }\r\n\r\n ChainPath storage cp = getAndCheckCP(_srcChainId, _srcPoolId);\r\n cp.lkb = cp.lkb.sub(_amountSD);\r\n\r\n uint256 amountLD = amountSDtoLD(_amountSD);\r\n _safeTransfer(token, _to, amountLD);\r\n emit RedeemLocalCallback(_to, _amountSD, _amountToMintSD);\r\n }\r\n\r\n // Local Remote\r\n // ------- ---------\r\n // redeemLocal(amount) -> redeemLocalCheckOnRemote\r\n // redeemLocalCallback <-\r\n function redeemLocalCheckOnRemote(\r\n uint16 _srcChainId,\r\n uint256 _srcPoolId,\r\n uint256 _amountSD\r\n ) external nonReentrant onlyRouter returns (uint256 swapAmount, uint256 mintAmount) {\r\n ChainPath storage cp = getAndCheckCP(_srcChainId, _srcPoolId);\r\n if (_amountSD > cp.balance) {\r\n mintAmount = _amountSD - cp.balance;\r\n swapAmount = cp.balance;\r\n cp.balance = 0;\r\n } else {\r\n cp.balance = cp.balance.sub(_amountSD);\r\n swapAmount = _amountSD;\r\n mintAmount = 0;\r\n }\r\n emit WithdrawRemote(_srcChainId, _srcPoolId, swapAmount, mintAmount);\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // DAO Calls\r\n function createChainPath(\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n uint256 _weight\r\n ) external onlyRouter {\r\n for (uint256 i = 0; i < chainPaths.length; ++i) {\r\n ChainPath memory cp = chainPaths[i];\r\n bool exists = cp.dstChainId == _dstChainId && cp.dstPoolId == _dstPoolId;\r\n require(!exists, \"Mirrorgate: cant createChainPath of existing dstChainId and _dstPoolId\");\r\n }\r\n totalWeight = totalWeight.add(_weight);\r\n chainPathIndexLookup[_dstChainId][_dstPoolId] = chainPaths.length;\r\n chainPaths.push(ChainPath(false, _dstChainId, _dstPoolId, _weight, 0, 0, 0, 0));\r\n emit ChainPathUpdate(_dstChainId, _dstPoolId, _weight);\r\n }\r\n\r\n function setWeightForChainPath(\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n uint16 _weight\r\n ) external onlyRouter {\r\n ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);\r\n totalWeight = totalWeight.sub(cp.weight).add(_weight);\r\n cp.weight = _weight;\r\n emit ChainPathUpdate(_dstChainId, _dstPoolId, _weight);\r\n }\r\n\r\n function setFee(uint256 _mintFeeBP) external onlyRouter {\r\n require(_mintFeeBP <= BP_DENOMINATOR, \"Bridge: cum fees > 100%\");\r\n mintFeeBP = _mintFeeBP;\r\n emit FeesUpdated(mintFeeBP);\r\n }\r\n\r\n function setFeeLibrary(address _feeLibraryAddr) external onlyRouter {\r\n require(_feeLibraryAddr != address(0x0), \"Mirrorgate: fee library cant be 0x0\");\r\n feeLibrary = _feeLibraryAddr;\r\n emit FeeLibraryUpdated(_feeLibraryAddr);\r\n }\r\n\r\n function setSwapStop(bool _swapStop) external onlyRouter {\r\n stopSwap = _swapStop;\r\n emit StopSwapUpdated(_swapStop);\r\n }\r\n\r\n function setDeltaParam(\r\n bool _batched,\r\n uint256 _swapDeltaBP,\r\n uint256 _lpDeltaBP,\r\n bool _defaultSwapMode,\r\n bool _defaultLPMode\r\n ) external onlyRouter {\r\n require(_swapDeltaBP <= BP_DENOMINATOR && _lpDeltaBP <= BP_DENOMINATOR, \"Mirrorgate: wrong Delta param\");\r\n batched = _batched;\r\n swapDeltaBP = _swapDeltaBP;\r\n lpDeltaBP = _lpDeltaBP;\r\n defaultSwapMode = _defaultSwapMode;\r\n defaultLPMode = _defaultLPMode;\r\n emit DeltaParamUpdated(_batched, _swapDeltaBP, _lpDeltaBP, _defaultSwapMode, _defaultLPMode);\r\n }\r\n\r\n function callDelta(bool _fullMode) external onlyRouter {\r\n _delta(_fullMode);\r\n }\r\n\r\n function activateChainPath(uint16 _dstChainId, uint256 _dstPoolId) external onlyRouter {\r\n ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);\r\n require(cp.ready == false, \"Mirrorgate: chainPath is already active\");\r\n // this func will only be called once\r\n cp.ready = true;\r\n }\r\n\r\n function withdrawProtocolFeeBalance(address _to) external onlyRouter {\r\n if (protocolFeeBalance > 0) {\r\n uint256 amountOfLD = amountSDtoLD(protocolFeeBalance);\r\n protocolFeeBalance = 0;\r\n _safeTransfer(token, _to, amountOfLD);\r\n emit WithdrawProtocolFeeBalance(_to, amountOfLD);\r\n }\r\n }\r\n\r\n function withdrawMintFeeBalance(address _to) external onlyRouter {\r\n if (mintFeeBalance > 0) {\r\n uint256 amountOfLD = amountSDtoLD(mintFeeBalance);\r\n mintFeeBalance = 0;\r\n _safeTransfer(token, _to, amountOfLD);\r\n emit WithdrawMintFeeBalance(_to, amountOfLD);\r\n }\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // INTERNAL\r\n // Conversion Helpers\r\n //---------------------------------------------------------------------------\r\n function amountLPtoLD(uint256 _amountLP) external view returns (uint256) {\r\n return amountSDtoLD(_amountLPtoSD(_amountLP));\r\n }\r\n\r\n function _amountLPtoSD(uint256 _amountLP) internal view returns (uint256) {\r\n require(totalSupply > 0, \"Mirrorgate: cant convert LPtoSD when totalSupply == 0\");\r\n return _amountLP.mul(totalLiquidity).div(totalSupply);\r\n }\r\n\r\n function _amountSDtoLP(uint256 _amountSD) internal view returns (uint256) {\r\n require(totalLiquidity > 0, \"Mirrorgate: cant convert SDtoLP when totalLiq == 0\");\r\n return _amountSD.mul(totalSupply).div(totalLiquidity);\r\n }\r\n\r\n function amountSDtoLD(uint256 _amount) internal view returns (uint256) {\r\n return _amount.mul(convertRate);\r\n }\r\n\r\n function amountLDtoSD(uint256 _amount) internal view returns (uint256) {\r\n return _amount.div(convertRate);\r\n }\r\n\r\n function getAndCheckCP(uint16 _dstChainId, uint256 _dstPoolId) internal view returns (ChainPath storage) {\r\n require(chainPaths.length > 0, \"Mirrorgate: no chainpaths exist\");\r\n ChainPath storage cp = chainPaths[chainPathIndexLookup[_dstChainId][_dstPoolId]];\r\n require(cp.dstChainId == _dstChainId && cp.dstPoolId == _dstPoolId, \"Mirrorgate: local chainPath does not exist\");\r\n return cp;\r\n }\r\n\r\n function getChainPath(uint16 _dstChainId, uint256 _dstPoolId) external view returns (ChainPath memory) {\r\n ChainPath memory cp = chainPaths[chainPathIndexLookup[_dstChainId][_dstPoolId]];\r\n require(cp.dstChainId == _dstChainId && cp.dstPoolId == _dstPoolId, \"Mirrorgate: local chainPath does not exist\");\r\n return cp;\r\n }\r\n\r\n function _burnLocal(address _from, uint256 _amountLP) internal returns (uint256) {\r\n require(totalSupply > 0, \"Mirrorgate: cant burn when totalSupply == 0\");\r\n uint256 amountOfLPTokens = balanceOf[_from];\r\n require(amountOfLPTokens >= _amountLP, \"Mirrorgate: not enough LP tokens to burn\");\r\n\r\n uint256 amountSD = _amountLP.mul(totalLiquidity).div(totalSupply);\r\n //subtract totalLiquidity accordingly\r\n totalLiquidity = totalLiquidity.sub(amountSD);\r\n\r\n _burn(_from, _amountLP);\r\n emit Burn(_from, _amountLP, amountSD);\r\n return amountSD;\r\n }\r\n\r\n function _delta(bool fullMode) internal {\r\n if (deltaCredit > 0 && totalWeight > 0) {\r\n uint256 cpLength = chainPaths.length;\r\n uint256[] memory deficit = new uint256[](cpLength);\r\n uint256 totalDeficit = 0;\r\n\r\n // algorithm steps 6-9: calculate the total and the amounts required to get to balance state\r\n for (uint256 i = 0; i < cpLength; ++i) {\r\n ChainPath storage cp = chainPaths[i];\r\n // (liquidity * (weight/totalWeight)) - (lkb+credits)\r\n uint256 balLiq = totalLiquidity.mul(cp.weight).div(totalWeight);\r\n uint256 currLiq = cp.lkb.add(cp.credits);\r\n if (balLiq > currLiq) {\r\n // save gas since we know balLiq > currLiq and we know deficit[i] > 0\r\n deficit[i] = balLiq - currLiq;\r\n totalDeficit = totalDeficit.add(deficit[i]);\r\n }\r\n }\r\n\r\n // indicates how much delta credit is distributed\r\n uint256 spent;\r\n\r\n // handle credits with 2 tranches. the [ < totalDeficit] [excessCredit]\r\n // run full Delta, allocate all credits\r\n if (totalDeficit == 0) {\r\n // only fullMode delta will allocate excess credits\r\n if (fullMode && deltaCredit > 0) {\r\n // credit ChainPath by weights\r\n for (uint256 i = 0; i < cpLength; ++i) {\r\n ChainPath storage cp = chainPaths[i];\r\n // credits = credits + toBalanceChange + remaining allocation based on weight\r\n uint256 amtToCredit = deltaCredit.mul(cp.weight).div(totalWeight);\r\n spent = spent.add(amtToCredit);\r\n cp.credits = cp.credits.add(amtToCredit);\r\n }\r\n } // else do nth\r\n } else if (totalDeficit <= deltaCredit) {\r\n if (fullMode) {\r\n // algorithm step 13: calculate amount to disperse to bring to balance state or as close as possible\r\n uint256 excessCredit = deltaCredit - totalDeficit;\r\n // algorithm steps 14-16: calculate credits\r\n for (uint256 i = 0; i < cpLength; ++i) {\r\n if (deficit[i] > 0) {\r\n ChainPath storage cp = chainPaths[i];\r\n // credits = credits + deficit + remaining allocation based on weight\r\n uint256 amtToCredit = deficit[i].add(excessCredit.mul(cp.weight).div(totalWeight));\r\n spent = spent.add(amtToCredit);\r\n cp.credits = cp.credits.add(amtToCredit);\r\n }\r\n }\r\n } else {\r\n // totalDeficit <= deltaCredit but not running fullMode\r\n // credit chainPaths as is if any deficit, not using all deltaCredit\r\n for (uint256 i = 0; i < cpLength; ++i) {\r\n if (deficit[i] > 0) {\r\n ChainPath storage cp = chainPaths[i];\r\n uint256 amtToCredit = deficit[i];\r\n spent = spent.add(amtToCredit);\r\n cp.credits = cp.credits.add(amtToCredit);\r\n }\r\n }\r\n }\r\n } else {\r\n // totalDeficit > deltaCredit, fullMode or not, normalize the deficit by deltaCredit\r\n for (uint256 i = 0; i < cpLength; ++i) {\r\n if (deficit[i] > 0) {\r\n ChainPath storage cp = chainPaths[i];\r\n uint256 proportionalDeficit = deficit[i].mul(deltaCredit).div(totalDeficit);\r\n spent = spent.add(proportionalDeficit);\r\n cp.credits = cp.credits.add(proportionalDeficit);\r\n }\r\n }\r\n }\r\n\r\n // deduct the amount of credit sent\r\n deltaCredit = deltaCredit.sub(spent);\r\n }\r\n }\r\n\r\n function _mintLocal(\r\n address _to,\r\n uint256 _amountLD,\r\n bool _feesEnabled,\r\n bool _creditDelta\r\n ) internal returns (uint256 amountSD) {\r\n require(totalWeight > 0, \"Mirrorgate: No ChainPaths exist\");\r\n amountSD = amountLDtoSD(_amountLD);\r\n\r\n uint256 mintFeeSD = 0;\r\n if (_feesEnabled) {\r\n mintFeeSD = amountSD.mul(mintFeeBP).div(BP_DENOMINATOR);\r\n amountSD = amountSD.sub(mintFeeSD);\r\n mintFeeBalance = mintFeeBalance.add(mintFeeSD);\r\n }\r\n\r\n if (_creditDelta) {\r\n deltaCredit = deltaCredit.add(amountSD);\r\n }\r\n\r\n uint256 amountLPTokens = amountSD;\r\n if (totalSupply != 0) {\r\n amountLPTokens = amountSD.mul(totalSupply).div(totalLiquidity);\r\n }\r\n totalLiquidity = totalLiquidity.add(amountSD);\r\n\r\n _mint(_to, amountLPTokens);\r\n emit Mint(_to, amountLPTokens, amountSD, mintFeeSD);\r\n\r\n // add to credits and call delta. short circuit to save gas\r\n if (!batched || deltaCredit > totalLiquidity.mul(lpDeltaBP).div(BP_DENOMINATOR)) {\r\n _delta(defaultLPMode);\r\n }\r\n }\r\n\r\n function _safeTransfer(\r\n address _token,\r\n address _to,\r\n uint256 _value\r\n ) private {\r\n (bool success, bytes memory data) = _token.call(abi.encodeWithSelector(SELECTOR, _to, _value));\r\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"Mirrorgate: TRANSFER_FAILED\");\r\n }\r\n}\r\n"
  12. },
  13. "contracts/Router.sol": {
  14. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\n// imports\r\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\r\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\r\nimport \"./Factory.sol\";\r\nimport \"./Pool.sol\";\r\nimport \"./Bridge.sol\";\r\n\r\n// interfaces\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport \"./interfaces/IMirrorgateRouter.sol\";\r\nimport \"./interfaces/IMirrorgateReceiver.sol\";\r\n\r\n// libraries\r\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\r\n\r\ncontract Router is IMirrorgateRouter, Ownable, ReentrancyGuard {\r\n using SafeMath for uint256;\r\n\r\n //---------------------------------------------------------------------------\r\n // CONSTANTS\r\n uint8 internal constant TYPE_REDEEM_LOCAL_RESPONSE = 1;\r\n uint8 internal constant TYPE_REDEEM_LOCAL_CALLBACK_RETRY = 2;\r\n uint8 internal constant TYPE_SWAP_REMOTE_RETRY = 3;\r\n\r\n //---------------------------------------------------------------------------\r\n // STRUCTS\r\n struct CachedSwap {\r\n address token;\r\n uint256 amountLD;\r\n address to;\r\n bytes payload;\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // VARIABLES\r\n Factory public factory; // used for creating pools\r\n address public protocolFeeOwner; // can call methods to pull Stargate fees collected in pools\r\n address public mintFeeOwner; // can call methods to pull mint fees collected in pools\r\n Bridge public bridge;\r\n mapping(uint16 => mapping(bytes => mapping(uint256 => bytes))) public revertLookup; //[chainId][srcAddress][nonce]\r\n mapping(uint16 => mapping(bytes => mapping(uint256 => CachedSwap))) public cachedSwapLookup; //[chainId][srcAddress][nonce]\r\n\r\n //---------------------------------------------------------------------------\r\n // EVENTS\r\n event Revert(uint8 bridgeFunctionType, uint16 chainId, bytes srcAddress, uint256 nonce);\r\n event CachedSwapSaved(uint16 chainId, bytes srcAddress, uint256 nonce, address token, uint256 amountLD, address to, bytes payload, bytes reason);\r\n event RevertRedeemLocal(uint16 srcChainId, uint256 _srcPoolId, uint256 _dstPoolId, bytes to, uint256 redeemAmountSD, uint256 mintAmountSD, uint256 indexed nonce, bytes indexed srcAddress);\r\n event RedeemLocalCallback(uint16 srcChainId, bytes indexed srcAddress, uint256 indexed nonce, uint256 srcPoolId, uint256 dstPoolId, address to, uint256 amountSD, uint256 mintAmountSD);\r\n\r\n //---------------------------------------------------------------------------\r\n // MODIFIERS\r\n modifier onlyBridge() {\r\n require(msg.sender == address(bridge), \"Bridge: caller must be Bridge.\");\r\n _;\r\n }\r\n\r\n constructor() {}\r\n\r\n function setBridgeAndFactory(Bridge _bridge, Factory _factory) external onlyOwner {\r\n require(address(bridge) == address(0x0) && address(factory) == address(0x0), \"Mirrorgate: bridge and factory already initialized\"); // 1 time only\r\n require(address(_bridge) != address(0x0), \"Mirrorgate: bridge cant be 0x0\");\r\n require(address(_factory) != address(0x0), \"Mirrorgate: factory cant be 0x0\");\r\n\r\n bridge = _bridge;\r\n factory = _factory;\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // VIEWS\r\n function _getPool(uint256 _poolId) internal view returns (Pool pool) {\r\n pool = factory.getPool(_poolId);\r\n require(address(pool) != address(0x0), \"Mirrorgate: Pool does not exist\");\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // INTERNAL\r\n function _safeTransferFrom(\r\n address token,\r\n address from,\r\n address to,\r\n uint256 value\r\n ) private {\r\n // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));\r\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));\r\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"Mirrorgate: TRANSFER_FROM_FAILED\");\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // LOCAL CHAIN FUNCTIONS\r\n function addLiquidity(\r\n uint256 _poolId,\r\n uint256 _amountLD,\r\n address _to\r\n ) external override nonReentrant {\r\n Pool pool = _getPool(_poolId);\r\n uint256 convertRate = pool.convertRate();\r\n _amountLD = _amountLD.div(convertRate).mul(convertRate);\r\n _safeTransferFrom(pool.token(), msg.sender, address(pool), _amountLD);\r\n pool.mint(_to, _amountLD);\r\n }\r\n\r\n function swap(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLD,\r\n uint256 _minAmountLD,\r\n lzTxObj memory _lzTxParams,\r\n bytes calldata _to,\r\n bytes calldata _payload\r\n ) external payable override nonReentrant {\r\n require(_amountLD > 0, \"Mirrorgate: cannot swap 0\");\r\n require(_refundAddress != address(0x0), \"Mirrorgate: _refundAddress cannot be 0x0\");\r\n Pool.SwapObj memory s;\r\n Pool.CreditObj memory c;\r\n {\r\n Pool pool = _getPool(_srcPoolId);\r\n {\r\n uint256 convertRate = pool.convertRate();\r\n _amountLD = _amountLD.div(convertRate).mul(convertRate);\r\n }\r\n\r\n s = pool.swap(_dstChainId, _dstPoolId, msg.sender, _amountLD, _minAmountLD, true);\r\n _safeTransferFrom(pool.token(), msg.sender, address(pool), _amountLD);\r\n c = pool.sendCredits(_dstChainId, _dstPoolId);\r\n }\r\n bridge.swap{value: msg.value}(_dstChainId, _srcPoolId, _dstPoolId, _refundAddress, c, s, _lzTxParams, _to, _payload);\r\n }\r\n\r\n function redeemRemote(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLP,\r\n uint256 _minAmountLD,\r\n bytes calldata _to,\r\n lzTxObj memory _lzTxParams\r\n ) external payable override nonReentrant {\r\n require(_refundAddress != address(0x0), \"Mirrorgate: _refundAddress cannot be 0x0\");\r\n require(_amountLP > 0, \"Mirrorgate: not enough lp to redeemRemote\");\r\n Pool.SwapObj memory s;\r\n Pool.CreditObj memory c;\r\n {\r\n Pool pool = _getPool(_srcPoolId);\r\n uint256 amountLD = pool.amountLPtoLD(_amountLP);\r\n // perform a swap with no liquidity\r\n s = pool.swap(_dstChainId, _dstPoolId, msg.sender, amountLD, _minAmountLD, false);\r\n pool.redeemRemote(_dstChainId, _dstPoolId, msg.sender, _amountLP);\r\n c = pool.sendCredits(_dstChainId, _dstPoolId);\r\n }\r\n // equal to a swap, with no payload (\"0x\") no dstGasForCall 0\r\n bridge.swap{value: msg.value}(_dstChainId, _srcPoolId, _dstPoolId, _refundAddress, c, s, _lzTxParams, _to, \"\");\r\n }\r\n\r\n function instantRedeemLocal(\r\n uint16 _srcPoolId,\r\n uint256 _amountLP,\r\n address _to\r\n ) external override nonReentrant returns (uint256 amountSD) {\r\n require(_amountLP > 0, \"Mirrorgate: not enough lp to redeem\");\r\n Pool pool = _getPool(_srcPoolId);\r\n amountSD = pool.instantRedeemLocal(msg.sender, _amountLP, _to);\r\n }\r\n\r\n function redeemLocal(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLP,\r\n bytes calldata _to,\r\n lzTxObj memory _lzTxParams\r\n ) external payable override nonReentrant {\r\n require(_refundAddress != address(0x0), \"Mirrorgate: _refundAddress cannot be 0x0\");\r\n Pool pool = _getPool(_srcPoolId);\r\n require(_amountLP > 0, \"Mirrorgate: not enough lp to redeem\");\r\n uint256 amountSD = pool.redeemLocal(msg.sender, _amountLP, _dstChainId, _dstPoolId, _to);\r\n require(amountSD > 0, \"Mirrorgate: not enough lp to redeem with amountSD\");\r\n\r\n Pool.CreditObj memory c = pool.sendCredits(_dstChainId, _dstPoolId);\r\n bridge.redeemLocal{value: msg.value}(_dstChainId, _srcPoolId, _dstPoolId, _refundAddress, c, amountSD, _to, _lzTxParams);\r\n }\r\n\r\n function sendCredits(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress\r\n ) external payable override nonReentrant {\r\n require(_refundAddress != address(0x0), \"Mirrorgate: _refundAddress cannot be 0x0\");\r\n Pool pool = _getPool(_srcPoolId);\r\n Pool.CreditObj memory c = pool.sendCredits(_dstChainId, _dstPoolId);\r\n bridge.sendCredits{value: msg.value}(_dstChainId, _srcPoolId, _dstPoolId, _refundAddress, c);\r\n }\r\n\r\n function quoteLayerZeroFee(\r\n uint16 _dstChainId,\r\n uint8 _functionType,\r\n bytes calldata _toAddress,\r\n bytes calldata _transferAndCallPayload,\r\n Router.lzTxObj memory _lzTxParams\r\n ) external view override returns (uint256, uint256) {\r\n return bridge.quoteLayerZeroFee(_dstChainId, _functionType, _toAddress, _transferAndCallPayload, _lzTxParams);\r\n }\r\n\r\n function revertRedeemLocal(\r\n uint16 _dstChainId,\r\n bytes calldata _srcAddress,\r\n uint256 _nonce,\r\n address payable _refundAddress,\r\n lzTxObj memory _lzTxParams\r\n ) external payable {\r\n require(_refundAddress != address(0x0), \"Mirrorgate: _refundAddress cannot be 0x0\");\r\n bytes memory payload = revertLookup[_dstChainId][_srcAddress][_nonce];\r\n require(payload.length > 0, \"Mirrorgate: no retry revert\");\r\n {\r\n uint8 functionType;\r\n assembly {\r\n functionType := mload(add(payload, 32))\r\n }\r\n require(functionType == TYPE_REDEEM_LOCAL_RESPONSE, \"Mirrorgate: invalid function type\");\r\n }\r\n\r\n // empty it\r\n revertLookup[_dstChainId][_srcAddress][_nonce] = \"\";\r\n\r\n uint256 srcPoolId;\r\n uint256 dstPoolId;\r\n assembly {\r\n srcPoolId := mload(add(payload, 64))\r\n dstPoolId := mload(add(payload, 96))\r\n }\r\n\r\n Pool.CreditObj memory c;\r\n {\r\n Pool pool = _getPool(dstPoolId);\r\n c = pool.sendCredits(_dstChainId, srcPoolId);\r\n }\r\n\r\n bridge.redeemLocalCallback{value: msg.value}(_dstChainId, _refundAddress, c, _lzTxParams, payload);\r\n }\r\n\r\n function retryRevert(\r\n uint16 _srcChainId,\r\n bytes calldata _srcAddress,\r\n uint256 _nonce\r\n ) external payable {\r\n bytes memory payload = revertLookup[_srcChainId][_srcAddress][_nonce];\r\n require(payload.length > 0, \"Mirrorgate: no retry revert\");\r\n\r\n // empty it\r\n revertLookup[_srcChainId][_srcAddress][_nonce] = \"\";\r\n\r\n uint8 functionType;\r\n assembly {\r\n functionType := mload(add(payload, 32))\r\n }\r\n\r\n if (functionType == TYPE_REDEEM_LOCAL_CALLBACK_RETRY) {\r\n (, uint256 srcPoolId, uint256 dstPoolId, address to, uint256 amountSD, uint256 mintAmountSD) = abi.decode(\r\n payload,\r\n (uint8, uint256, uint256, address, uint256, uint256)\r\n );\r\n _redeemLocalCallback(_srcChainId, _srcAddress, _nonce, srcPoolId, dstPoolId, to, amountSD, mintAmountSD);\r\n }\r\n // for retrying the swapRemote. if it fails again, retry\r\n else if (functionType == TYPE_SWAP_REMOTE_RETRY) {\r\n (, uint256 srcPoolId, uint256 dstPoolId, uint256 dstGasForCall, address to, Pool.SwapObj memory s, bytes memory p) = abi.decode(\r\n payload,\r\n (uint8, uint256, uint256, uint256, address, Pool.SwapObj, bytes)\r\n );\r\n _swapRemote(_srcChainId, _srcAddress, _nonce, srcPoolId, dstPoolId, dstGasForCall, to, s, p);\r\n } else {\r\n revert(\"Mirrorgate: invalid function type\");\r\n }\r\n }\r\n\r\n function clearCachedSwap(\r\n uint16 _srcChainId,\r\n bytes calldata _srcAddress,\r\n uint256 _nonce\r\n ) external {\r\n CachedSwap memory cs = cachedSwapLookup[_srcChainId][_srcAddress][_nonce];\r\n require(cs.to != address(0x0), \"Mirrorgate: cache already cleared\");\r\n // clear the data\r\n cachedSwapLookup[_srcChainId][_srcAddress][_nonce] = CachedSwap(address(0x0), 0, address(0x0), \"\");\r\n IMirrorgateReceiver(cs.to).mgReceive(_srcChainId, _srcAddress, _nonce, cs.token, cs.amountLD, cs.payload);\r\n }\r\n\r\n function creditChainPath(\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n uint256 _srcPoolId,\r\n Pool.CreditObj memory _c\r\n ) external onlyBridge {\r\n Pool pool = _getPool(_srcPoolId);\r\n pool.creditChainPath(_dstChainId, _dstPoolId, _c);\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // REMOTE CHAIN FUNCTIONS\r\n function redeemLocalCheckOnRemote(\r\n uint16 _srcChainId,\r\n bytes memory _srcAddress,\r\n uint256 _nonce,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n uint256 _amountSD,\r\n bytes calldata _to\r\n ) external onlyBridge {\r\n Pool pool = _getPool(_dstPoolId);\r\n try pool.redeemLocalCheckOnRemote(_srcChainId, _srcPoolId, _amountSD) returns (uint256 redeemAmountSD, uint256 mintAmountSD) {\r\n revertLookup[_srcChainId][_srcAddress][_nonce] = abi.encode(\r\n TYPE_REDEEM_LOCAL_RESPONSE,\r\n _srcPoolId,\r\n _dstPoolId,\r\n redeemAmountSD,\r\n mintAmountSD,\r\n _to\r\n );\r\n emit RevertRedeemLocal(_srcChainId, _srcPoolId, _dstPoolId, _to, redeemAmountSD, mintAmountSD, _nonce, _srcAddress);\r\n } catch {\r\n // if the func fail, return [swapAmount: 0, mintAMount: _amountSD]\r\n // swapAmount represents the amount of chainPath balance deducted on the remote side, which because the above tx failed, should be 0\r\n // mintAmount is the full amount of tokens the user attempted to redeem on the src side, which gets converted back into the lp amount\r\n revertLookup[_srcChainId][_srcAddress][_nonce] = abi.encode(TYPE_REDEEM_LOCAL_RESPONSE, _srcPoolId, _dstPoolId, 0, _amountSD, _to);\r\n emit Revert(TYPE_REDEEM_LOCAL_RESPONSE, _srcChainId, _srcAddress, _nonce);\r\n }\r\n }\r\n\r\n function redeemLocalCallback(\r\n uint16 _srcChainId,\r\n bytes memory _srcAddress,\r\n uint256 _nonce,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address _to,\r\n uint256 _amountSD,\r\n uint256 _mintAmountSD\r\n ) external onlyBridge {\r\n _redeemLocalCallback(_srcChainId, _srcAddress, _nonce, _srcPoolId, _dstPoolId, _to, _amountSD, _mintAmountSD);\r\n }\r\n\r\n function _redeemLocalCallback(\r\n uint16 _srcChainId,\r\n bytes memory _srcAddress,\r\n uint256 _nonce,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address _to,\r\n uint256 _amountSD,\r\n uint256 _mintAmountSD\r\n ) internal {\r\n Pool pool = _getPool(_dstPoolId);\r\n try pool.redeemLocalCallback(_srcChainId, _srcPoolId, _to, _amountSD, _mintAmountSD) {} catch {\r\n revertLookup[_srcChainId][_srcAddress][_nonce] = abi.encode(\r\n TYPE_REDEEM_LOCAL_CALLBACK_RETRY,\r\n _srcPoolId,\r\n _dstPoolId,\r\n _to,\r\n _amountSD,\r\n _mintAmountSD\r\n );\r\n emit Revert(TYPE_REDEEM_LOCAL_CALLBACK_RETRY, _srcChainId, _srcAddress, _nonce);\r\n }\r\n emit RedeemLocalCallback(_srcChainId, _srcAddress, _nonce, _srcPoolId, _dstPoolId, _to, _amountSD, _mintAmountSD);\r\n }\r\n\r\n function swapRemote(\r\n uint16 _srcChainId,\r\n bytes memory _srcAddress,\r\n uint256 _nonce,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n uint256 _dstGasForCall,\r\n address _to,\r\n Pool.SwapObj memory _s,\r\n bytes memory _payload\r\n ) external onlyBridge {\r\n _swapRemote(_srcChainId, _srcAddress, _nonce, _srcPoolId, _dstPoolId, _dstGasForCall, _to, _s, _payload);\r\n }\r\n\r\n function _swapRemote(\r\n uint16 _srcChainId,\r\n bytes memory _srcAddress,\r\n uint256 _nonce,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n uint256 _dstGasForCall,\r\n address _to,\r\n Pool.SwapObj memory _s,\r\n bytes memory _payload\r\n ) internal {\r\n Pool pool = _getPool(_dstPoolId);\r\n // first try catch the swap remote\r\n try pool.swapRemote(_srcChainId, _srcPoolId, _to, _s) returns (uint256 amountLD) {\r\n if (_payload.length > 0) {\r\n // then try catch the external contract call\r\n try IMirrorgateReceiver(_to).mgReceive{gas: _dstGasForCall}(_srcChainId, _srcAddress, _nonce, pool.token(), amountLD, _payload) {\r\n // do nothing\r\n } catch (bytes memory reason) {\r\n cachedSwapLookup[_srcChainId][_srcAddress][_nonce] = CachedSwap(pool.token(), amountLD, _to, _payload);\r\n emit CachedSwapSaved(_srcChainId, _srcAddress, _nonce, pool.token(), amountLD, _to, _payload, reason);\r\n }\r\n }\r\n } catch {\r\n revertLookup[_srcChainId][_srcAddress][_nonce] = abi.encode(\r\n TYPE_SWAP_REMOTE_RETRY,\r\n _srcPoolId,\r\n _dstPoolId,\r\n _dstGasForCall,\r\n _to,\r\n _s,\r\n _payload\r\n );\r\n emit Revert(TYPE_SWAP_REMOTE_RETRY, _srcChainId, _srcAddress, _nonce);\r\n }\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // DAO Calls\r\n function createPool(\r\n uint256 _poolId,\r\n address _token,\r\n uint8 _sharedDecimals,\r\n uint8 _localDecimals,\r\n string memory _name,\r\n string memory _symbol\r\n ) external onlyOwner returns (address) {\r\n require(_token != address(0x0), \"Mirrorgate: _token cannot be 0x0\");\r\n return factory.createPool(_poolId, _token, _sharedDecimals, _localDecimals, _name, _symbol);\r\n }\r\n\r\n function createChainPath(\r\n uint256 _poolId,\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n uint256 _weight\r\n ) external onlyOwner {\r\n Pool pool = _getPool(_poolId);\r\n pool.createChainPath(_dstChainId, _dstPoolId, _weight);\r\n }\r\n\r\n function activateChainPath(\r\n uint256 _poolId,\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId\r\n ) external onlyOwner {\r\n Pool pool = _getPool(_poolId);\r\n pool.activateChainPath(_dstChainId, _dstPoolId);\r\n }\r\n\r\n function setWeightForChainPath(\r\n uint256 _poolId,\r\n uint16 _dstChainId,\r\n uint256 _dstPoolId,\r\n uint16 _weight\r\n ) external onlyOwner {\r\n Pool pool = _getPool(_poolId);\r\n pool.setWeightForChainPath(_dstChainId, _dstPoolId, _weight);\r\n }\r\n\r\n function setProtocolFeeOwner(address _owner) external onlyOwner {\r\n require(_owner != address(0x0), \"Mirrorgate: _owner cannot be 0x0\");\r\n protocolFeeOwner = _owner;\r\n }\r\n\r\n function setMintFeeOwner(address _owner) external onlyOwner {\r\n require(_owner != address(0x0), \"Mirrorgate: _owner cannot be 0x0\");\r\n mintFeeOwner = _owner;\r\n }\r\n\r\n function setFees(uint256 _poolId, uint256 _mintFeeBP) external onlyOwner {\r\n Pool pool = _getPool(_poolId);\r\n pool.setFee(_mintFeeBP);\r\n }\r\n\r\n function setFeeLibrary(uint256 _poolId, address _feeLibraryAddr) external onlyOwner {\r\n Pool pool = _getPool(_poolId);\r\n pool.setFeeLibrary(_feeLibraryAddr);\r\n }\r\n\r\n function setSwapStop(uint256 _poolId, bool _swapStop) external onlyOwner {\r\n Pool pool = _getPool(_poolId);\r\n pool.setSwapStop(_swapStop);\r\n }\r\n\r\n function setDeltaParam(\r\n uint256 _poolId,\r\n bool _batched,\r\n uint256 _swapDeltaBP,\r\n uint256 _lpDeltaBP,\r\n bool _defaultSwapMode,\r\n bool _defaultLPMode\r\n ) external onlyOwner {\r\n Pool pool = _getPool(_poolId);\r\n pool.setDeltaParam(_batched, _swapDeltaBP, _lpDeltaBP, _defaultSwapMode, _defaultLPMode);\r\n }\r\n\r\n function callDelta(uint256 _poolId, bool _fullMode) external {\r\n Pool pool = _getPool(_poolId);\r\n pool.callDelta(_fullMode);\r\n }\r\n\r\n function withdrawMintFee(uint256 _poolId, address _to) external {\r\n require(mintFeeOwner == msg.sender, \"Mirrorgate: only mintFeeOwner\");\r\n Pool pool = _getPool(_poolId);\r\n pool.withdrawMintFeeBalance(_to);\r\n }\r\n\r\n function withdrawProtocolFee(uint256 _poolId, address _to) external {\r\n require(protocolFeeOwner == msg.sender, \"Mirrorgate: only protocolFeeOwner\");\r\n Pool pool = _getPool(_poolId);\r\n pool.withdrawProtocolFeeBalance(_to);\r\n }\r\n}\r\n"
  15. },
  16. "@openzeppelin/contracts/math/SafeMath.sol": {
  17. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n"
  18. },
  19. "contracts/interfaces/ILayerZeroReceiver.sol": {
  20. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity >=0.5.0;\r\n\r\ninterface ILayerZeroReceiver {\r\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\r\n // @param _srcChainId - the source endpoint identifier\r\n // @param _srcAddress - the source sending contract address from the source chain\r\n // @param _nonce - the ordered message nonce\r\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\r\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\r\n}\r\n"
  21. },
  22. "contracts/interfaces/ILayerZeroEndpoint.sol": {
  23. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity >=0.5.0;\r\n\r\nimport \"./ILayerZeroUserApplicationConfig.sol\";\r\n\r\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\r\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\r\n // @param _dstChainId - the destination chain identifier\r\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\r\n // @param _payload - a custom bytes payload to send to the destination contract\r\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\r\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\r\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\r\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\r\n\r\n // @notice used by the messaging library to publish verified payload\r\n // @param _srcChainId - the source chain identifier\r\n // @param _srcAddress - the source contract (as bytes) at the source chain\r\n // @param _dstAddress - the address on destination chain\r\n // @param _nonce - the unbound message ordering nonce\r\n // @param _gasLimit - the gas limit for external contract execution\r\n // @param _payload - verified payload to send to the destination contract\r\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\r\n\r\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\r\n // @param _srcChainId - the source chain identifier\r\n // @param _srcAddress - the source chain contract address\r\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\r\n\r\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\r\n // @param _srcAddress - the source chain contract address\r\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\r\n\r\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\r\n // @param _dstChainId - the destination chain identifier\r\n // @param _userApplication - the user app address on this EVM chain\r\n // @param _payload - the custom message to send over LayerZero\r\n // @param _payInZRO - if false, user app pays the protocol fee in native token\r\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\r\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\r\n\r\n // @notice get this Endpoint's immutable source identifier\r\n function getChainId() external view returns (uint16);\r\n\r\n // @notice the interface to retry failed message on this Endpoint destination\r\n // @param _srcChainId - the source chain identifier\r\n // @param _srcAddress - the source chain contract address\r\n // @param _payload - the payload to be retried\r\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\r\n\r\n // @notice query if any STORED payload (message blocking) at the endpoint.\r\n // @param _srcChainId - the source chain identifier\r\n // @param _srcAddress - the source chain contract address\r\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\r\n\r\n // @notice query if the _libraryAddress is valid for sending msgs.\r\n // @param _userApplication - the user app address on this EVM chain\r\n function getSendLibraryAddress(address _userApplication) external view returns (address);\r\n\r\n // @notice query if the _libraryAddress is valid for receiving msgs.\r\n // @param _userApplication - the user app address on this EVM chain\r\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\r\n\r\n // @notice query if the non-reentrancy guard for send() is on\r\n // @return true if the guard is on. false otherwise\r\n function isSendingPayload() external view returns (bool);\r\n\r\n // @notice query if the non-reentrancy guard for receive() is on\r\n // @return true if the guard is on. false otherwise\r\n function isReceivingPayload() external view returns (bool);\r\n\r\n // @notice get the configuration of the LayerZero messaging library of the specified version\r\n // @param _version - messaging library version\r\n // @param _chainId - the chainId for the pending config change\r\n // @param _userApplication - the contract address of the user application\r\n // @param _configType - type of configuration. every messaging library has its own convention.\r\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\r\n\r\n // @notice get the send() LayerZero messaging library version\r\n // @param _userApplication - the contract address of the user application\r\n function getSendVersion(address _userApplication) external view returns (uint16);\r\n\r\n // @notice get the lzReceive() LayerZero messaging library version\r\n // @param _userApplication - the contract address of the user application\r\n function getReceiveVersion(address _userApplication) external view returns (uint16);\r\n}\r\n"
  24. },
  25. "contracts/interfaces/ILayerZeroUserApplicationConfig.sol": {
  26. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity >=0.5.0;\r\n\r\ninterface ILayerZeroUserApplicationConfig {\r\n // @notice set the configuration of the LayerZero messaging library of the specified version\r\n // @param _version - messaging library version\r\n // @param _chainId - the chainId for the pending config change\r\n // @param _configType - type of configuration. every messaging library has its own convention.\r\n // @param _config - configuration in the bytes. can encode arbitrary content.\r\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\r\n\r\n // @notice set the send() LayerZero messaging library version to _version\r\n // @param _version - new messaging library version\r\n function setSendVersion(uint16 _version) external;\r\n\r\n // @notice set the lzReceive() LayerZero messaging library version to _version\r\n // @param _version - new messaging library version\r\n function setReceiveVersion(uint16 _version) external;\r\n\r\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\r\n // @param _srcChainId - the chainId of the source chain\r\n // @param _srcAddress - the contract address of the source contract at the source chain\r\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\r\n}\r\n"
  27. },
  28. "@openzeppelin/contracts/utils/Context.sol": {
  29. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n"
  30. },
  31. "@openzeppelin/contracts/utils/ReentrancyGuard.sol": {
  32. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor () {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
  33. },
  34. "contracts/LPTokenERC20.sol": {
  35. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\n\r\n// libraries\r\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\r\n\r\ncontract LPTokenERC20 {\r\n using SafeMath for uint256;\r\n\r\n //---------------------------------------------------------------------------\r\n // CONSTANTS\r\n string public name;\r\n string public symbol;\r\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\r\n // set in constructor\r\n bytes32 public DOMAIN_SEPARATOR;\r\n\r\n //---------------------------------------------------------------------------\r\n // VARIABLES\r\n uint256 public decimals;\r\n uint256 public totalSupply;\r\n mapping(address => uint256) public balanceOf;\r\n mapping(address => mapping(address => uint256)) public allowance;\r\n mapping(address => uint256) public nonces;\r\n\r\n //---------------------------------------------------------------------------\r\n // EVENTS\r\n event Approval(address indexed owner, address indexed spender, uint256 value);\r\n event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n constructor(string memory _name, string memory _symbol) {\r\n name = _name;\r\n symbol = _symbol;\r\n uint256 chainId;\r\n assembly {\r\n chainId := chainid()\r\n }\r\n DOMAIN_SEPARATOR = keccak256(\r\n abi.encode(\r\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\r\n keccak256(bytes(name)),\r\n keccak256(bytes(\"1\")),\r\n chainId,\r\n address(this)\r\n )\r\n );\r\n }\r\n\r\n function _mint(address to, uint256 value) internal {\r\n totalSupply = totalSupply.add(value);\r\n balanceOf[to] = balanceOf[to].add(value);\r\n emit Transfer(address(0), to, value);\r\n }\r\n\r\n function _burn(address from, uint256 value) internal {\r\n balanceOf[from] = balanceOf[from].sub(value);\r\n totalSupply = totalSupply.sub(value);\r\n emit Transfer(from, address(0), value);\r\n }\r\n\r\n function _approve(\r\n address owner,\r\n address spender,\r\n uint256 value\r\n ) private {\r\n allowance[owner][spender] = value;\r\n emit Approval(owner, spender, value);\r\n }\r\n\r\n function _transfer(\r\n address from,\r\n address to,\r\n uint256 value\r\n ) private {\r\n balanceOf[from] = balanceOf[from].sub(value);\r\n balanceOf[to] = balanceOf[to].add(value);\r\n emit Transfer(from, to, value);\r\n }\r\n\r\n function approve(address spender, uint256 value) external returns (bool) {\r\n _approve(msg.sender, spender, value);\r\n return true;\r\n }\r\n\r\n function transfer(address to, uint256 value) external returns (bool) {\r\n _transfer(msg.sender, to, value);\r\n return true;\r\n }\r\n\r\n function transferFrom(\r\n address from,\r\n address to,\r\n uint256 value\r\n ) external returns (bool) {\r\n if (allowance[from][msg.sender] != uint256(-1)) {\r\n allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);\r\n }\r\n _transfer(from, to, value);\r\n return true;\r\n }\r\n\r\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\r\n _approve(msg.sender, spender, allowance[msg.sender][spender].add(addedValue));\r\n return true;\r\n }\r\n\r\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\r\n _approve(msg.sender, spender, allowance[msg.sender][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\r\n return true;\r\n }\r\n\r\n function permit(\r\n address owner,\r\n address spender,\r\n uint256 value,\r\n uint256 deadline,\r\n uint8 v,\r\n bytes32 r,\r\n bytes32 s\r\n ) external {\r\n require(deadline >= block.timestamp, \"Bridge: EXPIRED\");\r\n bytes32 digest = keccak256(\r\n abi.encodePacked(\r\n \"\\x19\\x01\",\r\n DOMAIN_SEPARATOR,\r\n keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\r\n )\r\n );\r\n address recoveredAddress = ecrecover(digest, v, r, s);\r\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"Bridge: INVALID_SIGNATURE\");\r\n _approve(owner, spender, value);\r\n }\r\n}\r\n"
  36. },
  37. "contracts/interfaces/IMirrorgateFeeLibrary.sol": {
  38. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity ^0.7.6;\r\npragma abicoder v2;\r\nimport \"../Pool.sol\";\r\n\r\ninterface IMirrorgateFeeLibrary {\r\n function getFees(\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n uint16 _dstChainId,\r\n address _from,\r\n uint256 _amountSD\r\n ) external returns (Pool.SwapObj memory s);\r\n\r\n function getVersion() external view returns (string memory);\r\n}\r\n"
  39. },
  40. "contracts/Factory.sol": {
  41. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\r\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\r\nimport \"./Pool.sol\";\r\n\r\ncontract Factory is Ownable {\r\n using SafeMath for uint256;\r\n\r\n //---------------------------------------------------------------------------\r\n // VARIABLES\r\n mapping(uint256 => Pool) public getPool; // poolId -> PoolInfo\r\n address[] public allPools;\r\n address public immutable router;\r\n address public defaultFeeLibrary; // address for retrieving fee params for swaps\r\n\r\n //---------------------------------------------------------------------------\r\n // MODIFIERS\r\n modifier onlyRouter() {\r\n require(msg.sender == router, \"Mirrorgate: caller must be Router.\");\r\n _;\r\n }\r\n\r\n constructor(address _router) {\r\n require(_router != address(0x0), \"Mirrorgate: _router cant be 0x0\"); // 1 time only\r\n router = _router;\r\n }\r\n\r\n function setDefaultFeeLibrary(address _defaultFeeLibrary) external onlyOwner {\r\n require(_defaultFeeLibrary != address(0x0), \"Mirrorgate: fee library cant be 0x0\");\r\n defaultFeeLibrary = _defaultFeeLibrary;\r\n }\r\n\r\n function allPoolsLength() external view returns (uint256) {\r\n return allPools.length;\r\n }\r\n\r\n function createPool(\r\n uint256 _poolId,\r\n address _token,\r\n uint8 _sharedDecimals,\r\n uint8 _localDecimals,\r\n string memory _name,\r\n string memory _symbol\r\n ) public onlyRouter returns (address poolAddress) {\r\n require(address(getPool[_poolId]) == address(0x0), \"Mirrorgate: Pool already created\");\r\n\r\n Pool pool = new Pool(_poolId, router, _token, _sharedDecimals, _localDecimals, defaultFeeLibrary, _name, _symbol);\r\n getPool[_poolId] = pool;\r\n poolAddress = address(pool);\r\n allPools.push(poolAddress);\r\n }\r\n\r\n function renounceOwnership() public override onlyOwner {}\r\n}\r\n"
  42. },
  43. "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
  44. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
  45. },
  46. "contracts/interfaces/IMirrorgateRouter.sol": {
  47. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\ninterface IMirrorgateRouter {\r\n struct lzTxObj {\r\n uint256 dstGasForCall;\r\n uint256 dstNativeAmount;\r\n bytes dstNativeAddr;\r\n }\r\n\r\n function addLiquidity(\r\n uint256 _poolId,\r\n uint256 _amountLD,\r\n address _to\r\n ) external;\r\n\r\n function swap(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLD,\r\n uint256 _minAmountLD,\r\n lzTxObj memory _lzTxParams,\r\n bytes calldata _to,\r\n bytes calldata _payload\r\n ) external payable;\r\n\r\n function redeemRemote(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLP,\r\n uint256 _minAmountLD,\r\n bytes calldata _to,\r\n lzTxObj memory _lzTxParams\r\n ) external payable;\r\n\r\n function instantRedeemLocal(\r\n uint16 _srcPoolId,\r\n uint256 _amountLP,\r\n address _to\r\n ) external returns (uint256);\r\n\r\n function redeemLocal(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLP,\r\n bytes calldata _to,\r\n lzTxObj memory _lzTxParams\r\n ) external payable;\r\n\r\n function sendCredits(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress\r\n ) external payable;\r\n\r\n function quoteLayerZeroFee(\r\n uint16 _dstChainId,\r\n uint8 _functionType,\r\n bytes calldata _toAddress,\r\n bytes calldata _transferAndCallPayload,\r\n lzTxObj memory _lzTxParams\r\n ) external view returns (uint256, uint256);\r\n}\r\n"
  48. },
  49. "contracts/interfaces/IMirrorgateReceiver.sol": {
  50. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\n\r\ninterface IMirrorgateReceiver {\r\n function mgReceive(\r\n uint16 _chainId,\r\n bytes memory _srcAddress,\r\n uint256 _nonce,\r\n address _token,\r\n uint256 amountLD,\r\n bytes memory payload\r\n ) external;\r\n}\r\n"
  51. },
  52. "contracts/OmnichainFungibleToken.sol": {
  53. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\r\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\r\nimport \"./interfaces/ILayerZeroReceiver.sol\";\r\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\r\nimport \"./interfaces/ILayerZeroUserApplicationConfig.sol\";\r\n\r\n//---------------------------------------------------------------------------\r\n// THIS CONTRACT IS OF BUSINESS LICENSE. CONTACT US BEFORE YOU USE IT.\r\n//\r\n// LayerZero is pushing now a new cross-chain token standard with permissive license soon\r\n//\r\n// Stay tuned for maximum cross-chain compatability of your token\r\n//---------------------------------------------------------------------------\r\ncontract OmnichainFungibleToken is ERC20, Ownable, ILayerZeroReceiver, ILayerZeroUserApplicationConfig {\r\n ILayerZeroEndpoint immutable public endpoint;\r\n mapping(uint16 => bytes) public dstContractLookup; // a map of the connected contracts\r\n bool public paused; // indicates cross chain transfers are paused\r\n bool public isMain; // indicates this contract is on the main chain\r\n\r\n event Paused(bool isPaused);\r\n event SendToChain(uint16 srcChainId, bytes toAddress, uint256 qty, uint64 nonce);\r\n event ReceiveFromChain(uint16 srcChainId, address toAddress, uint256 qty, uint64 nonce);\r\n\r\n constructor(\r\n string memory _name,\r\n string memory _symbol,\r\n address _endpoint,\r\n uint16 _mainChainId,\r\n uint256 _initialSupplyOnMainEndpoint\r\n ) ERC20(_name, _symbol) {\r\n // only mint the total supply on the main chain\r\n if (ILayerZeroEndpoint(_endpoint).getChainId() == _mainChainId) {\r\n _mint(msg.sender, _initialSupplyOnMainEndpoint);\r\n isMain = true;\r\n }\r\n // set the LayerZero endpoint\r\n endpoint = ILayerZeroEndpoint(_endpoint);\r\n }\r\n\r\n function pauseSendTokens(bool _pause) external onlyOwner {\r\n paused = _pause;\r\n emit Paused(_pause);\r\n }\r\n\r\n function setDestination(uint16 _dstChainId, bytes calldata _destinationContractAddress) public onlyOwner {\r\n dstContractLookup[_dstChainId] = _destinationContractAddress;\r\n }\r\n\r\n function chainId() external view returns (uint16){\r\n return endpoint.getChainId();\r\n }\r\n\r\n function sendTokens(\r\n uint16 _dstChainId, // send tokens to this chainId\r\n bytes calldata _to, // where to deliver the tokens on the destination chain\r\n uint256 _qty, // how many tokens to send\r\n address _zroPaymentAddress, // ZRO payment address\r\n bytes calldata _adapterParam // txParameters\r\n ) public payable {\r\n require(!paused, \"OFT: sendTokens() is currently paused\");\r\n\r\n // lock by transferring to this contract if leaving the main chain, otherwise burn\r\n if (isMain) {\r\n _transfer(msg.sender, address(this), _qty);\r\n } else {\r\n _burn(msg.sender, _qty);\r\n }\r\n\r\n // abi.encode() the payload with the values to send\r\n bytes memory payload = abi.encode(_to, _qty);\r\n\r\n // send LayerZero message\r\n endpoint.send{value: msg.value}(\r\n _dstChainId, // destination chainId\r\n dstContractLookup[_dstChainId], // destination UA address\r\n payload, // abi.encode()'ed bytes\r\n msg.sender, // refund address (LayerZero will refund any extra gas back to msg.sender\r\n _zroPaymentAddress, // 'zroPaymentAddress'\r\n _adapterParam // 'adapterParameters'\r\n );\r\n uint64 nonce = endpoint.getOutboundNonce(_dstChainId, address(this));\r\n emit SendToChain(_dstChainId, _to, _qty, nonce);\r\n }\r\n\r\n function lzReceive(\r\n uint16 _srcChainId,\r\n bytes memory _fromAddress,\r\n uint64 _nonce,\r\n bytes memory _payload\r\n ) external override {\r\n require(msg.sender == address(endpoint)); // lzReceive must only be called by the endpoint\r\n require(\r\n _fromAddress.length == dstContractLookup[_srcChainId].length && keccak256(_fromAddress) == keccak256(dstContractLookup[_srcChainId]),\r\n \"OFT: invalid source sending contract\"\r\n );\r\n\r\n // decode and load the toAddress\r\n (bytes memory _to, uint256 _qty) = abi.decode(_payload, (bytes, uint256));\r\n address toAddress;\r\n assembly { toAddress := mload(add(_to, 20)) }\r\n\r\n // if the toAddress is 0x0, burn it\r\n if (toAddress == address(0x0)) toAddress == address(0xdEaD);\r\n\r\n // on the main chain unlock via transfer, otherwise _mint\r\n if (isMain) {\r\n _transfer(address(this), toAddress, _qty);\r\n } else {\r\n _mint(toAddress, _qty);\r\n }\r\n\r\n emit ReceiveFromChain(_srcChainId, toAddress, _qty, _nonce);\r\n }\r\n\r\n function estimateSendTokensFee(uint16 _dstChainId, bytes calldata _toAddress, bool _useZro, bytes calldata _txParameters) external view returns (uint256 nativeFee, uint256 zroFee) {\r\n // mock the payload for sendTokens()\r\n bytes memory payload = abi.encode(_toAddress, 1);\r\n return endpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _txParameters);\r\n }\r\n\r\n //---------------------------DAO CALL----------------------------------------\r\n // generic config for user Application\r\n function setConfig(\r\n uint16 _version,\r\n uint16 _chainId,\r\n uint256 _configType,\r\n bytes calldata _config\r\n ) external override onlyOwner {\r\n endpoint.setConfig(_version, _chainId, _configType, _config);\r\n }\r\n\r\n function setSendVersion(uint16 _version) external override onlyOwner {\r\n endpoint.setSendVersion(_version);\r\n }\r\n\r\n function setReceiveVersion(uint16 _version) external override onlyOwner {\r\n endpoint.setReceiveVersion(_version);\r\n }\r\n\r\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner {\r\n endpoint.forceResumeReceive(_srcChainId, _srcAddress);\r\n }\r\n\r\n function renounceOwnership() public override onlyOwner {}\r\n}\r\n"
  54. },
  55. "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
  56. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n"
  57. },
  58. "contracts/mocks/LZEndpointMock.sol": {
  59. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\n\r\nimport \"../interfaces/ILayerZeroEndpoint.sol\";\r\nimport \"../interfaces/ILayerZeroReceiver.sol\";\r\npragma abicoder v2;\r\n\r\n/*\r\nmocking multi endpoint connection.\r\n- send() will short circuit to lzReceive() directly\r\n- no reentrancy guard. the real LayerZero endpoint on main net has a send and receive guard, respectively.\r\nif we run a ping-pong-like application, the recursive call might use all gas limit in the block.\r\n- not using any messaging library, hence all messaging library func, e.g. estimateFees, version, will not work\r\n*/\r\ncontract LZEndpointMock is ILayerZeroEndpoint {\r\n mapping(address => address) public lzEndpointLookup;\r\n\r\n uint16 public mockChainId;\r\n address payable public mockOracle;\r\n address payable public mockRelayer;\r\n uint256 public mockBlockConfirmations;\r\n uint16 public mockLibraryVersion;\r\n uint256 public mockStaticNativeFee;\r\n uint16 public mockLayerZeroVersion;\r\n uint16 public mockReceiveVersion;\r\n uint16 public mockSendVersion;\r\n\r\n // inboundNonce = [srcChainId][srcAddress].\r\n mapping(uint16 => mapping(bytes => uint64)) public inboundNonce;\r\n // outboundNonce = [dstChainId][srcAddress].\r\n mapping(uint16 => mapping(address => uint64)) public outboundNonce;\r\n\r\n event SetConfig(uint16 version, uint16 chainId, uint256 configType, bytes config);\r\n event ForceResumeReceive(uint16 srcChainId, bytes srcAddress);\r\n\r\n constructor(uint16 _chainId) {\r\n mockStaticNativeFee = 42;\r\n mockLayerZeroVersion = 1;\r\n mockChainId = _chainId;\r\n }\r\n\r\n function getChainId() external view override returns (uint16) {\r\n return mockChainId;\r\n }\r\n\r\n function setDestLzEndpoint(address destAddr, address lzEndpointAddr) external {\r\n lzEndpointLookup[destAddr] = lzEndpointAddr;\r\n }\r\n\r\n function send(\r\n uint16 _chainId,\r\n bytes calldata _destination,\r\n bytes calldata _payload,\r\n address payable, /*_refundAddress*/\r\n address, /*_zroPaymentAddress*/\r\n bytes memory dstGas\r\n ) external payable override {\r\n address destAddr = packedBytesToAddr(_destination);\r\n address lzEndpoint = lzEndpointLookup[destAddr];\r\n\r\n require(lzEndpoint != address(0), \"LayerZeroMock: destination LayerZero Endpoint not found\");\r\n\r\n uint64 nonce;\r\n {\r\n nonce = ++outboundNonce[_chainId][msg.sender];\r\n }\r\n\r\n // Mock the relayer paying the dstNativeAddr the amount of extra native token\r\n {\r\n uint256 dstNative;\r\n address dstNativeAddr;\r\n assembly {\r\n dstNative := mload(add(dstGas, 66))\r\n dstNativeAddr := mload(add(dstGas, 86))\r\n }\r\n\r\n if (dstNativeAddr == 0x90F79bf6EB2c4f870365E785982E1f101E93b906) {\r\n require(dstNative == 453, \"Gas incorrect\");\r\n require(1 != 1, \"NativeGasParams check\");\r\n }\r\n\r\n // Doesnt actually transfer the native amount to the other side\r\n }\r\n\r\n bytes memory bytesSourceUserApplicationAddr = addrToPackedBytes(address(msg.sender)); // cast this address to bytes\r\n\r\n inboundNonce[_chainId][abi.encodePacked(msg.sender)] = nonce;\r\n LZEndpointMock(lzEndpoint).receiveAndForward(destAddr, mockChainId, bytesSourceUserApplicationAddr, nonce, _payload);\r\n }\r\n\r\n function receiveAndForward(\r\n address _destAddr,\r\n uint16 _srcChainId,\r\n bytes memory _srcAddress,\r\n uint64 _nonce,\r\n bytes memory _payload\r\n ) external {\r\n ILayerZeroReceiver(_destAddr).lzReceive(_srcChainId, _srcAddress, _nonce, _payload); // invoke lzReceive\r\n }\r\n\r\n // override from ILayerZeroEndpoint\r\n function estimateFees(\r\n uint16,\r\n address,\r\n bytes calldata,\r\n bool,\r\n bytes calldata\r\n ) external view override returns (uint256, uint256) {\r\n return (mockStaticNativeFee, 0); // just a mock\r\n }\r\n\r\n // give 20 bytes, return the decoded address\r\n function packedBytesToAddr(bytes calldata _b) public pure returns (address) {\r\n address addr;\r\n assembly {\r\n let ptr := mload(0x40)\r\n calldatacopy(ptr, sub(_b.offset, 2), add(_b.length, 2))\r\n addr := mload(sub(ptr, 10))\r\n }\r\n return addr;\r\n }\r\n\r\n // given an address, return the 20 bytes\r\n function addrToPackedBytes(address _a) public pure returns (bytes memory) {\r\n bytes memory data = abi.encodePacked(_a);\r\n return data;\r\n }\r\n\r\n function setConfig(\r\n uint16 _version,\r\n uint16 _chainId,\r\n uint256 _configType,\r\n bytes memory _config\r\n ) external override {\r\n emit SetConfig(_version, _chainId, _configType, _config);\r\n }\r\n\r\n function getConfig(\r\n uint16, /*_version*/\r\n uint16, /*_chainId*/\r\n address, /*_ua*/\r\n uint256 /*_configType*/\r\n ) external pure override returns (bytes memory) {\r\n return \"\";\r\n }\r\n\r\n function receivePayload(\r\n uint16 _srcChainId,\r\n bytes calldata _srcAddress,\r\n address _dstAddress,\r\n uint64 _nonce,\r\n uint256 _gasLimit,\r\n bytes calldata _payload\r\n ) external override {}\r\n\r\n function setSendVersion(uint16 _version) external override {\r\n mockSendVersion = _version;\r\n }\r\n\r\n function setReceiveVersion(uint16 _version) external override {\r\n mockReceiveVersion = _version;\r\n }\r\n\r\n function getSendVersion(\r\n address /*_userApplication*/\r\n ) external pure override returns (uint16) {\r\n return 1;\r\n }\r\n\r\n function getReceiveVersion(\r\n address /*_userApplication*/\r\n ) external pure override returns (uint16) {\r\n return 1;\r\n }\r\n\r\n function getInboundNonce(uint16 _chainID, bytes calldata _srcAddress) external view override returns (uint64) {\r\n return inboundNonce[_chainID][_srcAddress];\r\n }\r\n\r\n function getOutboundNonce(uint16 _chainID, address _srcAddress) external view override returns (uint64) {\r\n return outboundNonce[_chainID][_srcAddress];\r\n }\r\n\r\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override {\r\n emit ForceResumeReceive(_srcChainId, _srcAddress);\r\n }\r\n\r\n function retryPayload(\r\n uint16 _srcChainId,\r\n bytes calldata _srcAddress,\r\n bytes calldata _payload\r\n ) external pure override {}\r\n\r\n function hasStoredPayload(uint16 /*_srcChainId*/, bytes calldata /*_srcAddress*/) external pure override returns (bool) {\r\n return true;\r\n }\r\n\r\n function isSendingPayload() external pure override returns (bool) {\r\n return false;\r\n }\r\n\r\n function isReceivingPayload() external pure override returns (bool) {\r\n return false;\r\n }\r\n\r\n function getSendLibraryAddress(address /*_userApplication*/) external view override returns (address) {\r\n return address(this);\r\n }\r\n\r\n function getReceiveLibraryAddress(address /*_userApplication*/) external view override returns (address) {\r\n return address(this);\r\n }\r\n}\r\n"
  60. },
  61. "contracts/MirrorgateEthVault.sol": {
  62. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n// Copyright (C) 2015, 2016, 2017 Dapphub\r\n\r\n// This program is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n\r\n// This program is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n\r\n// You should have received a copy of the GNU General Public License\r\n// along with this program. If not, see <http://www.gnu.org/licenses/>.\r\n\r\npragma solidity ^0.7.6;\r\n\r\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\r\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\r\nimport \"./interfaces/IMirrorgateEthVault.sol\";\r\n\r\n// This contract always UNWRAPS the erc20 for native gas token on transfer + transferFrom.\r\n// If you wish to disable the transfer auto-unwrap, you can specify _to addresses with `setNoUnwrapTo`\r\ncontract MirrorgateEthVault is IMirrorgateEthVault, Ownable, ReentrancyGuard {\r\n string public constant name = \"Mirrorgate Ether Vault\";\r\n string public constant symbol = \"MGETH\";\r\n uint8 public constant decimals = 18;\r\n\r\n uint256 public totalSupply;\r\n\r\n event Approval(address indexed src, address indexed guy, uint wad);\r\n event Transfer(address indexed src, address indexed dst, uint wad);\r\n event Deposit(address indexed dst, uint wad);\r\n event Withdrawal(address indexed src, uint wad);\r\n event TransferNative(address indexed src, address indexed dst, uint wad);\r\n\r\n mapping(address => uint) public balanceOf;\r\n mapping(address => mapping(address => uint)) public allowance;\r\n mapping(address => bool) public noUnwrapTo;\r\n\r\n // if you do NOT wish to unwrap eth on transfers TO certain addresses\r\n function setNoUnwrapTo(address _addr) external onlyOwner {\r\n noUnwrapTo[_addr] = true;\r\n }\r\n\r\n function deposit() public payable override {\r\n balanceOf[msg.sender] += msg.value;\r\n totalSupply += msg.value;\r\n emit Deposit(msg.sender, msg.value);\r\n }\r\n\r\n function withdraw(uint wad) external override {\r\n require(balanceOf[msg.sender] >= wad);\r\n balanceOf[msg.sender] -= wad;\r\n msg.sender.transfer(wad);\r\n totalSupply -= wad;\r\n emit Withdrawal(msg.sender, wad);\r\n }\r\n\r\n function approve(address guy, uint wad) external override returns (bool) {\r\n allowance[msg.sender][guy] = wad;\r\n emit Approval(msg.sender, guy, wad);\r\n return true;\r\n }\r\n\r\n function transfer(address dst, uint wad) external override returns (bool) {\r\n return transferFrom(msg.sender, dst, wad);\r\n }\r\n\r\n function transferFrom(address src, address dst, uint wad) public override nonReentrant returns (bool) {\r\n require(balanceOf[src] >= wad);\r\n\r\n if (src != msg.sender && allowance[src][msg.sender] != uint(- 1)) {\r\n require(allowance[src][msg.sender] >= wad);\r\n allowance[src][msg.sender] -= wad;\r\n }\r\n\r\n // always decrement the src (payer) address\r\n balanceOf[src] -= wad;\r\n\r\n if (noUnwrapTo[dst]) {\r\n // we do *not* unwrap\r\n balanceOf[dst] += wad;\r\n emit Transfer(src, dst, wad);\r\n\r\n } else {\r\n // unwrap and send native gas token\r\n totalSupply -= wad;\r\n // if its getting unwrapped, decrement the totalSupply\r\n (bool success,) = dst.call{value : wad}(\"\");\r\n require(success, \"SGETH: failed to transfer\");\r\n emit TransferNative(src, dst, wad);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n function renounceOwnership() public override onlyOwner {}\r\n\r\n receive() external payable {\r\n deposit();\r\n }\r\n\r\n}\r\n"
  63. },
  64. "contracts/interfaces/IMirrorgateEthVault.sol": {
  65. "content": "// SPDX-License-Identifier: BUSL-1.1\r\npragma solidity 0.7.6;\r\n\r\ninterface IMirrorgateEthVault {\r\n function deposit() external payable;\r\n\r\n function transfer(address to, uint value) external returns (bool);\r\n\r\n function withdraw(uint) external;\r\n\r\n function approve(address guy, uint wad) external returns (bool);\r\n\r\n function transferFrom(address src, address dst, uint wad) external returns (bool);\r\n}\r\n"
  66. },
  67. "contracts/RouterETH.sol": {
  68. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\nimport \"./interfaces/IMirrorgateRouter.sol\";\r\nimport \"./interfaces/IMirrorgateEthVault.sol\";\r\n\r\ncontract RouterETH {\r\n address public immutable mirrorgateEthVault;\r\n IMirrorgateRouter public immutable mirrorgateRouter;\r\n uint16 public immutable poolId;\r\n\r\n constructor(address _mirrorgateEthVault, address _mirrorgateRouter, uint16 _poolId){\r\n require(_mirrorgateEthVault != address(0x0), \"RouterETH: _mirrorgateEthVault cant be 0x0\");\r\n require(_mirrorgateRouter != address(0x0), \"RouterETH: _mirrorgateRouter cant be 0x0\");\r\n mirrorgateEthVault = _mirrorgateEthVault;\r\n mirrorgateRouter = IMirrorgateRouter(_mirrorgateRouter);\r\n poolId = _poolId;\r\n }\r\n\r\n function addLiquidityETH() external payable {\r\n require(msg.value > 0, \"Mirrorgate: msg.value is 0\");\r\n\r\n uint256 amountLD = msg.value;\r\n\r\n // wrap the ETH into WETH\r\n IMirrorgateEthVault(mirrorgateEthVault).deposit{value: amountLD}();\r\n IMirrorgateEthVault(mirrorgateEthVault).approve(address(mirrorgateRouter), amountLD);\r\n\r\n // addLiquidity using the WETH that was just wrapped,\r\n // and mint the LP token to the msg.sender\r\n mirrorgateRouter.addLiquidity(\r\n poolId,\r\n amountLD,\r\n msg.sender\r\n );\r\n }\r\n\r\n // compose mirrorgate to swap ETH on the source to ETH on the destination\r\n function swapETH(\r\n uint16 _dstChainId, // destination mirrorgate chainId\r\n address payable _refundAddress, // refund additional messageFee to this address\r\n bytes calldata _toAddress, // the receiver of the destination ETH\r\n uint256 _amountLD, // the amount, in Local Decimals, to be swapped\r\n uint256 _minAmountLD // the minimum amount accepted out on destination\r\n ) external payable {\r\n require(msg.value > _amountLD, \"Mirrorgate: msg.value must be > _amountLD\");\r\n\r\n // wrap the ETH into WETH\r\n IMirrorgateEthVault(mirrorgateEthVault).deposit{value: _amountLD}();\r\n IMirrorgateEthVault(mirrorgateEthVault).approve(address(mirrorgateRouter), _amountLD);\r\n\r\n // messageFee is the remainder of the msg.value after wrap\r\n uint256 messageFee = msg.value - _amountLD;\r\n\r\n // compose a mirrorgate swap() using the WETH that was just wrapped\r\n mirrorgateRouter.swap{value: messageFee}(\r\n _dstChainId, // destination mirrorgate chainId\r\n poolId, // WETH mirrorgate poolId on source\r\n poolId, // WETH mirrorgate poolId on destination\r\n _refundAddress, // message refund address if overpaid\r\n _amountLD, // the amount in Local Decimals to swap()\r\n _minAmountLD, // the minimum amount swap()er would allow to get out (ie: slippage)\r\n IMirrorgateRouter.lzTxObj(0, 0, \"0x\"),\r\n _toAddress, // address on destination to send to\r\n bytes(\"\") // empty payload, since sending to EOA\r\n );\r\n }\r\n\r\n // this contract needs to accept ETH\r\n receive() external payable {}\r\n\r\n}\r\n"
  69. },
  70. "contracts/mocks/LoopBackMock.sol": {
  71. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\nimport \"../interfaces/IMirrorgateReceiver.sol\";\r\nimport \"../interfaces/IMirrorgateRouter.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\n\r\nimport \"hardhat/console.sol\";\r\n\r\ncontract LoopBackMock is IMirrorgateReceiver {\r\n IMirrorgateRouter public immutable router;\r\n\r\n event LoopBack(bytes srcAddress, uint256 srcPoolId, uint256 dstPoolId, uint256 amount);\r\n\r\n constructor(address _router) {\r\n router = IMirrorgateRouter(_router);\r\n }\r\n\r\n bool paused;\r\n\r\n function mgReceive(\r\n uint16 _chainId,\r\n bytes memory _srcAddress,\r\n uint256, /*_nonce*/\r\n address _token,\r\n uint256 amountLD,\r\n bytes memory payload\r\n ) external override {\r\n require(!paused, \"Failed sgReceive due to pause\");\r\n\r\n require(msg.sender == address(router), \"only router\");\r\n uint256 halfAmount = amountLD / 2;\r\n bytes memory srcAddress = _srcAddress;\r\n\r\n // approve the router to spend the halfAmount;\r\n IERC20(_token).approve(address(router), halfAmount);\r\n IMirrorgateRouter.lzTxObj memory txObj = IMirrorgateRouter.lzTxObj(500000, 0, \"\");\r\n (uint256 srcPoolId, uint256 dstPoolId) = abi.decode(payload, (uint256, uint256));\r\n\r\n (uint256 nativeFee, ) = router.quoteLayerZeroFee(_chainId, 1, srcAddress, \"\", txObj);\r\n router.swap{value: nativeFee}(_chainId, srcPoolId, dstPoolId, address(this), halfAmount, 0, txObj, srcAddress, bytes(\"0x\"));\r\n\r\n emit LoopBack(srcAddress, srcPoolId, dstPoolId, halfAmount);\r\n }\r\n\r\n function pause(bool _paused) external {\r\n paused = _paused;\r\n }\r\n\r\n // be able to receive ether\r\n fallback() external payable {}\r\n\r\n receive() external payable {}\r\n}\r\n"
  72. },
  73. "hardhat/console.sol": {
  74. "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.4.22 <0.9.0;\n\nlibrary console {\n\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n\tfunction _sendLogPayload(bytes memory payload) private view {\n\t\tuint256 payloadLength = payload.length;\n\t\taddress consoleAddress = CONSOLE_ADDRESS;\n\t\tassembly {\n\t\t\tlet payloadStart := add(payload, 32)\n\t\t\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n\t\t}\n\t}\n\n\tfunction log() internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log()\"));\n\t}\n\n\tfunction logInt(int p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n\t}\n\n\tfunction logUint(uint p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n\t}\n\n\tfunction logString(string memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n\t}\n\n\tfunction logBool(bool p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n\t}\n\n\tfunction logAddress(address p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n\t}\n\n\tfunction logBytes(bytes memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n\t}\n\n\tfunction logBytes1(bytes1 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n\t}\n\n\tfunction logBytes2(bytes2 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n\t}\n\n\tfunction logBytes3(bytes3 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n\t}\n\n\tfunction logBytes4(bytes4 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n\t}\n\n\tfunction logBytes5(bytes5 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n\t}\n\n\tfunction logBytes6(bytes6 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n\t}\n\n\tfunction logBytes7(bytes7 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n\t}\n\n\tfunction logBytes8(bytes8 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n\t}\n\n\tfunction logBytes9(bytes9 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n\t}\n\n\tfunction logBytes10(bytes10 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n\t}\n\n\tfunction logBytes11(bytes11 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n\t}\n\n\tfunction logBytes12(bytes12 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n\t}\n\n\tfunction logBytes13(bytes13 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n\t}\n\n\tfunction logBytes14(bytes14 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n\t}\n\n\tfunction logBytes15(bytes15 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n\t}\n\n\tfunction logBytes16(bytes16 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n\t}\n\n\tfunction logBytes17(bytes17 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n\t}\n\n\tfunction logBytes18(bytes18 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n\t}\n\n\tfunction logBytes19(bytes19 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n\t}\n\n\tfunction logBytes20(bytes20 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n\t}\n\n\tfunction logBytes21(bytes21 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n\t}\n\n\tfunction logBytes22(bytes22 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n\t}\n\n\tfunction logBytes23(bytes23 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n\t}\n\n\tfunction logBytes24(bytes24 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n\t}\n\n\tfunction logBytes25(bytes25 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n\t}\n\n\tfunction logBytes26(bytes26 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n\t}\n\n\tfunction logBytes27(bytes27 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n\t}\n\n\tfunction logBytes28(bytes28 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n\t}\n\n\tfunction logBytes29(bytes29 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n\t}\n\n\tfunction logBytes30(bytes30 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n\t}\n\n\tfunction logBytes31(bytes31 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n\t}\n\n\tfunction logBytes32(bytes32 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n\t}\n\n\tfunction log(uint p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n\t}\n\n\tfunction log(string memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n\t}\n\n\tfunction log(bool p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n\t}\n\n\tfunction log(address p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n\t}\n\n\tfunction log(uint p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n\t}\n\n\tfunction log(address p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n\t}\n\n\tfunction log(address p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n\t}\n\n\tfunction log(address p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n\t}\n\n\tfunction log(address p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n}\n"
  75. },
  76. "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": {
  77. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n"
  78. },
  79. "@openzeppelin/contracts/utils/Address.sol": {
  80. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n"
  81. },
  82. "contracts/mocks/MockToken.sol": {
  83. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\r\n\r\ncontract MockToken is ERC20 {\r\n constructor(\r\n string memory name_,\r\n string memory symbol_,\r\n uint8 decimals_\r\n ) ERC20(name_, symbol_) {\r\n _setupDecimals(decimals_);\r\n _mint(msg.sender, 1000000000 * (10**decimals_));\r\n }\r\n\r\n bool paused;\r\n\r\n function mint(address _to, uint256 _amount) public {\r\n _mint(_to, _amount);\r\n }\r\n\r\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\r\n // need to mock some failed transfer events\r\n require(!paused, \"Failed transfer due to pause\");\r\n\r\n return super.transfer(recipient, amount);\r\n }\r\n\r\n function transferFrom(\r\n address sender,\r\n address recipient,\r\n uint256 amount\r\n ) public virtual override returns (bool) {\r\n // need to mock some failed transfer events\r\n require(!paused, \"Failed transfer due to pause\");\r\n return super.transferFrom(sender, recipient, amount);\r\n }\r\n\r\n function pauseTransfers(bool _paused) external {\r\n paused = _paused;\r\n }\r\n}\r\n"
  84. },
  85. "contracts/LPStaking.sol": {
  86. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\n\r\n// imports\r\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\r\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\r\nimport \"./MirrorgateToken.sol\";\r\n\r\n// interfaces\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\n\r\n// libraries\r\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\r\n\r\ncontract LPStaking is Ownable {\r\n using SafeMath for uint256;\r\n using SafeERC20 for IERC20;\r\n // Info of each user.\r\n struct UserInfo {\r\n uint256 amount; // How many LP tokens the user has provided.\r\n uint256 rewardDebt; // Reward debt. See explanation below.\r\n //\r\n // We do some fancy math here. Basically, any point in time, the amount of STGs\r\n // entitled to a user but is pending to be distributed is:\r\n //\r\n // pending reward = (user.amount * pool.accStargatePerShare) - user.rewardDebt\r\n //\r\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\r\n // 1. The pool's `accStargatePerShare` (and `lastRewardBlock`) gets updated.\r\n // 2. User receives the pending reward sent to his/her address.\r\n // 3. User's `amount` gets updated.\r\n // 4. User's `rewardDebt` gets updated.\r\n }\r\n // Info of each pool.\r\n struct PoolInfo {\r\n IERC20 lpToken; // Address of LP token contract.\r\n uint256 allocPoint; // How many allocation points assigned to this pool. STGs to distribute per block.\r\n uint256 lastRewardBlock; // Last block number that STGs distribution occurs.\r\n uint256 accMirrorgatePerShare; // Accumulated STGs per share, times 1e12. See below.\r\n }\r\n // The STG TOKEN!\r\n MirrorgateToken public mirrorgate;\r\n // Block number when bonus STG period ends.\r\n uint256 public bonusEndBlock;\r\n // STG tokens created per block.\r\n uint256 public mirrorgatePerBlock;\r\n // Bonus multiplier for early stargate makers.\r\n uint256 public constant BONUS_MULTIPLIER = 1;\r\n // Track which tokens have been added.\r\n mapping(address => bool) private addedLPTokens;\r\n\r\n mapping(uint256 => uint256) public lpBalances;\r\n\r\n // Info of each pool.\r\n PoolInfo[] public poolInfo;\r\n // Info of each user that stakes LP tokens.\r\n mapping(uint256 => mapping(address => UserInfo)) public userInfo;\r\n // Total allocation points. Must be the sum of all allocation points in all pools.\r\n uint256 public totalAllocPoint = 0;\r\n // The block number when STG mining starts.\r\n uint256 public startBlock;\r\n event Deposit(address indexed user, uint256 indexed pid, uint256 amount);\r\n event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);\r\n event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);\r\n\r\n constructor(\r\n MirrorgateToken _mirrorgate,\r\n uint256 _mirrorgatePerBlock,\r\n uint256 _startBlock,\r\n uint256 _bonusEndBlock\r\n ) {\r\n require(_startBlock >= block.number, \"LPStaking: _startBlock must be >= current block\");\r\n require(_bonusEndBlock >= _startBlock, \"LPStaking: _bonusEndBlock must be > than _startBlock\");\r\n require(address(_mirrorgate) != address(0x0), \"Mirrorgate: _mirrorgate cannot be 0x0\");\r\n mirrorgate = _mirrorgate;\r\n mirrorgatePerBlock = _mirrorgatePerBlock;\r\n startBlock = _startBlock;\r\n bonusEndBlock = _bonusEndBlock;\r\n }\r\n\r\n function poolLength() external view returns (uint256) {\r\n return poolInfo.length;\r\n }\r\n\r\n /// @notice handles adding a new LP token (Can only be called by the owner)\r\n /// @param _allocPoint The alloc point is used as the weight of the pool against all other alloc points added.\r\n /// @param _lpToken The lp token address\r\n function add(uint256 _allocPoint, IERC20 _lpToken) public onlyOwner {\r\n massUpdatePools();\r\n require(address(_lpToken) != address(0x0), \"Mirrorgate: lpToken cant be 0x0\");\r\n require(addedLPTokens[address(_lpToken)] == false, \"Mirrorgate: _lpToken already exists\");\r\n addedLPTokens[address(_lpToken)] = true;\r\n uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock;\r\n totalAllocPoint = totalAllocPoint.add(_allocPoint);\r\n poolInfo.push(PoolInfo({lpToken: _lpToken, allocPoint: _allocPoint, lastRewardBlock: lastRewardBlock, accMirrorgatePerShare: 0}));\r\n }\r\n\r\n function set(uint256 _pid, uint256 _allocPoint) public onlyOwner {\r\n massUpdatePools();\r\n totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);\r\n poolInfo[_pid].allocPoint = _allocPoint;\r\n }\r\n\r\n function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) {\r\n if (_to <= bonusEndBlock) {\r\n return _to.sub(_from).mul(BONUS_MULTIPLIER);\r\n } else if (_from >= bonusEndBlock) {\r\n return _to.sub(_from);\r\n } else {\r\n return bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add(_to.sub(bonusEndBlock));\r\n }\r\n }\r\n\r\n function pendingMirrorgate(uint256 _pid, address _user) external view returns (uint256) {\r\n PoolInfo storage pool = poolInfo[_pid];\r\n UserInfo storage user = userInfo[_pid][_user];\r\n uint256 accMirrorgatePerShare = pool.accMirrorgatePerShare;\r\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\r\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\r\n uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);\r\n uint256 mirrorgateReward = multiplier.mul(mirrorgatePerBlock).mul(pool.allocPoint).div(totalAllocPoint);\r\n accMirrorgatePerShare = accMirrorgatePerShare.add(mirrorgateReward.mul(1e12).div(lpSupply));\r\n }\r\n return user.amount.mul(accMirrorgatePerShare).div(1e12).sub(user.rewardDebt);\r\n }\r\n\r\n function massUpdatePools() public {\r\n uint256 length = poolInfo.length;\r\n for (uint256 pid = 0; pid < length; ++pid) {\r\n updatePool(pid);\r\n }\r\n }\r\n\r\n function updatePool(uint256 _pid) public {\r\n PoolInfo storage pool = poolInfo[_pid];\r\n if (block.number <= pool.lastRewardBlock) {\r\n return;\r\n }\r\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\r\n if (lpSupply == 0) {\r\n pool.lastRewardBlock = block.number;\r\n return;\r\n }\r\n uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);\r\n uint256 mirrorgateReward = multiplier.mul(mirrorgatePerBlock).mul(pool.allocPoint).div(totalAllocPoint);\r\n\r\n pool.accMirrorgatePerShare = pool.accMirrorgatePerShare.add(mirrorgateReward.mul(1e12).div(lpSupply));\r\n pool.lastRewardBlock = block.number;\r\n }\r\n\r\n function deposit(uint256 _pid, uint256 _amount) public {\r\n PoolInfo storage pool = poolInfo[_pid];\r\n UserInfo storage user = userInfo[_pid][msg.sender];\r\n updatePool(_pid);\r\n if (user.amount > 0) {\r\n uint256 pending = user.amount.mul(pool.accMirrorgatePerShare).div(1e12).sub(user.rewardDebt);\r\n safeMirrorgateTransfer(msg.sender, pending);\r\n }\r\n pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);\r\n user.amount = user.amount.add(_amount);\r\n user.rewardDebt = user.amount.mul(pool.accMirrorgatePerShare).div(1e12);\r\n lpBalances[_pid] = lpBalances[_pid].add(_amount);\r\n emit Deposit(msg.sender, _pid, _amount);\r\n }\r\n\r\n function withdraw(uint256 _pid, uint256 _amount) public {\r\n PoolInfo storage pool = poolInfo[_pid];\r\n UserInfo storage user = userInfo[_pid][msg.sender];\r\n require(user.amount >= _amount, \"withdraw: _amount is too large\");\r\n updatePool(_pid);\r\n uint256 pending = user.amount.mul(pool.accMirrorgatePerShare).div(1e12).sub(user.rewardDebt);\r\n safeMirrorgateTransfer(msg.sender, pending);\r\n user.amount = user.amount.sub(_amount);\r\n user.rewardDebt = user.amount.mul(pool.accMirrorgatePerShare).div(1e12);\r\n pool.lpToken.safeTransfer(address(msg.sender), _amount);\r\n lpBalances[_pid] = lpBalances[_pid].sub(_amount);\r\n emit Withdraw(msg.sender, _pid, _amount);\r\n }\r\n\r\n /// @notice Withdraw without caring about rewards.\r\n /// @param _pid The pid specifies the pool\r\n function emergencyWithdraw(uint256 _pid) public {\r\n PoolInfo storage pool = poolInfo[_pid];\r\n UserInfo storage user = userInfo[_pid][msg.sender];\r\n uint256 userAmount = user.amount;\r\n user.amount = 0;\r\n user.rewardDebt = 0;\r\n pool.lpToken.safeTransfer(address(msg.sender), userAmount);\r\n lpBalances[_pid] = lpBalances[_pid].sub(userAmount);\r\n emit EmergencyWithdraw(msg.sender, _pid, userAmount);\r\n }\r\n\r\n /// @notice Safe transfer function, just in case if rounding error causes pool to not have enough STGs.\r\n /// @param _to The address to transfer tokens to\r\n /// @param _amount The quantity to transfer\r\n function safeMirrorgateTransfer(address _to, uint256 _amount) internal {\r\n uint256 mirrorgateBal = mirrorgate.balanceOf(address(this));\r\n if (_amount > mirrorgateBal) {\r\n IERC20(mirrorgate).safeTransfer(_to, mirrorgateBal);\r\n } else {\r\n IERC20(mirrorgate).safeTransfer(_to, _amount);\r\n }\r\n }\r\n\r\n function setMirrorgatePerBlock(uint256 _mirrorgatePerBlock) external onlyOwner {\r\n massUpdatePools();\r\n mirrorgatePerBlock = _mirrorgatePerBlock;\r\n }\r\n\r\n // Override the renounce ownership inherited by zeppelin ownable\r\n function renounceOwnership() public override onlyOwner {}\r\n}\r\n"
  87. },
  88. "@openzeppelin/contracts/utils/EnumerableSet.sol": {
  89. "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n"
  90. },
  91. "contracts/MirrorgateToken.sol": {
  92. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\n\r\nimport \"./OmnichainFungibleToken.sol\";\r\n\r\ncontract MirrorgateToken is OmnichainFungibleToken {\r\n constructor(\r\n string memory _name,\r\n string memory _symbol,\r\n address _endpoint,\r\n uint16 _mainEndpointId,\r\n uint256 _initialSupplyOnMainEndpoint\r\n ) OmnichainFungibleToken(_name, _symbol, _endpoint, _mainEndpointId, _initialSupplyOnMainEndpoint) {}\r\n}\r\n"
  93. },
  94. "contracts/libraries/MirrorgateFeeLibraryV02.sol": {
  95. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\nimport \"../interfaces/IMirrorgateFeeLibrary.sol\";\r\nimport \"../Pool.sol\";\r\nimport \"../Factory.sol\";\r\n\r\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\n\r\ncontract MirrorgateFeeLibraryV02 is IMirrorgateFeeLibrary, Ownable, ReentrancyGuard {\r\n using SafeMath for uint256;\r\n\r\n //---------------------------------------------------------------------------\r\n // VARIABLES\r\n\r\n // equilibrium func params. all in BPs * 10 ^ 2, i.e. 1 % = 10 ^ 6 units\r\n uint256 public constant DENOMINATOR = 1e18;\r\n uint256 public constant DELTA_1 = 6000 * 1e14;\r\n uint256 public constant DELTA_2 = 500 * 1e14;\r\n uint256 public constant LAMBDA_1 = 40 * 1e14;\r\n uint256 public constant LAMBDA_2 = 9960 * 1e14;\r\n uint256 public constant LP_FEE = 45 * 1e13;\r\n uint256 public constant PROTOCOL_FEE = 15 * 1e13;\r\n uint256 public constant PROTOCOL_SUBSIDY = 3 * 1e13;\r\n\r\n Factory public immutable factory;\r\n\r\n constructor(address _factory) {\r\n require(_factory != address(0x0), \"FeeLibrary: Factory cannot be 0x0\");\r\n factory = Factory(_factory);\r\n }\r\n\r\n function getFees(\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n uint16 _dstChainId,\r\n address, /*_from*/\r\n uint256 _amountSD\r\n ) external view override returns (Pool.SwapObj memory s) {\r\n // calculate the protocol fee\r\n s.protocolFee = _amountSD.mul(PROTOCOL_FEE).div(DENOMINATOR);\r\n\r\n // calculate the equilibrium Fee\r\n Pool pool = factory.getPool(_srcPoolId);\r\n Pool.ChainPath memory chainPath = pool.getChainPath(_dstChainId, _dstPoolId);\r\n\r\n // calculate the equilibrium fee\r\n (uint256 eqFee, uint256 protocolSubsidy) = _getEquilibriumFee(chainPath.idealBalance, chainPath.balance, _amountSD);\r\n s.eqFee = eqFee;\r\n s.protocolFee = s.protocolFee.sub(protocolSubsidy);\r\n\r\n // calculate the equilibrium reward\r\n address tokenAddress = pool.token();\r\n uint256 currentAssetSD = IERC20(tokenAddress).balanceOf(address(pool)).div(pool.convertRate());\r\n uint256 lpAsset = pool.totalLiquidity();\r\n if (lpAsset > currentAssetSD) {\r\n // in deficit\r\n uint256 poolDeficit = lpAsset.sub(currentAssetSD);\r\n uint256 rewardPoolSize = pool.eqFeePool();\r\n // reward capped at rewardPoolSize\r\n uint256 eqRewards = rewardPoolSize.mul(_amountSD).div(poolDeficit);\r\n if (eqRewards > rewardPoolSize) {\r\n eqRewards = rewardPoolSize;\r\n }\r\n s.eqReward = eqRewards;\r\n }\r\n\r\n // calculate the LP fee.\r\n s.lpFee = _amountSD.mul(LP_FEE).div(DENOMINATOR);\r\n\r\n return s;\r\n }\r\n\r\n function getEquilibriumFee(\r\n uint256 idealBalance,\r\n uint256 beforeBalance,\r\n uint256 amountSD\r\n ) external pure returns (uint256, uint256) {\r\n return _getEquilibriumFee(idealBalance, beforeBalance, amountSD);\r\n }\r\n\r\n function getTrapezoidArea(\r\n uint256 lambda,\r\n uint256 yOffset,\r\n uint256 xUpperBound,\r\n uint256 xLowerBound,\r\n uint256 xStart,\r\n uint256 xEnd\r\n ) external pure returns (uint256) {\r\n return _getTrapezoidArea(lambda, yOffset, xUpperBound, xLowerBound, xStart, xEnd);\r\n }\r\n\r\n function _getEquilibriumFee(\r\n uint256 idealBalance,\r\n uint256 beforeBalance,\r\n uint256 amountSD\r\n ) internal pure returns (uint256, uint256) {\r\n require(beforeBalance >= amountSD, \"Mirrorgate: not enough balance\");\r\n uint256 afterBalance = beforeBalance.sub(amountSD);\r\n\r\n uint256 safeZoneMax = idealBalance.mul(DELTA_1).div(DENOMINATOR);\r\n uint256 safeZoneMin = idealBalance.mul(DELTA_2).div(DENOMINATOR);\r\n\r\n uint256 eqFee = 0;\r\n uint256 protocolSubsidy = 0;\r\n\r\n if (afterBalance >= safeZoneMax) {\r\n // no fee zone, protocol subsidize it.\r\n eqFee = amountSD.mul(PROTOCOL_SUBSIDY).div(DENOMINATOR);\r\n protocolSubsidy = eqFee;\r\n } else if (afterBalance >= safeZoneMin) {\r\n // safe zone\r\n uint256 proxyBeforeBalance = beforeBalance < safeZoneMax ? beforeBalance : safeZoneMax;\r\n eqFee = _getTrapezoidArea(LAMBDA_1, 0, safeZoneMax, safeZoneMin, proxyBeforeBalance, afterBalance);\r\n } else {\r\n // danger zone\r\n if (beforeBalance >= safeZoneMin) {\r\n // across 2 or 3 zones\r\n // part 1\r\n uint256 proxyBeforeBalance = beforeBalance < safeZoneMax ? beforeBalance : safeZoneMax;\r\n eqFee = eqFee.add(_getTrapezoidArea(LAMBDA_1, 0, safeZoneMax, safeZoneMin, proxyBeforeBalance, safeZoneMin));\r\n // part 2\r\n eqFee = eqFee.add(_getTrapezoidArea(LAMBDA_2, LAMBDA_1, safeZoneMin, 0, safeZoneMin, afterBalance));\r\n } else {\r\n // only in danger zone\r\n // part 2 only\r\n eqFee = eqFee.add(_getTrapezoidArea(LAMBDA_2, LAMBDA_1, safeZoneMin, 0, beforeBalance, afterBalance));\r\n }\r\n }\r\n return (eqFee, protocolSubsidy);\r\n }\r\n\r\n function _getTrapezoidArea(\r\n uint256 lambda,\r\n uint256 yOffset,\r\n uint256 xUpperBound,\r\n uint256 xLowerBound,\r\n uint256 xStart,\r\n uint256 xEnd\r\n ) internal pure returns (uint256) {\r\n require(xEnd >= xLowerBound && xStart <= xUpperBound, \"Mirrorgate: balance out of bound\");\r\n uint256 xBoundWidth = xUpperBound.sub(xLowerBound);\r\n\r\n // xStartDrift = xUpperBound.sub(xStart);\r\n uint256 yStart = xUpperBound.sub(xStart).mul(lambda).div(xBoundWidth).add(yOffset);\r\n\r\n // xEndDrift = xUpperBound.sub(xEnd)\r\n uint256 yEnd = xUpperBound.sub(xEnd).mul(lambda).div(xBoundWidth).add(yOffset);\r\n\r\n // compute the area\r\n uint256 deltaX = xStart.sub(xEnd);\r\n return yStart.add(yEnd).mul(deltaX).div(2).div(DENOMINATOR);\r\n }\r\n\r\n function getVersion() external pure override returns (string memory) {\r\n return \"2.0.0\";\r\n }\r\n}\r\n"
  96. },
  97. "contracts/libraries/MirrorgateFeeLibraryV01.sol": {
  98. "content": "// SPDX-License-Identifier: BUSL-1.1\r\n\r\npragma solidity 0.7.6;\r\npragma abicoder v2;\r\n\r\nimport \"../interfaces/IMirrorgateFeeLibrary.sol\";\r\nimport \"../Pool.sol\";\r\nimport \"../Factory.sol\";\r\n// libraries\r\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\r\n\r\ncontract MirrorgateFeeLibraryV01 is IMirrorgateFeeLibrary, Ownable, ReentrancyGuard {\r\n using SafeMath for uint256;\r\n uint256 public constant BP_DENOMINATOR = 10000;\r\n\r\n constructor(address _factory) {\r\n require(_factory != address(0x0), \"FeeLibrary: Factory cannot be 0x0\");\r\n factory = Factory(_factory);\r\n }\r\n\r\n //---------------------------------------------------------------------------\r\n // VARIABLES\r\n Factory public factory;\r\n\r\n uint256 public lpFeeBP; // fee basis points for lp holders\r\n uint256 public protocolFeeBP; // fee basis points for xMirrorgate\r\n uint256 public eqFeeBP; // fee basis points for eqFeeBP\r\n uint256 public eqRewardBP; // fee basis points for eqRewardBP\r\n\r\n //---------------------------------------------------------------------------\r\n // EVENTS\r\n event FeesUpdated(uint256 lpFeeBP, uint256 protocolFeeBP);\r\n\r\n function getFees(\r\n uint256, /*_srcPoolId*/\r\n uint256, /*_dstPoolId*/\r\n uint16, /*_dstChainId*/\r\n address, /*_from*/\r\n uint256 _amountSD\r\n ) external view override returns (Pool.SwapObj memory s) {\r\n // calculate the xMirrorgate Fee.\r\n s.protocolFee = _amountSD.mul(protocolFeeBP).div(BP_DENOMINATOR);\r\n // calculate the LP fee. booked at remote\r\n s.lpFee = _amountSD.mul(lpFeeBP).div(BP_DENOMINATOR);\r\n // calculate the equilibrium Fee and reward\r\n s.eqFee = _amountSD.mul(eqFeeBP).div(BP_DENOMINATOR);\r\n s.eqReward = _amountSD.mul(eqRewardBP).div(BP_DENOMINATOR);\r\n return s;\r\n }\r\n\r\n function setFees(\r\n uint256 _lpFeeBP,\r\n uint256 _protocolFeeBP,\r\n uint256 _eqFeeBP,\r\n uint256 _eqRewardBP\r\n ) external onlyOwner {\r\n require(_lpFeeBP.add(_protocolFeeBP).add(_eqFeeBP).add(_eqRewardBP) <= BP_DENOMINATOR, \"FeeLibrary: sum fees > 100%\");\r\n require(eqRewardBP <= eqFeeBP, \"FeeLibrary: eq fee param incorrect\");\r\n lpFeeBP = _lpFeeBP;\r\n protocolFeeBP = _protocolFeeBP;\r\n eqFeeBP = _eqFeeBP;\r\n eqRewardBP = _eqRewardBP;\r\n emit FeesUpdated(lpFeeBP, protocolFeeBP);\r\n }\r\n\r\n function getVersion() external pure override returns (string memory) {\r\n return \"1.0.0\";\r\n }\r\n}\r\n"
  99. }
  100. },
  101. "settings": {
  102. "optimizer": {
  103. "enabled": true,
  104. "runs": 200
  105. },
  106. "outputSelection": {
  107. "*": {
  108. "*": [
  109. "abi",
  110. "evm.bytecode",
  111. "evm.deployedBytecode",
  112. "evm.methodIdentifiers",
  113. "metadata",
  114. "devdoc",
  115. "userdoc",
  116. "storageLayout",
  117. "evm.gasEstimates",
  118. "devdoc",
  119. "userdoc"
  120. ],
  121. "": [
  122. "ast"
  123. ]
  124. }
  125. },
  126. "metadata": {
  127. "useLiteralContent": true
  128. }
  129. }
  130. }